單線多路DS18B20測溫,附加讀取DS18B20序列號
第一次發帖寫教程,有問題請多提意見
文件在附件中
基于89C51單片機的單線多路DS18B20多點測溫 Keil文檔 + Protuse仿真
這是寫的第一篇文檔,可能有些地方有點啰嗦,請多多交流。 關于DS18B20的詳細介紹我就不啰嗦了 本人所使用軟件為ISIS,keil4
1.001.jpg (3.64 KB, 下載次數: 89)
下載附件
2017-8-8 17:50 上傳
1.002.jpg (3.56 KB, 下載次數: 95)
下載附件
2017-8-8 17:50 上傳
先看Protuse仿真
1.003.jpg (44.21 KB, 下載次數: 131)
下載附件
2017-8-8 17:50 上傳
圖中使用了1個89c51單片機,兩個DS18B20 ,1個74HC573寄存器,一排8個共陽數碼管,以及按鍵 按鍵1,2用于兩個溫度之間切換 按鍵一按下顯示第一個DS18B20溫度以及其上下限
1.004.jpg (45.26 KB, 下載次數: 96)
下載附件
2017-8-8 17:50 上傳
按鍵二按下顯示第二個DS18B20溫度以及其上下限
1.005.jpg (49.78 KB, 下載次數: 103)
下載附件
2017-8-8 17:50 上傳
其余四個按鍵用于調控溫度上下限設置使用; 附加 讀取DS18B20 的序列號功能(使用不同的顯示函數) 首先要在Protuse中設置DS18B20的序列號
右鍵點擊DS18B20
0.png (219.3 KB, 下載次數: 106)
下載附件
2017-8-8 17:48 上傳
0.png (144.67 KB, 下載次數: 102)
下載附件
2017-8-8 17:48 上傳
B8C534其中的序列號 4以更改
更改后可以用軟件CRC計算器 其對應序列號
計算方式如圖所示
28 為其家族序列號 固定使用
在HEX中輸入 編碼 點擊Calculate 記得到數值 52
0.png (57.89 KB, 下載次數: 128)
下載附件
2017-8-8 17:49 上傳
所以其完整序列號為: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)
2017-8-8 08:53 上傳
點擊文件名下載附件
protuse 仿真 下載積分: 黑幣 -5
|