智能散热系统课程设计报告.docx
《智能散热系统课程设计报告.docx》由会员分享,可在线阅读,更多相关《智能散热系统课程设计报告.docx(33页珍藏版)》请在冰豆网上搜索。
![智能散热系统课程设计报告.docx](https://file1.bdocx.com/fileroot1/2023-2/25/19e98533-72c0-412b-b142-4a1e08c69fc8/19e98533-72c0-412b-b142-4a1e08c69fc81.gif)
智能散热系统课程设计报告
《单片机原理及接口》
课程设计报告
题目:
智能散热系统
专业名称:
通信工程
班级:
创新142
学号:
201411403128
姓名:
刘小杰
2015年12月
课程设计报告首页
院、系(部)
信息工程学院
专业
通信工程
班级
创新142
学号
201411403128
姓名
刘小杰
任课教师
陈玮
课程名称
单片机原理及接口
成绩
评
语
签字:
年月日
复
核
人
意
见
签字:
年月日
课程设计报告的要求:
首先应先介绍课程设计的基本内容(包括设计目标)、设计的背景及意义。
其次是方案论证:
说明设计的原理并进行方案选择,再然后进行硬件电路的设计及原理说明,和软件的流程说明。
第三是过程(设计或实验)论述:
对设计调试工作的详细表述。
最后是结论或总结:
对整个研究工作进行归纳和综合、包括心得体会。
大致内容按上面要求来写,也可以参考网上“单片机课程设计报告”来扩充。
文章中的格式规定:
图:
图的名称采用中文,图名在图片下面格式为:
图1-1,后接图名。
表格:
表名在表格上面。
正文五号字
一级标题四号加粗
二级标题小四加粗
行距:
1.5倍
附录的程序:
两列
页边距:
上下2.5厘米左右2.8厘米
不要目录
需要中文摘要排版参考毕业设计论文格式(见下页)
参考文献若有可写
打印的报告里面不需要附录程序电子版里面需要
报告里面应该有各模块电路图调试现象图
刻盘要求:
最后,除了打印的,全班把每个人的程序(keil项目及hex文件)、电路(proteus文件或硬件的照片及电路原理图)和报告打包压缩后命名为“班级名-学号-姓名”(如电信091-123456-陈玮)刻盘。
散热系统
刘小杰
信息工程学院
摘要:
由于单片机体积小、成本低、使用方便,所以被广泛地应用于仪器仪表、现场数据的采集和控制。
通过本次课程设计掌握单片机硬件和软件方面的知识,更深入的了解单片机的实际应用。
关键词:
单片机,程序,DS18B20温度传感器,LCD1602液晶显示屏,定时器,直流电机等等
1课程设计的基本内容
为实现系统能采集当前环境温度,当温度达到一定值时触发直流风扇的转动进行主动散热,并且随着温度的变化而改变风力大小,风力与温度成正比,本系统设置了三个档来控制风力的大小,20C°--22C°为一档,22C°--24C°为二档,24C°--26C°为三档(为了演示方便而设计的三档,在实际用途中可依据要求来设置)。
本智能散热系统根据环境温度智能调控风力的功能可以放置在一些硬件中以达到降温的功能。
2方案论证
2.1设计原理及方案选择
通过DS18B20温度传感器来采集当前环境的温度,通过LCD1602液晶显示屏来显示温度以及工作时间,CPU根据当前温度来控制电机的速度。
2.2硬件电路设计及原理说明
使用P1.1口来连接电机,P0口连接LCD1602,P2.5口为读/写选择端,P2.6为命令/数据选择端,P2.7为使能端,P3.7口为数据总线,P3.4口为定时器0,P3.5为定时器1.
图为DS18B20原理图
图为LCD1602原理图
图为外部电路接线图
3设计过程论述
3.1DS18B20温度传感器
DS18b20采用单总线的结构,单总线的特点就是只有一根数据线,系统中的数据交换都由这根线进行。
DS18B20的一线工作协议流程是:
初始化→ROM操作指令→存储器操作指令→数据传输。
其工作时序包括:
1、初始化时序
2、写时序
3、读时序
DS18B20的初始化
主机首先发出一个480-960微秒的低电平脉冲,然后释放总线变为高电平,并在随后的480微秒时间内对总线进行检测,如果有低电平出现说明总线上有器件已做出应答。
若无低电平出现一直都是高电平说明总线上无器件应答。
做为从器件的DS18B20在一上电后就一直在检测总线上是否有480-960微秒的低电平出现,如果有,在总线转为高电平后等待15-60微秒后将总线电平拉低60-240微秒做出响应存在脉冲,告诉主机本器件已做好准备。
若没有检测到就一直在检测等待
初始化时序图
初始化程序
unsignedcharDs18b20Init()
{
unsignedinti;
DSIO=0;//将总线拉低480us~960us
i=70;
while(i--);//延时642us
DSIO=1;//然后拉高总线,若DS18B20做出反应会将在15us~60us后将总线拉低
i=0;
while(DSIO)//等待DS18B20拉低总线
{
i++;
if(i>50000)//等待>50MS
return0;//初始化失败
}
return1;//初始化成功
}
主机发出各种操作命令都是向DS18B20写0和写1组成的命令字节,接收数据时也是从DS18B20读取0或1的过程。
写周期最少为60微秒,最长不超过120微秒。
写周期一开始做为主机先把总线拉低1微秒表示写周期开始。
随后若主机想写0,则将总线置为低电平,若主机想写1,则将总线置为高电平,持续时间最少60微秒直至写周期结束,然后释放总线为高电平至少1微秒给总线恢复。
而DS18B20则在检测到总线被拉底后等待15微秒然后从15us到45us开始对总线采样,在采样期内总线为高电平则为1,若采样期内总线为低电平则为0。
写操作时序图
向DS18B20写入一个字节
voidDs18b20WriteByte(unsignedchardat)
{
unsignedinti,j;
for(j=0;j<8;j++)
{
DSIO=0;//每写入一位数据之前先把总线拉低1us
i++;
DSIO=dat&0x01;//然后写入一个数据,从最低位开始
i=6;
while(i--);//延时68us,持续时间最少60us
DSIO=1;//然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值
dat>>=1;
}
}
读周期是从主机把单总线拉低1微秒之后就得释放单总线为高电平,以让DS18B20把数据传输到单总线上。
作为从机DS18B20在检测到总线被拉低1微秒后,便开始送出数据,若是要送出0就把总线拉为低电平直到读周期结束。
若要送出1则释放总线为高电平。
主机在一开始拉低总线1微秒后释放总线,然后在包括前面的拉低总线电平1微秒在内的15微秒时间内完成对总线进行采样检测,采样期内总线为低电平则确认为0。
采样期内总线为高电平则确认为1。
完成一个读时序过程,至少需要60微秒才能完成
读操作时序图
读取一个字节
unsignedcharDs18b20ReadByte()
{
unsignedcharbyte,bi;
unsignedinti,j;
for(j=8;j>0;j--)
{
DSIO=0;//先将总线拉低1us
i++;
DSIO=1;//然后释放总线
i++;
i++;//延时6us等待数据稳定
bi=DSIO;//读取数据,从最高位开始读取
byte=(byte>>1)|(bi<<7);/*将byte右移一位,然后或上左移7位后的bi,注意移动之后移掉那位补0。
*/
i=4;//读取完之后等待48us再接着读取下一个数
while(i--);
}
returnbyte;
}
DS18B20内部结构主要由四部分组成:
64位光刻ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。
光刻ROM中的64位序列号是出厂前被光刻好的,它可以看作是该DS18B20的地址序列码。
64位光刻ROM的排列是:
开始8位(地址:
28H)是产品类型标号,接着的48位是该DS18B20自身的序列号,并且每个DS18B20的序列号都不相同,因此它可以看作是该DS18B20的地址序列码;最后8位则是前面56位的循环冗余校验码(CRC=X8+X5+X4+1)。
由于每一个DS18B20的ROM数据都各不相同,因此微控制器就可以通过单总线对多个DS18B20进行寻址,从而实现一根总线上挂接多个DS18B20的目的。
DS18B20的存储器由一个高速暂存RAM和一个非易失性、电可擦除(E2)RAM组成。
DS18B20经转换所得的温度值以二字节补码形式存放在高速暂存存储器的第0和第1个字节。
所以当我们只想简单的读取温度值的时候,只用读取暂存器中的第0和第1个字节就可以了。
简单的读取温度值的步骤如下:
1、跳过ROM操作
2、发送温度转换命令
3、跳过ROM操作
4、发送读取温度命令
5、读取温度值
开始转换温度
voidDs18b20ChangTemp()
{
Ds18b20Init();
Delay1ms
(1);
Ds18b20WriteByte(0xcc);//跳过ROM操作命令
Ds18b20WriteByte(0x44);//温度转换命令
Delay1ms(100);
}
发送读取温度命令
voidDs18b20ReadTempCom()
{
Ds18b20Init();
Delay1ms
(1);
Ds18b20WriteByte(0xcc);//跳过ROM操作命令
Ds18b20WriteByte(0xbe);//发送读取温度命令
}
读取温度
intDs18b20ReadTemp()
{
unsignedinttemp=0;
unsignedchartmh,tml;
Ds18b20ChangTemp();//先写入转换命令
Ds18b20ReadTempCom();//然后等待转换完后发送读取温度命令
tml=Ds18b20ReadByte();//读取温度值共16位,先读低字节
tmh=Ds18b20ReadByte();//再读高字节
temp=tmh;
temp<<=8;
temp|=tml;
returntemp;
}3.2LCD1602液晶显示屏
LCD1602的引脚
操作步骤:
1、初始化
2、写命令(RS=L)设置显示坐标
3、写数据(RS=H)
写入一个字节命令
voidLcdWriteCom(unsignedcharcom)//写入命令
{
RS=0;
RW=0;
GPIO_LCD=com;
Delay1ms(10);
LCDE=1;
Delay1ms(10);
LCDE=0;
}
写入一个字节数据
voidLcdWriteData(unsignedchardat)//写入数据
{
RS=1;
RW=0;
GPIO_LCD=dat;
Delay1ms(10);
LCDE=1;
Delay1ms(10);
LCDE=0;
}
初始化
voidLcdInit()//LCD初始化子程序
{
LcdWriteCom(0x38);//设置显示模式
LcdWriteCom(0x0c);//开显示不显示光标,光标不闪烁
LcdWriteCom(0x06);//写一个指针加1
LcdWriteCom(0x01);//清屏
LcdWriteCom(0x80);//设置数据指针起点
}
1602的指令码
DL:
0时:
选择4位数据总线模式。
1时:
选择8位数据总线模式。
N:
0时:
选择显示一行。
1时:
选择显示两行。
F:
0选择5*7模式,1选择5*10模式。
一般只有5*7模式。
显示开/关及按键显示
RAM地址映射图
3.3编程调试过程出现的问题
当控制电机速度的程序放在定时器1的中断中则会导致液晶显示屏出现闪烁,这是因为每中断一次就进入中断程序,则读取温度的程序就没有运行,所欲显示就会出错,而当控制电机的程序放在主程序中,则电机的速度则无法控制,只有转或不转。
这个问题无法突破就无法实现调节风力大小以及正确显示温度的功能,尝试了多种办法后发现在读取温度的时候先将定时器关闭,读取温度结束后就开启定时器。
4、程序清单
#include
voidTime1Config();
/*相关字符的重定义*/
#defineucharunsignedchar
#defineuintunsignedint
#defineLCD1602_DATAPINSP0
sbitLCD1602_E=P2^7;//定义P2.7口为使能端
sbitLCD1602_RW=P2^5;//定义P2.5口为读/写选择端(H/L)
sbitLCD1602_RS=P2^6;//定义P2.6口为数据/命令选择端(H/L)
sbitDSPORT=P3^7;//定义P3.7口为总线
sbitPWM=P1^1;//定义P1.1为电机电压输出端
/*定义一些相关变量*/
unsignedchartimer1;
floattp;
inttemp,speed;
unsignedchartable[]={'0','1','2','3','4','5','6','7','8','9'};
inti1=0,n1=0,j1=0,a1,k1=0,m1=0,flag=0,o1=0,p1=0,z1=0;
/*LCD1602延时函数*/
voidLcd1602_Delay1ms(uintc)//误差0us
{
uchara,b;
for(;c>0;c--)
{
for(b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
/*向LCD1602写入一个字节命令*/
voidLcdWriteCom(ucharcom)//写入命令
{
LCD1602_E=0;//使能
LCD1602_RS=0;//选择发送命令
LCD1602_RW=0;//选择写入
LCD1602_DATAPINS=com;//放入命令
Lcd1602_Delay1ms
(1);//等待数据稳定
LCD1602_E=1;//写入时序
Lcd1602_Delay1ms(5);//保持时间
LCD1602_E=0;
}
/*向LCD1602写入一个字节数据*/
voidLcdWriteData(uchardat)//写入数据
{
LCD1602_E=0;//使能清零
LCD1602_RS=1;//选择输入数据
LCD1602_RW=0;//选择写入
LCD1602_DATAPINS=dat;//写入数据
Lcd1602_Delay1ms
(1);
LCD1602_E=1;//写入时序
Lcd1602_Delay1ms(5);//保持时间
LCD1602_E=0;
}
/*初始化LCD屏*/
voidLcdInit()//LCD初始化子程序
{
LcdWriteCom(0x38);//开显示
LcdWriteCom(0x0c);//开显示不显示光标
LcdWriteCom(0x06);//写一个指针加1
LcdWriteCom(0x01);//清屏
LcdWriteCom(0x80);//设置数据指针起点
}
/*DS18B20的延时函数*/
voidDelay1ms(uinty)
{
uintx;
for(;y>0;y--)
{
for(x=110;x>0;x--);
}
}
/*DS18B20的初始化*/
ucharDs18b20Init()
{
uchari;
DSPORT=0;//将总线拉低480us~960us
i=70;
while(i--);//延时642us
DSPORT=1;//然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
i=0;
while(DSPORT)//等待DS18B20拉低总线
{
i++;
if(i>5)//等待>5MS
{
return0;//初始化失败
}
Delay1ms
(1);
}
return1;//初始化成功
}
/*向DS18B20写入一个字节*/
voidDs18b20WriteByte(uchardat)
{
uinti,j;
for(j=0;j<8;j++)
{
DSPORT=0;//每写入一位数据之前先把总线拉低1us
i++;
DSPORT=dat&0x01;//然后写入一个数据,从最低位开始
i=6;
while(i--);//延时68us,持续时间最少60us
DSPORT=1;//然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值
dat>>=1;
}
}
/*读取一个字节*/
ucharDs18b20ReadByte()
{
ucharbyte,bi;
uinti,j;
for(j=8;j>0;j--)
{
DSPORT=0;//先将总线拉低1us
i++;
DSPORT=1;//然后释放总线
i++;
i++;//延时6us等待数据稳定
bi=DSPORT;//读取数据,从最高位开始读取
/*将byte右移一位,然后与上左移7位后的bi,注意移动之后移掉那位补0。
*/
byte=(byte>>1)|(bi<<7);
i=4;//读取完之后等待48us再接着读取下一个数
while(i--);
}
returnbyte;
}
/*开始转换温度*/
voidDs18b20ChangTemp()
{
Ds18b20Init();
Delay1ms
(1);
Ds18b20WriteByte(0xcc);//跳过ROM操作命令
Ds18b20WriteByte(0x44);//温度转换命令
//Delay1ms(100);//等待转换成功,而如果你是一直刷着的话,就不用这个延时了
}
/*发送读取温度命令*/
voidDs18b20ReadTempCom()
{
Ds18b20Init();
Delay1ms
(1);
Ds18b20WriteByte(0xcc);//跳过ROM操作命令
Ds18b20WriteByte(0xbe);//发送读取温度命令
}
/*读取温度*/
intDs18b20ReadTemp()
{
inttemp=0;
uchartmh,tml;
TR1=0;
Ds18b20ChangTemp();//先写入转换命令
Ds18b20ReadTempCom();//然后等待转换完后发送读取温度命令
tml=Ds18b20ReadByte();//读取温度值共16位,先读低字节
tmh=Ds18b20ReadByte();//再读高字节
temp=tmh;
temp<<=8;
temp|=tml;
TR1=1;
returntemp;
}
/*定时器1的中断函数*/
voidTime1(void)interrupt3
{
TH1=0xfe;
TL1=0x0c;
timer1++;
if(timer1>100)//PWM周期为100*0.5ms
timer1=0;
if(timer1PWM=1;
else
PWM=0;
}
/*设置定时器1*/
voidTime1Config()
{
TMOD|=0x10;//设置定时计数器工作方式1为定时器
//--定时器赋初始值,12MHZ下定时0.5ms--//
TH1=0xfe;
TL1=0x0c;
ET1=1;//开启定时器1中断
EA=1;
TR1=1;//开启定时器
}
/*LCD显示读取到的温度*/
voidLcdDisplay(inttemp)//lcd显示
{
unsignedchardatas[]={0,0,0,0,0};//定义数组
if(temp<0)//当温度值为负数
{
LcdWriteCom(0xC1);//写地址80表示初始地址
LcdWriteData('-');//显示负
//因为读取的温度是实际温度的补码,所以减1,再取反求出原码
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算由?
.5,还是在小数点后面。
}
else
{
LcdWriteCom(0xC6);//写地址80表示初始地址
LcdWriteData('+');//显示正
tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
//如果温度是正的那么,那么正数的原码就是补码它本身
temp=tp*0.0625*100+0.5;
if(temp>=2000&&temp<=2200)
speed=30;
elseif(temp>=2200&&temp<=2400)
speed=50;
elseif(temp>2400)
speed=70;
else
speed=0;
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算加上0.5,还是在小数点后面。
}
datas[0]=temp/10000