单线多路DS18B20测温,附加读取DS18B20序列号
第一次发帖写教程,有问题请多提意见
文件在附件中
基于89C51单片机的单线多路DS18B20多点测温 Keil文档 + Protuse仿真
这是写的第一篇文档,可能有些地方有点啰嗦,请多多交流。 关于DS18B20的详细介绍我就不啰嗦了 本人所使用软件为ISIS,keil4 先看Protuse仿真
图中使用了1个89c51单片机,两个DS18B20 ,1个74HC573寄存器,一排8个共阳数码管,以及按键 按键1,2用于两个温度之间切换 按键一按下显示第一个DS18B20温度以及其上下限 按键二按下显示第二个DS18B20温度以及其上下限 其余四个按键用于调控温度上下限设置使用; 附加 读取DS18B20 的序列号功能(使用不同的显示函数) 首先要在Protuse中设置DS18B20的序列号
右键点击DS18B20 B8C534其中的序列号 4以更改
更改后可以用软件CRC计算器 其对应序列号
计算方式如图所示
28 为其家族序列号 固定使用
在HEX中输入 编码 点击Calculate 记得到数值 52
所以其完整序列号为:ROM1[] = {0x28,0x34,0xC5,0xB8,0x00,0x00,0x00,0x52};
更改protuse中ds18B20的末位数字即可得到不同的序列号
在使用Protuse仿真之前应先设置DS18B20de序列号
单片机源程序如下:
- /**********************************************/
- DS18B20驱动程序如下
- //******DS18B20子函数***********
- #define uint unsigned int
- #define uchar unsigned char
- code unsigned char ROM1[] = {0x28,0x34,0xC5,0xB8,0x00,0x00,0x00,0x52};
- code unsigned char ROM2[] = {0x28,0x31,0xC5,0xB8,0x00,0x00,0x00,0xB9}; //
- sbit DQ = P3^1; //单片机的P3.1 与ds18b20数据端口连接在一起
- void delay(uint x)
- {
- while(x--);
- }
- void Init_DS18B20(void)
- {
- unsigned char x = 255;
- DQ = 1; //先让DQ = 1;
- DQ = 0; //单片机将DQ拉低
- delay(80); //延时480~960s
- DQ = 1; //释放总线
- while(DQ && x--); //等待返回的低电平响应,如果没有响应,
- delay(20); //则做适量延时自动往下执行
- }
- //读取温度
- unsigned char Read_OneChar(void)
- {
- uchar i = 0;
- uchar dat = 0;
- for(i = 0;i < 8;i++)
- {
- DQ = 0; //发送启动信号
- dat =dat >> 1;
- DQ = 1;
- if(DQ) //判断总线是否为高电平
- dat =dat | 0x80; //如果是高电平则把 j 的最高位置1,如果不是置0;
- delay(10);
- }
- return(dat);
- }
- //向DS18b20中写入一个字节
- void Write_OneChar(unsigned char dat)
- {
- uchar i = 0;
- for(i = 0;i < 8;i++)
- {
- DQ = 0;
- DQ = dat & 0x01; //读取 X 的最低位
- delay(10);
- DQ = 1;
- dat= dat >> 1;
- }
- delay(8);
- }
- void PP_SZ1()
- {
- uchar i;
- Write_OneChar(0x55);
- for(i=0;i<8;i++) //发送序列号
- {
- Write_OneChar(ROM1[i]);
- }
- }
- void PP_SZ2()
- {
- uchar i;
- Write_OneChar(0x55);
- for(i=0;i<8;i++) //发送序列号
- {
- Write_OneChar(ROM2[i]);
- }
- }
-
- //********保存温度上下限********
- void write_temprom(uchar temp_up,uchar temp_down) //应用操作函数2
- {
- Init_DS18B20();
- // Write_OneChar(0xcc);
- if((key_flag1 == 1)&&(key_flag2 == 0))PP_SZ1();
- if((key_flag1 == 0)&&(key_flag2 == 1))PP_SZ2(); //跳过读序号列号的操作
- Write_OneChar(0x4e); //写准备
- Write_OneChar(temp_up); //向18B20的暂存写上限
- Write_OneChar(temp_down); //向18B20的暂存写下限
- // Write_OneChar(0x7f)
- Init_DS18B20();
- // Write_OneChar(0xcc);
- if((key_flag1 == 1)&&(key_flag2 == 0))PP_SZ1();
- if((key_flag1 == 0)&&(key_flag2 == 1))PP_SZ2();
- Write_OneChar(0x48); //向18B20的rom中写数据
- Init_DS18B20();
- // Write_OneChar(0xcc);
- if((key_flag1 == 1)&&(key_flag2 == 0))PP_SZ1();
- if((key_flag1 == 0)&&(key_flag2 == 1))PP_SZ2();
- Write_OneChar(0xb8);
- }
- //********读取温度上下限********
- uchar temp_up,temp_down; //温度上下限值
- void read_temprom(void) //应用操作函数3
- {
- uchar i;
- Init_DS18B20();
- // Write_OneChar(0xcc); //跳过读序号列号的操作
- if((key_flag1 == 1)&&(key_flag2 == 0))PP_SZ1();
- if((key_flag1 == 0)&&(key_flag2 == 1))PP_SZ2();
- Write_OneChar(0xbe); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
- i = Read_OneChar(); //读0地址寄存器,扔掉
- i = Read_OneChar(); //读1地址寄存器,扔掉
- temp_up = Read_OneChar(); //读2地址寄存器
- temp_down = Read_OneChar(); //读3地址寄存器
- }
- unsigned char a,b,c;
- /************读取温度程序***********/
- uchar get_temp()
- {
- unsigned char i = 0, t = 0;
- Init_DS18B20();
- //Write_OneChar(0xF0);
- if((key_flag1 == 1)&&(key_flag2 == 0))PP_SZ1();
- if((key_flag1 == 0)&&(key_flag2 == 1))PP_SZ2();
- Write_OneChar(0x44);
- Init_DS18B20();
- if((key_flag1 == 1)&&(key_flag2 == 0))PP_SZ1();
- if((key_flag1 == 0)&&(key_flag2 == 1))PP_SZ2();
- Write_OneChar(0xbe); //读暂存器
- a = Read_OneChar(); //读取匹配ds18B20温度 //a 1001 0111
- b = Read_OneChar();
- c = a & 0x0f;
- a = a >> 4; //a 0000 1001
- b = b << 4; //b 0111 0000
- t = a | b;
- return(t);
- }
- /***********进制转换***********/
- uchar BCD_DEC_conv(unsigned char x)
- {
- unsigned char dec;
- dec = 0x0f & x;
- x = x >> 4;
- dec = dec + x * 10;
- return(dec);
- }
- /**********读取DS18B20的ROM值*************/
- uchar ID[10];ID1[10];
- void Read_DS18B20_rom()
- {
- uchar k;
- Init_DS18B20();
- Write_OneChar(0x33);
- for(k = 0;k <= 8;k++)
- {
- ID[k] = Read_OneChar();
- ID1[k] = BCD_DEC_conv(ID[k]);
- }
- }
- /*********************按键函数********************/
- sbit key1 = P2^0;
- sbit key2 = P2^3;
- sbit key3 = P2^1;
- sbit key4 = P2^2;
- sbit key5 = P2^4;
- sbit key6 = P2^5;
- sbit LED = P3^2;
- bit key1_s,key2_s,key3_s,key4_s,key5_s,key6_s;
- void key(void)
- {
- if(key1 == 0)
- {
- delay(300);
- if(key1 == 0)
- key1_s = 1;
- if((key1 == 1)&&(key1_s = 1))
- {
- key1_s = 0;
- key_flag1 = 1;
- key_flag2 = 0;
- }
- }
- if(key2 == 0)
- {
- delay(300);
- if(key2 == 0)
- key2_s = 1;
- if((key2 == 1)&&(key2_s = 1))
- {
- key2_s = 0;
- key_flag1 = 0;
- key_flag2 = 1;
- }
- }
- if(key3 == 0)
- {
- delay(300);
- if(key3 == 0)
- key3_s = 1;
- if((key3 == 1)&&(key3_s = 1))
- {
- key3_s = 0;
- temp_up++;
- write_temprom(temp_up,temp_down);
- delay(20);
- if(temp_up >= 99)temp_up = 99;
- }
- }
- if(key4 == 0)
- {
- delay(300);
- if(key4 == 0)
- key4_s = 1;
- if((key4 == 1)&&(key4_s = 1))
- {
- key4_s = 0;
- temp_up--;
- write_temprom(temp_up,temp_down);
- delay(20);
- if(temp_up <= 0)temp_up = 0;
- }
- }
- if(key5 == 0)
- {
- delay(300);
- if(key5 == 0)
- key5_s = 1;
- if((key5 == 1)&&(key5_s = 1))
- {
- key5_s = 0;
- temp_down++;
- write_temprom(temp_up,temp_down);
- delay(20);
- if(temp_down >= 98)temp_down = 98;
- }
- }
- if(key6 == 0)
- {
- delay(300);
- if(key6 == 0)
- key6_s = 1;
- if((key6 == 1)&&(key6_s = 1))
- {
- key6_s = 0;
- temp_down--;
- write_temprom(temp_up,temp_down);
- delay(20);
- if(temp_down <= 0)temp_down = 0;
- }
- }
- }
- /****************display显示函数*******************/
- sbit P1_0 = P3^0; //用P1_0表示P3^0
- uchar cp2;
- uchar flash;
- uint temp_num,temp_num1,temp_dot,temp;
- code uchar seven_seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
- 0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//数码管显示数组
- void display0(void)
- {
- P0 = 0xff; //消隐
- switch(cp2) //显示
- {
- case 0: P1_0 = 0;P0 = 0x01;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[8];break;
- case 1: P1_0 = 0;P0 = 0x02;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[2];break;
- case 2:P1_0 = 0;P0 = 0x04;P1_0 = 1;P1_0 = 0;
- P0 = 0xbf | flash; ;break;
- case 3: P1_0 = 0;P0 = 0x08;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[7];break;
- case 4: P1_0 = 0;P0 = 0x10;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[0];break;
- case 5: P1_0 = 0;P0 = 0x20;P1_0 = 1;P1_0 = 0;
- P0 = 0xbf | flash;break;
- case 6: P1_0 = 0;P0 = 0x40;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[7];break;
- case 7: P1_0 = 0;P0 = 0x80;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[1];break;
- }
- cp2++;
- if(cp2 >= 8)cp2 = 0;
- }
- void display1(void)
- {
- P0 = 0xff; //消隐
- switch(cp2) //显示
- {
- case 0:P1_0 = 0;P0 = 0x01;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[temp_num1 % 10%10];break;//显示个位并加上小数点
- case 1:
- {
- if(temp_num < 10)
- {
- P1_0 = 0;P0 = 0x02;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[0];break; //如果温度小于10度,且为正值,十位0不显示
- }
- // if((temp_num > 0x80) && ( temp_num1 < 10))
- // {
- // P1_0 = 0;P0 = 0x02;P1_0 = 1;P1_0 = 0;
- // P0 = 0xbf; break; //如果温度小于10度,且为负值,十位0不显示,只显示"-"
- // }
- P1_0 = 0;P0 = 0x02;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[temp_num1 / 10 % 10];break; //如果温度大于10度,10位正常显示
- }
- case 2: P1_0 = 0;P0 = 0x04;P1_0 = 1;P1_0 = 0;
- P0 = 0xbf|flash;break;
- case 3: P1_0 = 0;P0 = 0x08;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[temp_down%10];break;
- case 4: P1_0 = 0;P0 = 0x10;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[temp_down/10];break;
- case 5: P1_0 = 0;P0 = 0x20;P1_0 = 1;P1_0 = 0;
- P0 = 0xbf|flash;break;
- case 6: P1_0 = 0;P0 = 0x40;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[temp_up%10];break;
- case 7: P1_0 = 0;P0 = 0x80;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[temp_up/10];break;
- }
- }
- void display2(void)
- {
- P0 = 0xff; //消隐
- switch(cp2) //显示
- {
- case 0: P1_0 = 0;P0 = 0x01;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[7]%10];break;
- case 1: P1_0 = 0;P0 = 0x02;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[7]/10];break;
- case 2: P1_0 = 0;P0 = 0x04;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[6]%10]; ;break;
- case 3: P1_0 = 0;P0 = 0x08;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[6]/10];break;
- case 4: P1_0 = 0;P0 = 0x10;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[5]%10];break;
- case 5: P1_0 = 0;P0 = 0x20;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[5]/10];break;
- case 6: P1_0 = 0;P0 = 0x40;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[4]%10];break;
- case 7: P1_0 = 0;P0 = 0x80;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[4]/10];break;
- }
- }
- void display3(void)
- {
- P0 = 0xff; //消隐
- switch(cp2) //显示
- {
- case 0: P1_0 = 0;P0 = 0x01;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[3]%10];break;
- case 1: P1_0 = 0;P0 = 0x02;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[3]/10];break;
- case 2: P1_0 = 0;P0 = 0x04;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[2]%10]; ;break;
- case 3: P1_0 = 0;P0 = 0x08;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[2]/10];break;
- case 4: P1_0 = 0;P0 = 0x10;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[1]%10];break;
- case 5: P1_0 = 0;P0 = 0x20;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[1]/10];break;
- case 6: P1_0 = 0;P0 = 0x40;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[0]%10];break;
- case 7: P1_0 = 0;P0 = 0x80;P1_0 = 1;P1_0 = 0;
- P0 = seven_seg[ID1[0]/10];break;
- }
- }
- /***************主函数******************/
- /***************************/
- #include"reg51.h"
- bit key_flag1 = 0,key_flag2 = 0; //用于打开对应的DS18B20
- #include
- #include
- #include
- uchar cp,cp1,conv;
- /******中断服务函数***********/
- void timer0_isr(void)interrupt 1
- {
- TH0 = (65535 - 2000) / 255;
- TL0 = (65535 - 2000) % 255;
- cp++;
- if(cp >= 250)
- {
- cp1++;
- cp = 0;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
单线多路DS18B20测温.docx
(858.86 KB, 下载次数: 112)
|