恒温控制器系统概述
该恒温控制器系统包含以下几个功能:
- 可按键设定温度
- 可显示当前温度和用户设定温度
- 有升温、降温模块
- 可最终达到恒温
仿真软件
- Keil 5
- Proteus 8.6
系统设计
电路设计
恒温控制系统一共有6个模块,分别是主控芯片模块、按键输入模块、设定温度显示模块、当前温度显示模块、温度采集模块和升温、降温模块。
- 按键输入模块:该模块由4*3的矩阵键盘和1个确认按钮构成。系统刚开始启动后,用户通过矩阵键盘输入想要设定的温度(0°~99°),输入完毕后按下确认键,然后将该温度数据传送给主控芯片AT89C51;
- 设定温度显示模块:该模块由一个2位8段LED数码管构成,主控芯片AT89C51使用P3口控制该数码管的段选,使用P2.4和P2.5两个端口来控制该数码管的位选。主控芯片AT89C51将从矩阵键盘得到的设定温度信息,通过2位8段LED数码管显示出来;
- 温度采集模块;该模块由一个DS18B20温度传感器构成。使用DS18B20温度传感器采集当前的温度,并将该温度信息传送给主控芯片AT89C51;
- 当前温度显示模块:该模块由两个74HC573锁存器和一个4位8段LED数码管构成,主控芯片AT89C51使用P2.6和P2.7控制两个74HC573锁存器的片选,两个锁存器的输入口均与主控芯片的P0口相连,并使用一个100欧的排阻作为P0口的上拉电阻,两个锁存器的输出口分别与4位8段LED数码管的段选口与位选口相连;
- 升温、降温模块:该模块由一个绿色LED和一个红色LED构成,绿色LED负责降温,每闪烁一次温度下降0.5°,红色LED负责升温,每闪烁一次温度上升0.5°。主控芯片AT89C51根据当前温度和用户设定温度之间的差值,来控制升温还是降温,以达到恒温的目的。
软件代码编写
程序的具体流程如下:
- 硬件初始化,关闭所有的数码管;
- 进行两次按键扫描循环,分别获取用户设定温度的十位和个位,获取完毕后,判断确认键是否被按下,如果用户按下确认键则进入到主程序循环中;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | while (ok) //用户设定温度 { while (key1 == 15) { key1 = keyscan(); delay(50); } while (key2 == 15) { key2 = keyscan(); delay(50); } delay(100); //等待确认键 } //键盘扫描 uchar keyscan() { uchar temp,key; key = 15; // 默认值,如果没有按键按下key就为该默认值 P1 = 0xfe; //扫描第一行 temp = P1; temp = temp & 0xf0; if (temp!=0xf0) { delay(10); // 延时消抖 temp = P1; temp = temp & 0xf0; if (temp!=0xf0) { temp = P1; switch (temp) //扫描列 { case 0xee: key = 1; break ; case 0xde: key = 2; break ; case 0xbe: key = 3; break ; } while (temp!=0xf0) //等待按键释放 { temp = P1; temp = temp & 0xf0; } } } P1 = 0xfd; //扫描第二行 temp = P1; temp = temp & 0xf0; if (temp!=0xf0) { delay(10); // 延时消抖 temp = P1; temp = temp & 0xf0; if (temp!=0xf0) { temp = P1; switch (temp) //扫描列 { case 0xed: key = 4; break ; case 0xdd: key = 5; break ; case 0xbd: key = 6; break ; } while (temp!=0xf0) //等待按键释放 { temp = P1; temp = temp & 0xf0; } } } P1 = 0xfb; //扫描第三行 temp = P1; temp = temp & 0xf0; if (temp!=0xf0) { delay(10); // 延时消抖 temp = P1; temp = temp & 0xf0; if (temp!=0xf0) { temp = P1; switch (temp) //扫描列 { case 0xeb: key = 7; break ; case 0xdb: key = 8; break ; case 0xbb: key = 9; break ; } while (temp!=0xf0) //等待按键释放 { temp = P1; temp = temp & 0xf0; } } } P1 = 0xf7; //扫描第四行 temp = P1; temp = temp & 0xf0; if (temp!=0xf0) { delay(10); // 延时消抖 temp = P1; temp = temp & 0xf0; if (temp!=0xf0) { temp = P1; switch (temp) //扫描列 { case 0xe7: key = 0; break ; case 0xd7: key = 0; break ; case 0xb7: key = 0; break ; } while (temp!=0xf0) //等待按键释放 { temp = P1; temp = temp & 0xf0; } } } return key; } |
- 在主程序循环中,首先调用dis_set()函数显示用户设定温度;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | for (i=20;i>0;i--) dis_set(key1, key2); //显示用户设定的温度 //显示设定温度函数 void dis_set(uchar k1, uchar k2) { display2(1, k1); display2(2, k2); display2(0, k1); } //设定温度数据显示函数 void display2(uchar num, uchar tem_data) { if (num==0) { S1 = 1; S2 = 1; delay(5); } if (num==1) { S1 = 0; S2 = 1; P3 = table[tem_data]; //table为 0-9的16进制编码表 delay(5); } else if (num==2) { S1 = 1; S2 = 0; P3 = table[tem_data]; delay(5); } } |
然后再从温度传感器获取当前温度,获取当前温度的流程如下图所示,先调用DSreset()函数进行温度传感器的初始化,再调用temwrite()函数,对传感器写入温度转换的指令,进行温度获取和转换,然后调用get_tem()函数对传感器写入读取寄存器指令,从寄存器中读取存储的温度数据,并对该数据进行精度转换处理,最后获得一个保留了1位小数的当前温度数据;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | temchange(); //获取当前温度 //温度获取和转换函数 void temchange( void ) { DSreset(); delay(1); temwrite(0xcc); //写跳过ROM指令 temwrite(0x44); //写温度转换指令 } //读取寄存器中存储的温度数据 uint get_tem( void ) { uchar l8,h8; DSreset(); delay(1); temwrite(0xcc); //写跳过ROM指令 temwrite(0xbe); //写读寄存器指令 l8 = temread(); //读低8位数据 h8 = temread(); //读高8位数据 tem = h8; tem = tem<<8; tem = tem|l8; //合成一个16位数据 f_tem = tem*0.0625; tem = f_tem*10+0.5; //*10用于保留1位小数点,+0.5用于四舍五入 return (tem); } |
DS18B20温度传感器的基本操作代码如下,各项操作要严格遵守DS18B20温度传感器的时序图,延时时间要足够,可以根据使用的主控芯片适当地修改循环的次数来调整延时。
初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //温度传感器初始化 uint DSreset( void ) { uint i; DS = 0; i = 73; while (i>0) i--; DS = 1; i = 0; while (DS) { //等待DS18B20拉低总线 delay(1); i++; if (i>10) { return 0; //初始化失败 } } DS = 1; return 1; //初始化成功 } |
读1位数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //读1位数据 bit temreadbit( void ) { uint i; bit tem_bitdata; DS = 0; i++; //延时 DS = 1; i++; i++; tem_bitdata = DS; i = 10; while (i>0) i--; return (tem_bitdata); } |
读1字节数据
1 2 3 4 5 6 7 8 9 10 11 12 | //读1字节数据 uchar temread( void ) { uint i; uchar j,tem_data; for (i=1;i<=8;i++) { j = temreadbit(); tem_data = (j<<7)|(tem_data>>1); //移位,让最低位在最后面 } return (tem_data); } |
写1字节数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | //写1字节数据 void temwrite(uchar tem_data) { uint i; uchar j; bit send_bitdata; for (j=1;j<=8;j++) { send_bitdata = tem_data&0x01; //取要发送数据的最低位 tem_data = tem_data>>1; //右移一位 if (send_bitdata) //写1 { DS = 0; i++; i++; DS = 1; i = 10; while (i>0) i--; } else //写0 { DS = 0; i = 10; while (i>0) i--; DS = 1; i++; i++; } } } |
- 获取完当前温度,调用dis_tem()函数显示当前温度;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | for (i=20;i>0;i--) //显示当前温度 dis_tem(get_tem()); //显示当前温度函数 void dis_tem(uint t) { uchar i; i = t/100; //取温度的十位 display1(1,i); i = t%100/10; //取温度的个位 display1(2,i+10); i = t%10; //取温度的小数点后一位 display1(3,i); } //当前温度数据显示函数 void display1(uchar num, uchar tem_data) { WE = 1; //选位,低电平有效 P0 = ~((0x01)<<(num)); WE = 0; DU = 1; //选段,高电平有效 P0 = table[tem_data]; DU = 0; delay(10); } |
- 将当前温度和用户设定温度传入deal()函数,进行恒温控制,在恒温控制函数deal()中,根据判断当前温度和用户设定温度之间的差值进行不同的处理,如果当前温度小于用户设定温度,就进行升温处理,即红灯闪烁一次,每闪烁一次温度上升0.5°,如果当前温度大于用户设定温度,就进行降温处理,即绿灯闪烁一次,每闪烁一次温度下降0.5°,如果当前温度与用户设定温度想等,则不做处理,只显示温度;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | void deal(uint t, uint t_set) { uchar i; if (t<t_set) if (t= "" else = "" }= "" 升温= "" 0x20);= "" work(15,= "" {= "" >t_set) { work(15, 0x40); //降温 } else { i = 15; while (i--) { dis_tem(tem_set); dis_set(key1, key2); } } } //升温、降温模块 void work(uint s, uchar led) { uchar i; if (led==0x20) { i = s; led0 = ~(led0); //灯亮 tem = tem+5; while (i--) { dis_tem(tem); dis_set(key1, key2); } led0 = ~(led0); //灯灭 i = s; while (i--) { dis_tem(tem); dis_set(key1, key2); } } else { i = s; led1 = ~(led1); //灯亮 tem = tem-5; while (i--) { dis_tem(tem); dis_set(key1, key2); } led1 = ~(led1); //灯灭 i = s; while (i--) { dis_tem(tem); dis_set(key1, key2); } } }</t_set)> |
- 进行一次恒温控制后,系统又回到主程序循环的起始点,不断重复上述3-5步骤,使温度保持在用户设定的温度,达到恒温的效果。
代码下载 51单片机恒温控制系统C语言程序代码
