找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 14009|回复: 21
打印 上一主题 下一主题
收起左侧

单片机+DS18B20+LCD1602温度检测,注释超级详细,适合新手。

  [复制链接]
跳转到指定楼层
楼主
单片机+DS18B20+LCD1602  温度检测,注释超级详细,适合新手。
需要的下载自取,解压后即可。包括C文件以及hex文件   晶振使用的是11.0592MHZ

  •   硬件电路设计
(1)复位电路设计
通过Vcc(+5V)电源给电容C充电,然后加给RST引脚一个短暂的高电平信号,此信号随着Vcc对电容C的充电过程而逐渐回落。RST引脚上的高电平大于复位要求的高电平时间。(电路中使用10千欧电阻,10微法电解电容),如图2所示。
图2 复位电路
(2)时钟电路设计
本设计采用内部时钟方式。AT89S52单片机内部有一个用于构成振荡器的高增益反相放大器,它的输入端为芯片引脚XTAL1,输出端为引脚XTAL2。这两个引脚外部跨接石英晶体振荡器和微调电容,构成一个稳定的自激振荡器。(电路中使用2个30皮法的瓷片电容,12MHZ晶振)如图3所示。

图3时钟电路
(3)温度测量电路设计
温度传感器采用美国DALLAS半导体公司生产的DS18B20,与传统的热敏电阻等测温元件相比,能够直接读出被测温度,硬件电路简单,单线接口,可通过数据线供电,电压范围在3.0V~5.5V。如图4所示。

图4温度测量电路
(4)显示电路设计
字符型液晶显示模块是一种专门用于显示字母、数字、版本号等的点阵式液晶显示模块。它是由若干个5×7或5×11等点阵符位组成的,第一个点阵字符位都可以显示一个字符。点阵字符位之间有一定点距的间隔,这样就起到了字符间距和行距的作用。本设计采用字符型液晶显示模块LCD1602。如图5如示。

图5LCD1602连线电路
                      图5液晶显示模块电路

(5)总体电路图

图6系统总体电路图
  •   软件程序设计(包括程序框图和参考程序)
(1)DS18B20显示温度模块需要调用4个子程序分别为
1.DS18B20初始化子程序,让单片机知道DS18B20在总线上已准备好操作;
2.DS18B20写字节子程序,对DS18B20发出命令;
3.DS18B20读字节子程序,读取DS18B20存储器的数据;
4.延时子程序,对DS18B20操作时的时序控制;


设计结果分析及心得体会
(1)结果分析
本次设计达到题目要求,能够利用DS18B20数字式温度传感器较准确测量周围环境的温度,并能通过字符型的显示模块LCD1602进行实时显示,并且掌握了DS18B20的单总线协议,如图16所示,使我们本次设计的实物图。

                           图16设计结果实物图
(2)心得体会
本系统完成设计的要求、测温较准确,作品性能好,具有一定的实际应用价值。该温度检测系统只是DS18B20在温度测量领域的一个简单实例,还有许多需要完善的地方。通过本次设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,才能提高自己的实际动手能力和独立思考的能力。同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固。总的来说,这次设计还是比较成功的,在设计中遇到了很多问题,最后在老师的辛勤的指导下,终于游刃而解,有点小小的成就感,终于觉得平时所学的知识有了实用的价值,达到了理论与实际相结合的目的,不仅学到了不少知识,而且锻炼了自己的能力。最后,对给过我帮助的所有同学和各位指导老师再次表示忠心的感谢。

单片机源程序如下:
  1. #include<reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. sbit DQ=P0^1; //ds18b20 与单片机连接口
  5. sbit RS=P1^0; //1602 写数据 / 写命令选择端口
  6. //RS=1 写数据,即要显示的内容
  7. //RS=0 写命令,即一些 LCD设置命令
  8. sbit RW=P1^1; //1602 读/ 写选择端, RW=0为写模式
  9. sbit EN=P1^2; // 给 EN一个高脉冲,将数据送入液晶控制器,完成写操作
  10. uchar code str1[]={"1503322615033211"};
  11. uchar code str2[]={"  T="};
  12. uchar data disdata[4];// 百、十、个、小数位
  13. uint tvalue; // 温度值
  14. uchar tflag; // 温度正负标志
  15. /**********************lcd1602 设置子函数 *********************/
  16. void delay1ms(uint ms) // 延时 1 毫秒子函数 ,形参为 ms(不够精确的)
  17. {
  18. unsigned int i,j;
  19. for(i=0;i<ms;i++)
  20. for(j=0;j<120;j++);
  21. }
  22. void wr_com(uchar com) //lcd 写控制指令子函数,形参为 com
  23. {
  24. delay1ms(1); // 调用延时子函数,并用实参 1 代替延时子函数中的形参 ms
  25. RS=0; //RS=0 进入写命令状态,即一些 LCD设置命令
  26. RW=0; //RW=0 为写模式
  27. EN=0;  //EN=0 时不能完成写操作
  28. P2=com; // 把要设置的指令码 com送给 P2 口
  29. delay1ms(1);
  30. EN=1; // 给 EN一个高脉冲,将数据送入液晶控制器,完成写操作
  31. delay1ms(1);
  32. EN=0; }//EN=0 时不能完成写操作
  33. /******************检测忙标志函数***************************/  
  34. void check_busy(void)
  35. {
  36.   uchar dt;
  37.   do
  38. {
  39.               dt=0xff;
  40.               EN=0;
  41.               RS=0;
  42.               RW=1;
  43.               EN=1;
  44.               dt=P2;
  45.               }while(dt&0x80);
  46.               EN=0;
  47. }
  48. */
  49. //*****************写数据*******************************/
  50. void wr_dat(uchar dat) //lcd 写显示数据子函数,形参为 dat
  51. {
  52. /* check_busy();*/
  53. delay1ms(1);
  54. RS=1; //RS=1 进入写数据状态,即要显示的内容
  55. RW=0; //RW=0 为写模式
  56. EN=0; //EN=0 时不能完成写操作
  57. P2=dat; // 把要显示的数据 dat 送给 P2 口
  58. delay1ms(1);
  59. EN=1; // 给 EN一个高脉冲,将数据送入液晶控制器,完成写操作
  60. delay1ms(1);
  61. EN=0; //EN=0 时不能完成写操作
  62. }
  63. void lcd_init() //lcd 初始化设置子函数,不带参数 ,0x38 是显示模式设置 , 其余是显示开 / 关及光标设置,无顺序
  64. {
  65. delay1ms(15);
  66. wr_com(0x38); // 调用写控制指令子函数,并用实参 "0011 1000" 代替形参 com
  67. //0x38 表示设置为 16*2 显示,每个块为 5*7 点阵, 8 位数据接口
  68. delay1ms(5);
  69. wr_com(0x08); // 调用写控制指令子函数,并用实参 "0000 1000" 代替形参 com
  70. //0x08 表示设置为关显示、不显示光标、光标不闪烁
  71. delay1ms(5);
  72. wr_com(0x01); // 调用写控制指令子函数,并用实参 "0000 0001" 代替形参 com
  73. //0x01 表示显示数据清屏(数据指针清 0,所有显示清 0)
  74. delay1ms(5);
  75. wr_com(0x06);// 调用写控制指令子函数,并用实参 "0000 0110" 代替形参 com
  76. //0x06 表示当读或写一个字符后地址指针加 1,且光标加 1; 当写一个字符时,整屏显示不移动
  77. delay1ms(5);
  78. wr_com(0x0c);// 调用写控制指令子函数,并用实参 "0000 1100" 代替形参 com
  79. //0x0c 打开显示、不显示光标、光标不闪烁
  80. delay1ms(5);
  81. }
  82. void display(uchar *p) //lcd 显示字符串子函数
  83. {
  84. while(*p!='\0') // 测试是否等于 '\0' ,即判断字符是否结尾
  85. {
  86. wr_dat(*p); // 显示指针所指的字符串
  87. p++; // 指针加 1
  88. delay1ms(1);
  89. }
  90. }
  91. void init_play() // 初始化显示子函数
  92. {
  93. lcd_init(); // 调用 lcd 初始化设置子函数,对 LCD进行初始化
  94. wr_com(0x80); // 调用写控制指令子函数,并用实参 "1000 0000" 代替形参 com
  95. // 并将数据指针定位到第一行第一个字符处
  96. display(str1);// 从第一行第一个字符处显示字符串 str1
  97. wr_com(0x80+0x40);// 调用写控制指令子函数,并用实参 "1000 0000" 代替形参 com
  98. // 并将数据指针定位到第二行第一个字符处
  99. display(str2); // 从第二行第一个字符处显示字符串 str2
  100. }

  101. /********************************************************/
  102. /********************ds18b20 程序 ***********************/
  103. void delay_18b20(uint i) // 延时 1 微秒
  104. {
  105. while(i--);
  106. }
  107. void ds18b20rst() //ds18b20 初始化子函数
  108. // 要求"数据线拉高 - 延时 - 数据线拉低 - 延时大于 480 微妙 -数据线拉高 - 延时等待 "
  109. {
  110. uchar x=0;
  111. DQ = 1; // 信号线 DQ复位
  112. delay_18b20(4); // 延时
  113. DQ = 0; //DQ 拉低
  114. delay_18b20(100); // 精确延时大于 480us
  115. DQ = 1; // 拉高
  116. delay_18b20(40);
  117. }
  118. void ds18b20wr(uchar wdata) /* 写数据子函数 , 无返回值,含参数 */
  119. {
  120. uchar i=0;
  121. for (i=8; i>0; i--)// 要写完一个字节,故需要重复 8 次以下操作
  122. {
  123. DQ = 0; // 数据线拉低
  124. DQ = wdata&0x01;//wdata 是一个形参,将其与 0000 0001 进行按位与
  125. // 按从低到高的顺序发送数据(一次发送一位 )
  126. delay_18b20(10);
  127. DQ = 1; // 最后将数据线拉高
  128. wdata>>=1; // 将 wdata 右移 1 位
  129. }
  130. }
  131. uchar ds18b20rd() // 读数据子函数 , 是有返回值 dat
  132. {
  133. uchar i=0;
  134. uchar dat = 0;
  135. for (i=8;i>0;i--)// 要读完一个字节,故需要重复 8 次以下操作
  136. {
  137. DQ = 0; // 给脉冲信号
  138. dat>>=1;
  139. DQ = 1; // 给脉冲信号
  140. if(DQ)
  141. dat|=0x80;
  142. delay_18b20(10);
  143. }
  144. return(dat); // 返回 dat
  145. }
  146. read_temp() // 读取温度值并转换的子函数,有返回值温度值 tvalue
  147. {
  148. uchar a,b;
  149. ds18b20rst(); // 调用 ds18b20 初始化子函数
  150. ds18b20wr(0xcc);// 调用写数据子函数,向 ds18b20 写命令 0xcc
  151. //ccH 表示跳过 ROM读序列号,适用于单机工作,直接向 18b20 发送温度变换命令
  152. ds18b20wr(0x44);// 调用写数据子函数,向 ds18b20 写命令 0x44
  153. //44H 表示启动 ds18b20 温度转换 , 结果自行存入 9 字节的 RAM中
  154. ds18b20rst(); // 调用 ds18b20 初始化子函数
  155. ds18b20wr(0xcc);// 同上
  156. ds18b20wr(0xbe);// 调用写数据子函数,向 ds18b20 写命令 0xbe
  157. //beH 表示读取 RAM中 9 字节的温度数据
  158. a=ds18b20rd(); // 调用读数据子函数,并将所得数据给 a
  159. b=ds18b20rd(); //
  160. tvalue=b; // 把 b 的值给 tvalue
  161. tvalue<<=8; //tvalue 左移 8 位
  162. tvalue=tvalue|a;//tvalue 与 a 进行按位或
  163. if(tvalue<0x0fff)//
  164. tflag=0; // 前五位为 0 时,读取的温度为正,标志位为 0,此时只要
  165. // 将测得数值乘以 0.0625 即可得到实际温度
  166. else // 前五位为 1 时,读取的温度为负,标志位为 1,此时需要
  167. { // 将测得数值取反后再加 1,再乘以 0.0625 即可得到实际温度
  168. tflag=1; // 此时表示负温度
  169. tvalue=~tvalue+1;
  170. }
  171. tvalue=tvalue*(0.625);// 温度值扩大 10 倍,精确到 1 位小数
  172. return(tvalue); // 返回温度值
  173. }
  174. /**********************************************************/
  175. /************************ 温度值显示 *********************/
  176. void ds18b20disp() // 温度值显示
  177. {
  178. uchar flagdat;
  179. disdata[0]=tvalue/1000+0x30; // 百位数
  180. disdata[1]=tvalue%1000/100+0x30;// 十位数
  181. disdata[2]=tvalue%100/10+0x30; // 个位数
  182. disdata[3]=tvalue%10+0x30; // 小数位
  183. if(tflag==0)
  184. flagdat=0x2b; // 正温度显示符号 :+
  185. else
  186. flagdat=0x2d; // 负温度显示负号 :-
  187. if(disdata[0]==0x30)
  188. {
  189. disdata[0]=0x20; // 如果百位为 0,不显示
  190. if(disdata[1]==0x30)
  191. {
  192. disdata[1]=0x20; // 如果百位为 0,十位为 0 也不显示
  193. }
  194. }
  195. wr_com(0x80+0x44); // 定位数据指针的位置:第二行第五个字符处
  196. wr_dat(flagdat); // 显示符号位
  197. wr_com(0x80+0x45);  // 定位数据指针的位置:第二行第六个字符处
  198. wr_dat(disdata[0]);  // 显示百位
  199. wr_com(0x80+0x46);  // 定位数据指针的位置:第二行第七个字符处
  200. wr_dat(disdata[1]);  // 显示十位
  201. wr_com(0x80+0x47);  // 定位数据指针的位置:第二行第八个字符处
  202. wr_dat(disdata[2]);  // 显示个位
  203. wr_com(0x80+0x48);  // 定位数据指针的位置:第二行第九个字符处
  204. wr_dat(0x2e); // 显示小数点
  205. wr_com(0x80+0x49);  // 定位数据指针的位置:第二行第十个字符处
  206. wr_dat(disdata[3]);  // 显示小数位
  207.               /**********************显示摄氏度************************/
  208. wr_com(0x80+0x4A);  // 定位数据指针的位置:第二行第十一个字符处
  209. wr_dat(0XDF);
  210. wr_com(0x80+0x4B);  // 定位数据指针的位置:第二行第十二个字符处
  211. wr_dat(0X43);
  212. }

  213. /*******************************************************/
  214. /******************** 主程序 *****************************/
  215. void main()
  216. {
  217. init_play();  // 调用 lcd 初始化显示子函数
  218. while(1)
  219. {
  220. read_temp(); // 调用 ds18b20 读取温度
  221. ds18b20disp(); // 调用温度显示子函数
  222. }
  223. }
复制代码
全部资料51hei下载地址:
基于51温度检测程序.zip (17.52 MB, 下载次数: 649)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏30 分享淘帖 顶2 踩
回复

使用道具 举报

沙发
ID:532593 发表于 2019-5-10 15:51 | 只看该作者
你这程序有错
回复

使用道具 举报

板凳
ID:532593 发表于 2019-5-10 16:07 | 只看该作者
大家看看就好,在keil中只是可以翻译,不能编译,亲测的
回复

使用道具 举报

地板
ID:484960 发表于 2020-3-21 16:03 | 只看该作者

没有呀!我设计就是这个程序呀!当时都可以演示的尼
回复

使用道具 举报

5#
ID:484960 发表于 2020-3-21 16:04 | 只看该作者
大白菜111 发表于 2019-5-10 16:07
大家看看就好,在keil中只是可以翻译,不能编译,亲测的

你生成HEX文件后烧录在单片机里面搭配其他外围硬件就可以实现功能的呀!!!
回复

使用道具 举报

6#
ID:701939 发表于 2020-3-23 17:09 | 只看该作者
感谢楼主分享
回复

使用道具 举报

7#
ID:611568 发表于 2020-3-23 21:25 | 只看该作者
学习一下,就是下载速度太慢了。
回复

使用道具 举报

8#
ID:720980 发表于 2020-4-2 17:20 | 只看该作者
请问一下楼主 为什么我的proteus中仿真就一直显示的温度为-1、-0这种?
回复

使用道具 举报

9#
ID:703051 发表于 2020-4-3 12:23 | 只看该作者
问一下楼主,硬件里面的电源那块你是怎么弄的,直接用USB转DC线就行了嘛?
回复

使用道具 举报

10#
ID:224782 发表于 2020-4-16 11:14 | 只看该作者
大白菜111 发表于 2019-5-10 16:07
大家看看就好,在keil中只是可以翻译,不能编译,亲测的

正常编译,正常工作,只能说你有毒,或者不会用。。。。。。
回复

使用道具 举报

11#
ID:730449 发表于 2020-4-17 19:28 来自手机 | 只看该作者
大白菜111 发表于 2019-5-10 16:07
大家看看就好,在keil中只是可以翻译,不能编译,亲测的

注意是AT89C52单片机!建工程别选错!

回复

使用道具 举报

12#
ID:362692 发表于 2020-5-14 16:47 来自手机 | 只看该作者
大白菜111 发表于 2019-5-10 16:07
大家看看就好,在keil中只是可以翻译,不能编译,亲测的

啥都不会,乱叫
回复

使用道具 举报

13#
ID:744393 发表于 2020-5-23 12:09 | 只看该作者
黑子的难拿 发表于 2020-4-2 17:20
请问一下楼主 为什么我的proteus中仿真就一直显示的温度为-1、-0这种?

时序问题,改一下单片机的频率,改为12M的
回复

使用道具 举报

14#
ID:737508 发表于 2020-5-25 10:20 | 只看该作者
xddfandy 发表于 2020-3-21 16:03
没有呀!我课程设计就是这个程序呀!当时都可以演示的尼

兄弟你做成了吗
回复

使用道具 举报

15#
ID:861694 发表于 2020-12-16 20:29 | 只看该作者
如果出错,可能还与软件有关
回复

使用道具 举报

16#
ID:495586 发表于 2020-12-20 08:38 | 只看该作者
只有程序,没有其他的内容了/
回复

使用道具 举报

17#
ID:484960 发表于 2021-1-9 14:57 | 只看该作者
黑弓的拉迪 发表于 2020-4-3 12:23
问一下楼主,硬件里面的电源那块你是怎么弄的,直接用USB转DC线就行了嘛?

这个是直接转DC的,后面我自己做了一个220V交流转5V直流的电源,用作DIY小玩意了,但是已经找不见了,后面找见给你发过去,或者你在网上直接找,很多的原理图。
回复

使用道具 举报

18#
ID:484960 发表于 2021-1-9 14:58 | 只看该作者

我做成了,给师傅演示了
回复

使用道具 举报

19#
ID:484960 发表于 2021-1-9 14:58 | 只看该作者
cheng7791 发表于 2020-12-20 08:38
只有程序,没有其他的内容了/

里面的文字描述的可以作为设计思路的,提交文本直接给师傅看
回复

使用道具 举报

20#
ID:18702 发表于 2022-2-4 22:19 | 只看该作者
编译的没有问题,做的不错
回复

使用道具 举报

21#
ID:18702 发表于 2022-2-5 12:11 | 只看该作者
追加回复来了,通过调试研究,注释的和实际编写的I/O 口有时候对不上,但文档里的是对的,请楼主自行查验,我根据自己的电路更改了一下程序,下载到单片机上了,可用,very good!

IMG_20220205_115513.jpg (3.74 MB, 下载次数: 83)

IMG_20220205_115513.jpg
回复

使用道具 举报

22#
ID:1088965 发表于 2023-9-21 22:54 | 只看该作者
试运行结果为0,仔细看,原来是tvalue这个全局变量。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表