基于单片机的散热器设计
计算机应用系统专题设计说明书
设计题目: 基于51单片机简易散热器
设计者姓名:
同组成员:(姓名[学号]):
自动化学院 2014年11月16日
一、系统设计小组工作分工
二.系统设计目标
三.系统方案设计 1.程序设计及调试
根据课程设计内容和要求,温度传感器采用DS18B20将温度信号传给STC89C52进行处理,之后送给138译码器进行译码,将译码结果送给共阴极数码管显示。并且同时检测温度值是否达到动作温度,散热风扇由直流电动机带动,达到动作温度时单片机给ULN2003发送信号驱动电机转动。
在Protues中进行电路的设计,用Keil软件编写散热器程序,并进行仿真模拟调试。
2.硬件焊接及调试
根据仿真电路图完成电路板的焊接,并且进行程序的烧写和调试,达到预期效果。
3. 单片机系统方框图
晶振电路
4. 器件选择
根据系统的设计目标,我们采用STC89C52芯片作为主控芯片。显示使用共阴极数码管,并且使用138译码器进行译码位选。温度采集我们使用DS18B20,因为它是一种直接将其温度信号转变为数字信号的温度传感器,不用使用A/D转换电路,使用方便电路简单。我们还是用ULN2003A芯片实现直流电动机的驱动,因为UNL2003A的工作电压为5V,在输入为高电平时可以实现最大输出电流500mA的电流输出驱动直流电机转动。另外晶振电路采用30pf电容两个,12M晶振一个,数码管上拉电阻采用200Ω电阻八个,电机限流电阻51Ω一个。
主要器件介绍: (1)DS18B20温度传感器
DS18B20数字温度计提供9位温读数,指示器件温度。信息经过单线接口送入DS18B20或送出,因此从DS18B20到中央处理器仅需连接一条,读、写和完成温度转换的电源可由数据线本身提供,而不需要外部电源。
DS18B20温
度采集电路
52单片机系统
电机驱动电路
译码位选电路
数码管显示电路
右图为引脚图 引脚说明:GND 地
DQ 数字输入输出 VDD 可选的VDD NC 空引脚 DNC 不连接
(2)74LS138译码器
74LS138的管脚排列和真值表见下图。由真值表可知,4、5、6脚是控制脚,只有当6脚为高电平而4、5脚都为低电平时,74LS138才对1、2、3脚的输入进行译码,选择和从这三个管脚输入的三位二进制码相对应的某一个输出脚输出低电平,否则所有的输出脚都是输出高电平。引脚及真值表如下。
(3)ULN2003A电机驱动芯片
ULN2003A是一个7路反向器电路,即当输入端为高电平时ULN2003A输出端为低电平,当输入端为低电平时ULN2003A输出端为高电平。也可以作为一些器件,如步进电机的驱动电路。如右图所示。
四.硬件电路设计及描述
1.晶振电路采用的是12M晶振,如图1所示。
图1 2.数码管显示电路
数码管的八位数据接口与单片机的P0口相连。中间加200Ω的上拉电阻连接如图2。数码管的位选接口与138译码器的输出端Y2,Y3连接如图3所示。74LS138译码器的A B C三端分别与P2.2、P2.3、P2.4相连,E1接高电平,E2 E3同接高低电平
图2 图3
3. DS18B20温度传感器电路连接
DS18B20的数据接口与单片机的P3.7相连,VCC接5V电源,GND接地。如图4所示。
图
4
4. UNL2003A电机驱动电路
如图6所示。
UNL2003A的输入端1B接单片机的P2.6,COM端接VCC。输出端1C接直流电动机的一端。电动机的另一端接电源。
图6
五.软件设计及描述
1、软件设计流程
程序首先进行初始化,对DS18B20温度传感器进行初始化然后进行温度读取,并通过端口P3.7将数据送给单片机进行处理。对温度值分别取十位和个位,通过P0口将十位和个位轮流送给数码管数据端。同时单片机的P2.2,P2.3,P2.4与138译码器连接通过译码进行数码管的位选,实现温度显示。单片机通过温度值与动作温度比较,当温度高与动作温度时通过单片机的P2.6给UNL2003A发送信号实现直流电动机的驱动。从而达到温度的显示和高温自动散热的效果。
2、系统总流程图
3、源程序代码
#include #include
sbit D18B20=P3^7;
#define NOP() _nop_() /* 定义空指令 */ #define _Nop() _nop_() /*定义空指令*/
void WriteByte (unsigned char idata wr); //单字节写入 void read_bytes (unsigned char idata j); unsigned char CRC (unsigned char j); void GetTemp (void); void Config18b20 (void); void ReadID (void);
void TemperatuerResult(void);
bit flag;
unsigned int idata Temperature;
unsigned char idata temp_buff[9]; //存储读取的字节,read scratchpad为9字节,read rom ID为8字节
unsigned char idata id_buff[8]; unsigned char idata *p,TIM; unsigned char idata crc_data;
/*extern GetTemp(); //声明引用外部函数
extern unsigned int idata Temperature; // 声明引用外部变量 */
void delay(unsigned int i);
//else IO
sbit LS138A=P2^2; //管脚定义 sbit LS138B=P2^3; sbit LS138C=P2^4; sbit pwm=P2^7;
//此表为 LED 的字模, 共阴数码管 0-9 - unsigned char code Disp_Tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};
unsigned char code CrcTable [256]={0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,70, 24, 250, 164, 39, 121, 155,
197, 132, 218, 56, 102, 229, 187, 89, 7,219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
unsigned long LedOut[5],LedNumVal; void PWM(void);
void system_Ini() {
TMOD|= 0x11;
TH1 = 0xD8; //10 TL1 = 0xF0; IE = 0x8A; TR1 = 1; }
main()
{ unsigned char i; system_Ini(); while(1) {
GetTemp(); /********以下将读18b20的数据送到LED数码管显示*************/ LedNumVal=Temperature; //把实际温度送到LedNumVal变量中 LedOut[0]=Disp_Tab[LedNumVal%10000/1000]; LedOut[1]=Disp_Tab[LedNumVal%1000/100];
LedOut[2]=Disp_Tab[LedNumVal%100/10]; //十位 LedOut[3]=Disp_Tab[LedNumVal%10]; //个位 switch(i) { //138译码
case 0:LS138A=0; LS138B=0; LS138C=0; break;
case 1:LS138A=1; LS138B=0; LS138C=0; break;
case 2:LS138A=0; LS138B=1; LS138C=0; break; case 3:LS138A=1; LS138B=1; LS138C=0; break; }
if(LedNumVal>25) {
pwm=1;}
else{pwm=0;} delay(40); }
P0 = 0; }
//延时程序
void delay(unsigned int i) {
char j;
for(i; i > 0; i--)
for(j = 200; j > 0; j--); }
void TempDelay (unsigned char idata us) {
while(us--); }
/************************************************************ *Function:18B20初始化 *parameter: *Return: *Modify:
*************************************************************/ void Init18b20 (void) {
D18B20=1; _nop_(); D18B20=0;
TempDelay(80); //delay 530 uS//80 _nop_(); D18B20=1;
TempDelay(14); //delay 100 uS//14
_nop_();
_nop_();
_nop_();
if(D18B20==0)
flag = 1; //detect 1820 success!
else
flag = 0; //detect 1820 fail!
TempDelay(20); //20
_nop_();
_nop_();
D18B20 = 1;
}
/************************************************************ *Function:向18B20写入一个字节
*parameter:
*Return:
*Modify:
*************************************************************/ void WriteByte (unsigned char idata wr) //单字节写入
{
unsigned char idata i;
for (i=0;i
{
D18B20 = 0;
_nop_();
D18B20=wr&0x01;
TempDelay(3); //delay 45 uS //5
_nop_();
_nop_();
D18B20=1;
wr >>= 1;
}
}
/************************************************************ *Function:读18B20的一个字节
*parameter:
*Return:
*Modify:
*************************************************************/ unsigned char ReadByte (void) //读取单字节
{
unsigned char idata i,u=0;
for(i=0;i
{
D18B20 = 0;
u >>= 1;
D18B20 = 1;
if(D18B20==1)
u |= 0x80;
TempDelay (2);
_nop_();
}
return(u);
}
/************************************************************ *Function:读18B20
*parameter:
*Return:
*Modify:
*************************************************************/ void read_bytes (unsigned char idata j)
{
unsigned char idata i;
for(i=0;i
{
*p = ReadByte();
p++;
}
}
/************************************************************ *Function:CRC校验
*parameter:
*Return:
*Modify:
*************************************************************/ unsigned char CRC (unsigned char j)
{
unsigned char idata i,crc_data=0;
for(i=0;i
crc_data = CrcTable[crc_data^temp_buff[i]];
return (crc_data);
}
/************************************************************ *Function:读取温度
*parameter:
*Return:
*Modify:
*************************************************************/ void GemTemp (void)
{
read_bytes (9);
if (CRC(9)==0) //校验正确
{
Temperature = temp_buff[1]*0x100 + temp_buff[0];
// Temperature *= 0.625;
Temperature /= 16;
TempDelay(1);
}
}
/************************************************************ *Function:内部配置
*parameter:
*Return:
*Modify:
*************************************************************/ void Config18b20 (void) //重新配置报警限定值和分辨率
{
Init18b20();
WriteByte(0xcc); //skip rom
WriteByte(0x4e); //write scratchpad
WriteByte(0x19); //上限
WriteByte(0x1a); //下限
WriteByte(0x7f); //set 12 bit (0.125)
Init18b20();
WriteByte(0xcc); //skip rom
WriteByte(0x48); //保存设定值
Init18b20();
WriteByte(0xcc); //skip rom
WriteByte(0xb8); //回调设定值
}
/************************************************************ *Function:读18B20ID
*parameter:
*Return:
*Modify:
*************************************************************/ void ReadID (void)//读取器件 id
{
Init18b20();
WriteByte(0x33); //read rom
read_bytes(8);
}
/************************************************************ *Function:18B20ID全处理
*parameter:
*Return:
*Modify:
*************************************************************/ void TemperatuerResult(void)
{
p = id_buff;
ReadID();
Config18b20();
Init18b20 ();
WriteByte(0xcc); //skip rom
WriteByte(0x44); //Temperature convert
Init18b20 ();
WriteByte(0xcc); //skip rom
WriteByte(0xbe); //read Temperature
p = temp_buff;
GemTemp();
}
void GetTemp()
{
if(TIM==100) //每隔 1000ms 读取温度
{ TIM=0;
TemperatuerResult();
}
}
/*************************************
[ t1 (10ms)中断] 中断
*************************************/
void T1zd(void) interrupt 3
{
TH1 = 0xD8; //10
TL1 = 0xF0;
TIM++;
}
六.设计调试过程及结果
1. 电脑上仿真调试
利用Keil编写主程序,通过编译生成hex文件,再通过Protues对程序进行仿真,得到所预期的结果如图7所示。
图7 Keil软件编译
在Protues上仿真调试计算的效果图如下所示
2. 实物调试
将hex文件烧写进51单片机里,得到所预期结果,如图11所示。
七.系统设计体会
1、遇到的问题及解决方案:
(1)在进行实物调试时,当温度到达动作温度时电动机只转动一下,不能持续转动。通过查阅资料和多次试验发现,在电动机两端并联一个电容可以解决这个问题,电容可以通交流隔直流的作用,把电动机旋转时产生的交流回馈电流在电容中消耗使它不会影响到其它电路,使电动机能持续获得电流转动。
(2)在实际温度显示电路中开始时数码管不能明显显示,亮度很低。经过试验我们将10kΩ的上拉电阻改为200Ω的电阻,数码管显示亮度明显提高得到解决。
2、收获与体会
宋晓彤:
通过这次课程设计我学到了很多有关单片机的知识,并且将书中的知识通过实践也发现了很多细节上的东西,例如在电动机两端并联一个大小适合的电容可以消除电动机旋转时的交流回馈电流,防止回馈电流影响电路。并且在软件编辑中我也学到了很多知识,让我更加了解了一些函数的使用和规则,使我对C语言软件编辑有了更多的经验,能力也得到了一些提高。中间有很多次编译出错,经过多次的修改和查阅函数使用规则终于修改正确并且最终编译成功。另外通过课程设计我也对一些其它外围扩展芯片有了更深刻的了解,例如UNL2003的电流驱动芯片可以实现最大输出电流500mA的输出电流,同样对DS18B20的使用和初始化也有了更深入的了解。
王鑫:
这次对主板的焊接让我意识到自己的动手能力还有很大的不足,需要对着电路图摆放元器件,并且需要一边对照图一边焊接电路,而无法在看完电路图后流畅的完成电路的焊接。在连接完电路后发生了短路现象,经过排查后用透明胶带解决了问题,焊接数码管的时候发现提供的与实际不一样,使用电笔逐一测试后找出了一一对应的引脚并准确完成了焊接。经过这次焊接过程中的失误以及手忙脚乱的焊接后意识到自己对焊接操作的浅显的认知和轻视,对电路图的识别和认知还有待提高,对元器件的焊接的熟悉程度还远远不够,需要多加练习焊接操作提高自己的熟练度。
谢慧龙:
从一开始构思,编写程序,绘制电路图,仿真调试,焊接实物,到最后显示屏显示成功,我学到了很多东西,当出现问题时不要着急,仔细检查是否接地,焊接有没有错误,程序有没有编错,需要我的耐心和热情,这次设计增加了我实践能力和动手能力。
除此之外,无论是在单片机理论方面还是电子器件焊接方面我都取得了很大的进步,然后对它进行了调试,写了一个小程序,把程序下载到单片机里,一下就成功了,我真的很开心,通过这次实践,我不仅加深了对单片机理论的了解,将理论很好的应用到实践中去,在接下来的学习中,我会更加努力的!
八.参考文献
[1] 郭天祥,51单片机C语言教程,电子工业出版社
[2] 张齐,单片机系统设计与开发,机械工业出版社
[3]朱月秀,单片机原理与应用(第二版).北京:科学出版社