找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机DS18B20多路温度采集显示 Proteus仿真程序

  [复制链接]
跳转到指定楼层
#
本帖最后由 Lxy18 于 2021-10-31 23:51 编辑

认真学习了DS18B20的手册,发现DS18B20单总线实现多路采集,需要读取ROM指令,通过ROM指令读取指定的DS18B20温度。操作相当麻烦,参考了CSDN的例子,最后还是没搞出来。后来就想能不能把8个DS18B20连接到8个IO口上,然后就是分别读取8个IO口的温度数据,这样的话就需要8个驱动程,理论可行,需要的程序相当多,所以这样也不可行。然后就想,如果用一个驱动程序,在函数中改变总线变量定义的IO口,也就是改变变量的地址,查找很多资料后,发现这根本不可能。

最后,就想有没有一种芯片可以一个IO口选通8个口,经过一番努力之后,果然有,74HC4051,8通道模拟多路选择器/多路分配器,带有3个数字选择端(S0至S2),1个低有效使能端(E),8个独立输入/输出端(Y0至Y7)和1个公共输入/输出端(Z)。

然后就是画仿真,写程序了。经过测试后非常好用,程序也非常简单。


主程序如下,只实现了基本的8路温度采集,温度报警、串口什么的都没加。


  1. /******************************************************************************
  2. 单片机八路温度采集系统
  3. *******************************************************************************/
  4. #include <reg52.h>                        
  5. #include "delay.h"
  6. #include "lcd1602.h"
  7. #include "DS18B20.h"

  8. #define uchar unsigned char          //对数据类型定义
  9. #define uint  unsigned int

  10. /****************************端口定义******************************************/                                 
  11. /*----74HC4051端口定义------------*/

  12. sbit HC4051_A=P2^0;
  13. sbit HC4051_B=P2^1;
  14. sbit HC4051_C=P2^2;
  15.                                                          
  16. /****************************定义变量******************************************/
  17. float Temp[8];                        //温度变量
  18. uchar Temp_Str[3];            //数组变量存放温度数据        
  19. /*****************************************************************************/
  20. /***************************函数声明******************************************/
  21. void HC4051_CH(uchar ch);//HC4051通道选择函数
  22. /******************************************************************************
  23. * 函 数 名         : 主函数
  24. * 函数功能                   :
  25. * 输    入         : 无
  26. * 输    出         : 无
  27. *******************************************************************************/
  28. void main()
  29. {
  30.         uchar i;
  31.         Lcd1602_Init();              //1602初始化
  32.         Lcd1602_Write_Cmd(0x01);     //清屏
  33.         for(i=0;i<8;i++)                         //8个温度传感器初始化
  34.         {
  35.                 HC4051_CH(i);                          //选择通道
  36.                 DS18B20_Init();                         //温度传感器初始化
  37.         }
  38.         while(1)
  39.         {
  40.                 for(i=0;i<8;i++)                 //读取8路温度传感器温度值
  41.                 {
  42.                         HC4051_CH(i);                                            //选择通道
  43.                         Temp[i]=DS18B20_ReadTemp();                   //读取温度值
  44.                         if(Temp[i]>0)                                           //正温度
  45.                         {
  46.                                 Temp_Str[0]=(int)Temp[i]/100+48;          //提取温度百、十、个位
  47.                                 Temp_Str[1]=((int)Temp[i]%100)/10+48;
  48.                                 Temp_Str[2]=(int)Temp[i]%10+48;
  49.                         }
  50.                         else                                                           //负温度
  51.                         {
  52.                                 Temp[i]=-Temp[i];                           //将负数转换为正数
  53.                                 Temp_Str[0]='-';                           //显示“—”号
  54.                                 Temp_Str[1]=((int)Temp[i]%100)/10+48; //提取温度个、十位
  55.                                 Temp_Str[2]=(int)Temp[i]%10+48;
  56.                                 Temp[i]=-Temp[i];                           //将温度恢复
  57.                         }
  58.                         LcdShowStr(0+4*(i%4),i/4,Temp_Str);//将温度显示在LCD上
  59.                 }        
  60.                 Delay_Ms(30);
  61.         }
  62. }
  63. /******************************************************************************
  64. * 函 数 名         : HC4051_CH(uchar ch)
  65. * 函数功能                   : HC4051通道选择函数
  66. * 输    入         : ch:选择的通道
  67. * 输    出         : 无
  68. *******************************************************************************/
  69. void HC4051_CH(uchar ch)
  70. {
  71.         HC4051_A=ch%2;
  72.         HC4051_B=(ch%4)/2;
  73.         HC4051_C=ch/4;        
  74. }
复制代码

评分

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

查看全部评分

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

使用道具 举报

19#
ID:1110110 发表于 2024-2-25 10:59 | 只看该作者
可以分享一下全套源码吗?
回复

使用道具 举报

18#
ID:73422 发表于 2024-2-18 20:58 | 只看该作者
可以并行一次性读取8个DS18B20里的数据放入8个单元的数组里,然后对这些数据进行处理就可以了。这个方法程序简单,不需要多余的电路,也不用读ID,就是要占用8个IO口。
回复

使用道具 举报

17#
ID:383215 发表于 2024-1-26 18:35 | 只看该作者
Lxy18 发表于 2024-1-26 11:25
前面已经说明,最开始匹配rom的程序没做出来,所以才选择这个方案,虽然增加了io口,增加了一个芯片,但 ...

如果仅仅是交作品混学分,就没有讨论的意义了,就算是交作品混学分,用匹配ROM或者8个I/O口读出8个18B20的温度,你的老师为你负责的话,得到的学分更高才对,最关键可以提高自己的编程水平。
回复

使用道具 举报

16#
ID:856329 发表于 2024-1-26 11:25 | 只看该作者
kmsj 发表于 2024-1-25 17:47
单片机的应用思路,就是要用好单片机的内部资源包括程序让外围电路越简单越好,楼主增加74HC4051让单片机编 ...

前面已经说明,最开始匹配rom的程序没做出来,所以才选择这个方案,虽然增加了io口,增加了一个芯片,但是可以实现功能,而且相对于匹配rom替换DS18B20不需要重新读取rom,不需要修改程序。各有优缺点。工程角度肯定考虑成本,但是这仅仅是学习交流使用,交作品用的。
回复

使用道具 举报

15#
ID:1110110 发表于 2024-1-25 20:15 | 只看该作者
请教一下关于lcd1602的代码怎样编写
回复

使用道具 举报

14#
ID:383215 发表于 2024-1-25 17:47 | 只看该作者
单片机的应用思路,就是要用好单片机的内部资源包括程序让外围电路越简单越好,楼主增加74HC4051让单片机编程变的简单的思路完全背离了单片机应用的基本思路,肯定是不可取的。虽然74HC4051只是几毛钱,但是,增加了74HC4051电路就复杂了,增加74HC4051读写8个18B20,依然用掉单片机的4个I/O口,相当于用4个I/O口换取8个18B20的读写,还增加了一片74HC4051,一点也不划算。单片机读取8个18B20温度的正确编程思路只有两个,一个是用8个I/O口连接8个18B20,编程思路是同时对8个18B20做初始化和跳过ROM指令的操作,然后把8个18B20的温度读出来,另一个是8个18B20的8个单总线接单片机的一个I/O口,用匹配ROM的方法把每一个18B20的温度读出来,无论是8个I/O口接8个18B20还是8个18B20的8个单总线接单片机的一个I/O口,都可以用细化到步的编程方法,提高单片机的CPU应用率,顶多是读取温度的时间慢一点而已(最多慢零点零几秒到零点几秒),温度是一个渐变的过程,读取温度的时间慢一点对绝大多数的温度控制毫无影响。个人意见,仅供参考。

评分

参与人数 2黑币 +25 收起 理由
liang1981 + 5 正确思路
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

13#
ID:1110110 发表于 2024-1-25 15:34 | 只看该作者
太感谢了,DIY小玩意就做关于这个的方向,只不过是需要将读取的八路温度数据传输到labview上位机进行检测,作者是否对labview上位机有研究?
回复

使用道具 举报

12#
ID:1016228 发表于 2022-4-6 21:21 | 只看该作者
lkc8210 发表于 2022-1-20 14:29
对~
但IO口的读写不能直接P00 = 1 或 if(P00)
要参考arduino的写法
  1. #include "reg52.h"

  2. void digitalWrite(char PinNum, bit Command){
  3.         if(Command){
  4.                 P1 |= 0x01 << PinNum;
  5.         }else{
  6.                 P1 &= ~(0x01 << PinNum);
  7.         }
  8. }

  9. bit digitalRead(char PinNum){
  10.         if(P1 & (0x01<<PinNum))
  11.                 return 1;
  12.         else
  13.                 return 0;
  14. }

  15. //单总线延时函数
  16. void Delay_OneWire(unsigned int t){
  17.   while(t--);
  18. }

  19. //通过单总线向DS18B20写一个字节
  20. void Write_DS18B20(unsigned char N,unsigned char dat){
  21.   unsigned char i;
  22.   for(i=0;i<8;i++){
  23.     digitalWrite(N,0);
  24.     digitalWrite(N,dat&0x01);
  25.     Delay_OneWire(5);
  26.     digitalWrite(N,1);
  27.     dat >>= 1;
  28.   }
  29.   Delay_OneWire(5);
  30. }

  31. //从DS18B20读取一个字节
  32. unsigned char Read_DS18B20(unsigned char N){
  33.   unsigned char i;
  34.   unsigned char dat;

  35.   for(i=0;i<8;i++){
  36.     digitalWrite(N,0);
  37.     dat >>= 1;
  38.     digitalWrite(N,1);
  39.     if(digitalRead(N)){
  40.       dat |= 0x80;
  41.     }            
  42.     Delay_OneWire(5);
  43.   }
  44.   return dat;
  45. }

  46. //DS18B20设备初始化
  47. bit init_ds18b20(unsigned char N){
  48.   bit initflag = 0;
  49.          
  50.   digitalWrite(N,1);
  51.   Delay_OneWire(12);
  52.   digitalWrite(N,0);
  53.   Delay_OneWire(80);
  54.   digitalWrite(N,1);
  55.   Delay_OneWire(10);
  56.   initflag = digitalRead(N);
  57.   Delay_OneWire(5);
  58.   
  59.   return initflag;
  60. }

  61. unsigned int rd_temperature(unsigned char N){
  62.   unsigned char low, high;

  63.   init_ds18b20(N);                               // 初始化
  64.   Write_DS18B20(N,0xCC);                          // 跳过ROM
  65.   Write_DS18B20(N,0x44);                          // 启动温度转换

  66.   init_ds18b20(N);
  67.   Write_DS18B20(N,0xCC);
  68.   Write_DS18B20(N,0xBE);                          // 读取寄存器
  69.   low = Read_DS18B20(N);                         // 低字节
  70.   high = Read_DS18B20(N);                        // 高字节

  71.   return (high<<8)+low;
  72. }
复制代码
就这个代码,rd_temperature函数读数据
回复

使用道具 举报

11#
ID:1016228 发表于 2022-4-6 21:19 | 只看该作者
lkc8210 发表于 2022-1-20 14:29
对~
但IO口的读写不能直接P00 = 1 或 if(P00)
要参考arduino的写法

哦,就是把所有的P0^n=i;换成digitalWrite(n,i)。P0^n换成digitalRead(n),是吗?
我这样做了,可是出错了呀,数据读不出来
回复

使用道具 举报

10#
ID:1016228 发表于 2022-4-6 20:47 | 只看该作者
lkc8210 发表于 2022-1-20 14:29
对~
但IO口的读写不能直接P00 = 1 或 if(P00)
要参考arduino的写法

这两个函数什么意思啊,能吧根据参数选择IO口写具体点吗,单片机,求求大佬解惑了
回复

使用道具 举报

9#
ID:856329 发表于 2022-3-14 08:50 | 只看该作者
lkc8210 发表于 2022-1-20 14:29
对~
但IO口的读写不能直接P00 = 1 或 if(P00)
要参考arduino的写法

原来如此,学到了学到了。
回复

使用道具 举报

8#
ID:161164 发表于 2022-1-20 14:29 | 只看该作者
Lxy18 发表于 2022-1-20 11:45
按你所说,用8个IO口接8个18B20,温度读取函数设置通道选择参数(IO口不能作为参数输入),那在函数中如何 ...

对~
但IO口的读写不能直接P00 = 1 或 if(P00)
要参考arduino的写法
  1. void digitalWrite(char PinNum, bit Command){
  2.         if(Command){
  3.                 P0 |= 0x01 << PinNum;
  4.         }else{
  5.                 P0 &= ~(0x01 << PinNum);
  6.         }
  7. }
  8. bit digitalRead(char PinNum){
  9.         if(P0 & (0x01<<PinNum))
  10.                 return 1;
  11.         else
  12.                 return 0;
  13. }
复制代码
回复

使用道具 举报

7#
ID:856329 发表于 2022-1-20 11:45 | 只看该作者
vscos 发表于 2021-12-13 07:38
不是程序多,是那个程序要改成多端口的,你是从网上抄来的吧!网上那个只能用一个端口,你要是只改函数名, ...

按你所说,用8个IO口接8个18B20,温度读取函数设置通道选择参数(IO口不能作为参数输入),那在函数中如何根据输入的通道切换操作的IO口?
回复

使用道具 举报

6#
ID:856329 发表于 2022-1-20 11:40 | 只看该作者
vscos 发表于 2021-12-13 07:38
不是程序多,是那个程序要改成多端口的,你是从网上抄来的吧!网上那个只能用一个端口,你要是只改函数名, ...

程序原创的!!io作为函数参数,就不可能实现,我也想过这样。现在单总线ROM方式已经搞出来了。
回复

使用道具 举报

5#
ID:654797 发表于 2021-12-13 07:38 | 只看该作者
不是程序多,是那个程序要改成多端口的,你是从网上抄来的吧!网上那个只能用一个端口,你要是只改函数名,就想用肯定多了,你要将程序的函数都改成有参数的,调用时通过参数确定用那个端口,这样可以减少代码量
回复

使用道具 举报

地板
ID:654797 发表于 2021-12-13 07:27 | 只看该作者
Lxy18 发表于 2021-10-31 23:33
发现被人拿到咸鱼卖了,30元一个

这都有人买呀
回复

使用道具 举报

板凳
ID:744809 发表于 2021-11-3 15:07 | 只看该作者
可以直接把八路都接到一根引脚的,然后用ID的方式去读不同芯片的温度
回复

使用道具 举报

沙发
ID:856329 发表于 2021-10-31 23:33 | 只看该作者
发现被人拿到咸鱼卖了,30元一个
回复

使用道具 举报

楼主
ID:795427 发表于 2021-10-31 20:18 | 只看该作者
采用74HC4051思路方法不错。学习学习!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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