找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 15531|回复: 15
收起左侧

基于stc89c52单片机的数字温度传感器电路与代码(注释详细)

  [复制链接]
ID:343796 发表于 2018-10-24 09:43 | 显示全部楼层 |阅读模式
这是一个使用DS18B20作为温度传感器的简易数字温度传感器,将温度传感器的实时数据输出到LCD1602液晶显示。P0口上拉10K电阻接液晶屏,P2.0-P2.3分别是LCD1602的RS,RW,EN和DS18B20的DQ数据口。

电路原理图如下:

电路图

电路图


单片机源程序如下:
  1. #include <reg52.h>
  2. #include<intrins.h>
  3. sbit RS = P2^0;   //定义端口
  4. sbit RW = P2^1;
  5. sbit EN = P2^2;
  6. sbit DQ = P2^3; //定义总线的I/O管脚
  7. void SendByte(unsigned char dat);
  8. void zf_1602(unsigned char x,unsigned char y,unsigned dat);
  9. void Delay4us() //延时4us
  10. {
  11. ;
  12. }
  13. void Delay(unsigned char j)  //一个循环15us
  14. {
  15. unsigned char i;
  16. while(j--)
  17. {
  18.   i = 5;
  19.   while (--i);
  20. }
  21. }
  22. bit d18b20_qs() //18b20 起始
  23. {
  24. bit dat;
  25. DQ = 1; //DQ复位
  26. Delay4us();
  27. DQ = 0; //拉低总线
  28. Delay(35); //这里延时大概 525us
  29. DQ = 1; //拉高总线
  30. Delay(2);  //这里延时大概 30us
  31. dat = DQ; //读取返回值(0:有18b20存在 1:是没有)
  32. Delay(2);
  33. return dat; //返回数值
  34. }
  35. void d18b20_x(unsigned char dat) //写 8 位 数 据
  36. {
  37. unsigned char i;
  38. for(i=0;i<8;i++) //8位计数器
  39. {
  40.   DQ = 0; //拉低总线
  41.   DQ = dat & 0x01; //取最低位赋值给总线
  42.   Delay(3); //延时45us
  43.   DQ = 1; //拉过总线准备写下一个数据(或者总线复位)
  44.   dat >>= 1; //数据右移一位
  45. }
  46. }
  47. unsigned char d18b20_d() //读 8 位 数 据
  48. {
  49. unsigned char i,dat=0;
  50. for(i=0;i<8;i++) //8位计数器
  51. {
  52.   DQ = 0; //拉低总线
  53.   dat >>= 1; //数据右移一位
  54.   DQ = 1; //拉过总线(准备读取数据)
  55.   if(DQ) //判断是否是 1 如果是就把数据赋值给变量的高位
  56.    dat |= 0x80;
  57.   Delay(4);
  58. }
  59. return dat; //返回读取到数据数据
  60. }
  61. unsigned int wd() //读取温度函数
  62. {
  63. unsigned char i = 0; //低8位数据
  64. unsigned char j = 0; //高8位数据
  65. unsigned int k = 0; //无符号16整形用来存储读回来的 16位温度数据(j和i组合后的数据)
  66. d18b20_qs(); //初始化
  67. d18b20_x(0xCC); //跳过序列号的操作(因为18b20在总线上可以挂很多个,这个序列号和网卡MAC地址类似)
  68. d18b20_x(0x44); //开启温度转换
  69. Delay(200);   //开启温度转换需要时间这里延时一下

  70. d18b20_qs(); //初始化
  71. d18b20_x(0xCC); //跳过序列号的操作(因为18b20在总线上可以挂很多个,这个序列号和网卡MAC地址类似)
  72. d18b20_x(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
  73. i = d18b20_d(); //读取低8位
  74. j = d18b20_d(); //读取高8位
  75. k = j;  
  76. k <<= 8;
  77. k = k + i;
  78. return k; //返回读取到的16位数据
  79. }
  80. void zh(unsigned int i)  //1602显示缓存写入函数
  81. {
  82. unsigned char x,z;
  83. x = i & 0x0f; //取出小数
  84. i >>=4;
  85. switch(x) //小数位转换
  86. {
  87.   case 0: z=0;break;
  88.   case 1: z=1;break;
  89.   case 2: z=1;break;
  90.   case 3: z=2;break;
  91.   case 4: z=3;break;
  92.   case 5: z=3;break;
  93.   case 6: z=4;break;
  94.   case 7: z=4;break;
  95.   case 8: z=5;break;
  96.   case 9: z=6;break;
  97.   case 10: z=6;break;
  98.   case 11: z=7;break;
  99.   case 12: z=8;break;
  100.   case 13: z=8;break;
  101.   case 14: z=9;break;
  102.   case 15: z=9;break;
  103. }
  104. z = z +48; //转换成ascii码
  105. zf_1602(5,1,z); //写入1602缓存
  106. z = i & 0xff; //取出整数
  107. x = z/10; //取出十位
  108. x= x+48; //转换成ascii码
  109. zf_1602(2,1,x); //写入1602缓存
  110. x = z%10; //取出个位
  111. x= x+48; //转换成ascii码
  112. zf_1602(3,1,x); //写入1602缓存
  113. }
  114. void Delayus(unsigned char t) // us级别延时
  115. {  
  116. while(--t);
  117. }
  118. void Delayms(unsigned char t)// ms级别延时
  119. {
  120.    
  121. while(t--)
  122. {
  123.      //大致延时1mS
  124.      Delayus(245);
  125.   Delayus(245);
  126. }
  127. }
  128. bit m_1602() //判断1602是否忙
  129. {
  130. P0 = 0xFF; //准备读取
  131. RS = 0;
  132. RW = 1;
  133. EN = 0;
  134. _nop_();
  135. EN = 1; //产生高电平
  136. return (bit)(P0 & 0x80);
  137. }
  138. void x_1602(bit i,unsigned char j) //参数一是写(0、写指令 1、写数据),参数二是写入的8位数据
  139. {
  140. while(m_1602())
  141. {
  142.   _nop_();
  143.   _nop_();
  144.   _nop_();
  145.   _nop_();
  146.   _nop_();
  147. }
  148. RS = i;
  149. RW = 0;
  150. EN = 1;
  151. P0 = j;
  152. _nop_();
  153. EN = 0; //产生下降沿
  154. }
  155. void qp_1602() //清屏函数
  156. {
  157. x_1602(0,0x01); //第一个参数是:写入的类型(0、写指令 1、写数据),第一个参数是:写入的数据
  158. Delayms(5);
  159. }
  160. //显示字符
  161. void zf_1602(unsigned char x,unsigned char y,unsigned dat) //参数一是显示的列,参数二是显示的行,参数三是显示的数据
  162. {
  163. if(y==0)
  164. {
  165.   x_1602(0,(0x80+x)); //第一行
  166. }
  167. else
  168. {
  169.   x_1602(0,(0xc0+x)); //第二行
  170. }
  171. x_1602(1,dat); //写入数据
  172. }
  173. void zfc_1602(unsigned char x,unsigned char y,unsigned char *dat)
  174. {
  175. if(y==0)
  176. {
  177.   x_1602(0,(0x80+x)); //第一行
  178. }
  179. else
  180. {
  181.   x_1602(0,(0xc0+x)); //第二行
  182. }
  183. while(*dat) //&:取地址 *:取值
  184. {
  185.   x_1602(1,*dat);
  186.   dat ++;
  187. }
  188. }
  189. void csh_1602()  //初始化1602
  190. {
  191. x_1602(0,0x38); //显示模式设置
  192. Delayms(5);
  193. x_1602(0,0x38);
  194. Delayms(5);
  195. x_1602(0,0x38);
  196. Delayms(5);
  197. x_1602(0,0x38);
  198. x_1602(0,0x08); //显示关闭.
  199. x_1602(0,0x01); //显示清屏
  200. x_1602(0,0x06); //显示光标移动设置
  201. Delayms(5);
  202. x_1602(0,0x0c);  //显示开及光标设置
  203. }
  204. void Lcd_User_Chr(void) // 1602 自定义字符(摄氏度的小点)    自定义字符
  205. {
  206. x_1602(0,0x48); //"01 001 000"  第1行地址
  207. x_1602(1,0x03); //"XXX 00001" 第1行数据
  208. x_1602(0,0x49); //"01 001 001"  第2行地址
  209. x_1602(1,0x03); //"XXX 11011" 第2行数据
  210. x_1602(0,0x4a); //"01 001 010"  第3行地址
  211. x_1602(1,0x00); //"XXX 11101" 第3行数据
  212. x_1602(0,0x4b); //"01 001 011"  第4行地址
  213. x_1602(1,0x00); //"XXX 11001" 第4行数据
  214. x_1602(0,0x4c); //"01 001 100"  第5行地址
  215. x_1602(1,0x00); //"XXX 11101" 第5行数据
  216. x_1602(0,0x4d); //"01 001 101"  第6行地址
  217. x_1602(1,0x00); //"XXX 11011" 第6行数据
  218. x_1602(0,0x4e); //"01 001 110"  第7行地址
  219. x_1602(1,0x00); //"XXX 00001" 第7行数据
  220. x_1602(0,0x4f); //"01 001 111"  第8行地址
  221. x_1602(1,0x00); //"XXX 00000" 第8行数据
  222. }
  223. void main()
  224. {
  225. unsigned char i;
  226. csh_1602();
  227. qp_1602();
  228. Lcd_User_Chr();
  229. zf_1602(4,1,'.');
  230. zf_1602(6,1,0x01); //摄氏度的点
  231. zf_1602(7,1,'C'); //大写的C
  232. zfc_1602(1,0,"www.51hei.com");
  233. while(1)
  234. {
  235.   zh(wd());
  236.   for(i=0;i<10;i++)
  237.    Delayms(200);
  238. }
  239. }
复制代码

所有资料51hei提供下载:
温度显示2.zip (2.06 KB, 下载次数: 144)

评分

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

查看全部评分

回复

使用道具 举报

ID:426241 发表于 2018-11-26 22:16 来自手机 | 显示全部楼层
请问这个是直接在液晶屏上显示温度吗?
回复

使用道具 举报

ID:343796 发表于 2018-11-27 23:57 | 显示全部楼层
回复楼上,是的
回复

使用道具 举报

ID:433919 发表于 2018-11-30 16:11 | 显示全部楼层
你好,图能发完整吗
回复

使用道具 举报

ID:29048 发表于 2018-12-1 08:10 | 显示全部楼层
要是整个工程就更好了
回复

使用道具 举报

ID:481272 发表于 2019-4-1 17:48 | 显示全部楼层
完整的仿真图
回复

使用道具 举报

ID:388130 发表于 2019-7-22 14:58 | 显示全部楼层
楼主,要想在数码管上显示温度该怎么去修改呢·?
回复

使用道具 举报

ID:388130 发表于 2019-7-22 15:06 | 显示全部楼层

楼主,请问,如果改成数码管显示温度,要怎么去改呢?
回复

使用道具 举报

ID:343168 发表于 2019-12-1 22:48 | 显示全部楼层
如果能讲讲原理就好了,对于小白来说,直接看程序,头大啊。
回复

使用道具 举报

ID:424506 发表于 2019-12-1 23:03 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

ID:670929 发表于 2019-12-23 09:18 | 显示全部楼层
感谢分享
回复

使用道具 举报

ID:671488 发表于 2019-12-23 16:09 | 显示全部楼层
请问这个是直接在液晶屏上显示温度吗?
回复

使用道具 举报

ID:671488 发表于 2019-12-25 11:10 | 显示全部楼层
我能评论一下吗
回复

使用道具 举报

ID:996194 发表于 2021-12-23 16:49 | 显示全部楼层
左边的图有吗
回复

使用道具 举报

ID:1010749 发表于 2022-3-16 11:35 | 显示全部楼层
用C语言编码会节约单片机内存
回复

使用道具 举报

ID:1002955 发表于 2022-3-17 08:23 | 显示全部楼层
ls147258 发表于 2019-12-1 22:48
如果能讲讲原理就好了,对于小白来说,直接看程序,头大啊。

KST51梳理应该有
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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