标题: 单片机DS18B20多路温度采集显示 Proteus仿真程序 [打印本页]
作者: Lxy18 时间: 2021-10-15 23:27
标题: 单片机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路温度采集,温度报警、串口什么的都没加。
- /******************************************************************************
- 单片机八路温度采集系统
- *******************************************************************************/
- #include <reg52.h>
- #include "delay.h"
- #include "lcd1602.h"
- #include "DS18B20.h"
- #define uchar unsigned char //对数据类型定义
- #define uint unsigned int
- /****************************端口定义******************************************/
- /*----74HC4051端口定义------------*/
- sbit HC4051_A=P2^0;
- sbit HC4051_B=P2^1;
- sbit HC4051_C=P2^2;
-
- /****************************定义变量******************************************/
- float Temp[8]; //温度变量
- uchar Temp_Str[3]; //数组变量存放温度数据
- /*****************************************************************************/
- /***************************函数声明******************************************/
- void HC4051_CH(uchar ch);//HC4051通道选择函数
- /******************************************************************************
- * 函 数 名 : 主函数
- * 函数功能 :
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void main()
- {
- uchar i;
- Lcd1602_Init(); //1602初始化
- Lcd1602_Write_Cmd(0x01); //清屏
- for(i=0;i<8;i++) //8个温度传感器初始化
- {
- HC4051_CH(i); //选择通道
- DS18B20_Init(); //温度传感器初始化
- }
- while(1)
- {
- for(i=0;i<8;i++) //读取8路温度传感器温度值
- {
- HC4051_CH(i); //选择通道
- Temp[i]=DS18B20_ReadTemp(); //读取温度值
- if(Temp[i]>0) //正温度
- {
- Temp_Str[0]=(int)Temp[i]/100+48; //提取温度百、十、个位
- Temp_Str[1]=((int)Temp[i]%100)/10+48;
- Temp_Str[2]=(int)Temp[i]%10+48;
- }
- else //负温度
- {
- Temp[i]=-Temp[i]; //将负数转换为正数
- Temp_Str[0]='-'; //显示“—”号
- Temp_Str[1]=((int)Temp[i]%100)/10+48; //提取温度个、十位
- Temp_Str[2]=(int)Temp[i]%10+48;
- Temp[i]=-Temp[i]; //将温度恢复
- }
- LcdShowStr(0+4*(i%4),i/4,Temp_Str);//将温度显示在LCD上
- }
- Delay_Ms(30);
- }
- }
- /******************************************************************************
- * 函 数 名 : HC4051_CH(uchar ch)
- * 函数功能 : HC4051通道选择函数
- * 输 入 : ch:选择的通道
- * 输 出 : 无
- *******************************************************************************/
- void HC4051_CH(uchar ch)
- {
- HC4051_A=ch%2;
- HC4051_B=(ch%4)/2;
- HC4051_C=ch/4;
- }
复制代码
作者: perseverance51 时间: 2021-10-31 20:18
采用74HC4051思路方法不错。学习学习!
作者: Lxy18 时间: 2021-10-31 23:33
发现被人拿到咸鱼卖了,30元一个
作者: 123156fsadf 时间: 2021-11-3 15:07
可以直接把八路都接到一根引脚的,然后用ID的方式去读不同芯片的温度
作者: vscos 时间: 2021-12-13 07:27
这都有人买呀
作者: vscos 时间: 2021-12-13 07:38
不是程序多,是那个程序要改成多端口的,你是从网上抄来的吧!网上那个只能用一个端口,你要是只改函数名,就想用肯定多了,你要将程序的函数都改成有参数的,调用时通过参数确定用那个端口,这样可以减少代码量
作者: Lxy18 时间: 2022-1-20 11:40
程序原创的!!io作为函数参数,就不可能实现,我也想过这样。现在单总线ROM方式已经搞出来了。
作者: Lxy18 时间: 2022-1-20 11:45
按你所说,用8个IO口接8个18B20,温度读取函数设置通道选择参数(IO口不能作为参数输入),那在函数中如何根据输入的通道切换操作的IO口?
作者: lkc8210 时间: 2022-1-20 14:29
对~
但IO口的读写不能直接P00 = 1 或 if(P00)
要参考arduino的写法
- void digitalWrite(char PinNum, bit Command){
- if(Command){
- P0 |= 0x01 << PinNum;
- }else{
- P0 &= ~(0x01 << PinNum);
- }
- }
- bit digitalRead(char PinNum){
- if(P0 & (0x01<<PinNum))
- return 1;
- else
- return 0;
- }
复制代码
作者: Lxy18 时间: 2022-3-14 08:50
原来如此,学到了学到了。
作者: 1192833874 时间: 2022-4-6 20:47
这两个函数什么意思啊
,能吧根据参数选择IO口写具体点吗,单片机,求求大佬解惑了
作者: 1192833874 时间: 2022-4-6 21:19
哦,就是把所有的P0^n=i;换成digitalWrite(n,i)。P0^n换成digitalRead(n),是吗?
我这样做了,可是出错了呀,数据读不出来
作者: 1192833874 时间: 2022-4-6 21:21
- #include "reg52.h"
- void digitalWrite(char PinNum, bit Command){
- if(Command){
- P1 |= 0x01 << PinNum;
- }else{
- P1 &= ~(0x01 << PinNum);
- }
- }
- bit digitalRead(char PinNum){
- if(P1 & (0x01<<PinNum))
- return 1;
- else
- return 0;
- }
- //单总线延时函数
- void Delay_OneWire(unsigned int t){
- while(t--);
- }
- //通过单总线向DS18B20写一个字节
- void Write_DS18B20(unsigned char N,unsigned char dat){
- unsigned char i;
- for(i=0;i<8;i++){
- digitalWrite(N,0);
- digitalWrite(N,dat&0x01);
- Delay_OneWire(5);
- digitalWrite(N,1);
- dat >>= 1;
- }
- Delay_OneWire(5);
- }
- //从DS18B20读取一个字节
- unsigned char Read_DS18B20(unsigned char N){
- unsigned char i;
- unsigned char dat;
-
- for(i=0;i<8;i++){
- digitalWrite(N,0);
- dat >>= 1;
- digitalWrite(N,1);
- if(digitalRead(N)){
- dat |= 0x80;
- }
- Delay_OneWire(5);
- }
- return dat;
- }
- //DS18B20设备初始化
- bit init_ds18b20(unsigned char N){
- bit initflag = 0;
-
- digitalWrite(N,1);
- Delay_OneWire(12);
- digitalWrite(N,0);
- Delay_OneWire(80);
- digitalWrite(N,1);
- Delay_OneWire(10);
- initflag = digitalRead(N);
- Delay_OneWire(5);
-
- return initflag;
- }
- unsigned int rd_temperature(unsigned char N){
- unsigned char low, high;
- init_ds18b20(N); // 初始化
- Write_DS18B20(N,0xCC); // 跳过ROM
- Write_DS18B20(N,0x44); // 启动温度转换
- init_ds18b20(N);
- Write_DS18B20(N,0xCC);
- Write_DS18B20(N,0xBE); // 读取寄存器
- low = Read_DS18B20(N); // 低字节
- high = Read_DS18B20(N); // 高字节
- return (high<<8)+low;
- }
复制代码 就这个代码,rd_temperature函数读数据
作者: 陈123456礊 时间: 2024-1-25 15:34
太感谢了,DIY小玩意就做关于这个的方向,只不过是需要将读取的八路温度数据传输到labview上位机进行检测,作者是否对labview上位机有研究?
作者: kmsj 时间: 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应用率,顶多是读取温度的时间慢一点而已(最多慢零点零几秒到零点几秒),温度是一个渐变的过程,读取温度的时间慢一点对绝大多数的温度控制毫无影响。个人意见,仅供参考。
作者: 陈123456礊 时间: 2024-1-25 20:15
请教一下关于lcd1602的代码怎样编写
作者: Lxy18 时间: 2024-1-26 11:25
前面已经说明,最开始匹配rom的程序没做出来,所以才选择这个方案,虽然增加了io口,增加了一个芯片,但是可以实现功能,而且相对于匹配rom替换DS18B20不需要重新读取rom,不需要修改程序。各有优缺点。工程角度肯定考虑成本,但是这仅仅是学习交流使用,交作品用的。
作者: kmsj 时间: 2024-1-26 18:35
如果仅仅是交作品混学分,就没有讨论的意义了,就算是交作品混学分,用匹配ROM或者8个I/O口读出8个18B20的温度,你的老师为你负责的话,得到的学分更高才对,最关键可以提高自己的编程水平。
作者: xiaogan_gu 时间: 2024-2-18 20:58
可以并行一次性读取8个DS18B20里的数据放入8个单元的数组里,然后对这些数据进行处理就可以了。这个方法程序简单,不需要多余的电路,也不用读ID,就是要占用8个IO口。
作者: 陈123456礊 时间: 2024-2-25 10:59
可以分享一下全套源码吗?
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |