利用51單片機DS18B20和1602做的溫度計,可以實現溫度上限報警,進行華氏和攝氏度的轉換,利用三個按鍵實現這些功能。
單片機源程序如下:
- /*作者:王先生
- 51單片機:清華電子的板
- #include<reg52.h>
- #include<intrins.h>
- #include<math.h>
- typedef unsigned char uchar;
- typedef unsigned int uint;
- sbit DS = P2^2;//DS18B20接口
- sbit BP = P2^3;//蜂鳴器
- sbit DU = P2^6;//數碼管段選碼
- sbit WE = P2^7;//數碼管位選碼
- sbit key_s1 = P3^0;
- sbit key_s2 = P3^1;
- sbit key_s3 = P3^2;
- sbit EN = P3^4;//LCD使能端
- sbit RS = P3^5;//LCD數據命令選擇端
- sbit RW = P3^6;//LCD讀寫選擇端
- uint FF;
- uint DD,LL;
- uint K=0;
- uint M=0;
- uint s=0;
- void delayus(uchar us)
- {
- while(us--);//us--要6.5us,進入一次函數11.95us;
- } //微秒延時
- void LCD_READ_BUSY() //忙不忙
- {
- uchar busy;
- P0 = 0XFF;
- RS = 0;
- RW = 1;
- do
- {
- EN = 1;
- busy = P0;
- EN = 0;
- }while(busy&0X80);
- EN = 1;
- }
- void LCD_WRITE_CMD(uchar cmd)//寫一個字節命令流程
- {
- LCD_READ_BUSY();//判斷忙不忙
- RS = 0;
- RW = 0;
- P0 = cmd;
- EN = 1;
- EN = 0;
- }
- void LCD_WRITE_DATE(uchar dat)//寫一個字節數據
- {
- LCD_READ_BUSY();
- RS = 1;
- RW = 0;
- P0 = dat;
- EN = 1;
- EN = 0;
- }
- void LCD_OneChar(uchar x, uchar y,uchar dat)//指定位置顯示字符
- {
- if(y)
- x |= 0x40;//位選或
- x |= 0x80;
- LCD_WRITE_CMD(x);
- LCD_WRITE_DATE(dat);
- }
- void LCD_Str(uchar x, uchar y, uchar *str)//指定位置顯示字符串
- {
- if(y)
- x |= 0x40;
- x |= 0x80;
- LCD_WRITE_CMD(x);
- while(*str != '\0')
- {
- LCD_WRITE_DATE(*str++);
- }
- }
- void LCD_Init() // 初始化
- {
- LCD_WRITE_CMD(0x38); // 設置16*2顯示,5*7點陣,8位數據接口
- LCD_WRITE_CMD(0x0c); //開顯示
- LCD_WRITE_CMD(0x06); //讀寫一字節后地址指針加1
- LCD_WRITE_CMD(0x01); //清除顯示
- }
- bit ds_init()//單總線初始化程序
- {
- bit i;
- DS = 1;
- _nop_();
- DS = 0;
- delayus(75);//拉低總線;保持480us以上,75*6.5+11.95=499.45ms
- DS = 1;//釋放總線
- delayus(1);//1*6.5+11.95=18.45us等待發回信號(15-60us)
- i = DS;
- delayus(20);//讀取存在信號的時間20*6.5+11.95=141.95us
- DS = 1; //釋放總線
- _nop_();
- return(i);//i=0代表DS18B20已經準備好了
- }
- void displayN(int c)//溫度正常顯示
- {
- uint i;
- uchar M1,M2,M3,M4;
- uchar TestStr[] = {"Tem:"};
- uchar TestStr1[] = {"DB:WYX"};
- /*if(c<0)
- {m = 2;}
- else if(c>=0)
- {m = 0;}*/
- i = abs(c);
- M1 = i/1000;//千位
- M2 = i%1000/100;//百位
- M3 = i%1000%100/10;//十位
- M4 = i%10; //個位
-
- DU = 0;
- WE = 0;//關閉數碼管顯示
- LCD_Init();//1602初始化
- LCD_Str(0, 0, &TestStr[0]); //顯示字符串
- LCD_Str(0, 1, &TestStr1[0]); //顯示字符串
- LCD_OneChar(6 , 0, 43+s);//正負號
- LCD_OneChar(7, 0, M1+48); //顯示溫度
- LCD_OneChar(8, 0, M2+48);
- LCD_OneChar(9 , 0, M3+48);//正負號
- LCD_OneChar(10, 0, 46);
- LCD_OneChar(11, 0, M4+48);
- LCD_OneChar(12, 0, 39);
- LCD_OneChar(13, 0, 67);
- LCD_OneChar(15, 0, 78+DD*10); //顯示蜂鳴器開關
- LCD_OneChar(15, 1, 78+LL*10); //顯示指示燈開關
- }
- void displayM(int c)
- {
- uchar M1,M2,M3,M4;
- int i,m;
- uchar TestStr[] = {"Tem:"};
- uchar TestStr1[] = {"High"};
- if(c<0)
- {m = 2;}
- else if(c>=0)
- {m = 0;}
- i = abs(c);
- M1 = i/1000;//千位
- M2 = i%1000/100;//百位
- M3 = i%1000%100/10;//十位
- M4 = i%10; //個位
-
- DU = 0;
- WE = 0;//關閉數碼管顯示
- LCD_Init();//1602初始化
- LCD_Str(0, 0, &TestStr[0]); //顯示字符串
- LCD_Str(7, 1, &TestStr1[0]); //顯示字符串
- LCD_OneChar(6 , 0, 43+m);//正負號
- LCD_OneChar(7, 0, M1+48); //顯示溫度
- LCD_OneChar(8, 0, M2+48);
- LCD_OneChar(9 , 0, M3+48);//正負號
- LCD_OneChar(10, 0, 46);
- LCD_OneChar(11, 0, M4+48);
- LCD_OneChar(12, 0, 39);
- LCD_OneChar(13, 0, 67);
- LCD_OneChar(15, 0, 78+DD*10); //顯示蜂鳴器開關
- LCD_OneChar(15, 1, 78+LL*10); //顯示指示燈開關
- }
- void displayL(int c)
- {
- uchar M1,M2,M3,M4;
- int i,m;
- uchar TestStr[] = {"Tem:"};
- uchar TestStr1[] = {"Low"};
- if(c<0)
- {m = 2;}
- else if(c>=0)
- {m = 0;}
- i = abs(c);
- M1 = i/1000;//千位
- M2 = i%1000/100;//百位
- M3 = i%1000%100/10;//十位
- M4 = i%10; //個位
-
- DU = 0;
- WE = 0;//關閉數碼管顯示
- LCD_Init();//1602初始化
- LCD_Str(0, 0, &TestStr[0]); //顯示字符串
- LCD_Str(7, 1, &TestStr1[0]); //顯示字符串
- LCD_OneChar(6 , 0, 43+m);//正負號
- LCD_OneChar(7, 0, M1+48); //顯示溫度
- LCD_OneChar(8, 0, M2+48);
- LCD_OneChar(9 , 0, M3+48);//正負號
- LCD_OneChar(10, 0, 46);
- LCD_OneChar(11, 0, M4+48);
- LCD_OneChar(12, 0, 39);
- LCD_OneChar(13, 0, 67);
- LCD_OneChar(15, 0, 78+DD*10); //顯示蜂鳴器開關
- LCD_OneChar(15, 1, 78+LL*10); //顯示指示燈開關
- }
- void displayNF(int c)
- {
- uchar M1,M2,M3,M4;
- uchar TestStr[] = {"Tem:"};
- uchar TestStr1[] = {"DB:WYX"};
- uint p,i;
- /*if(c<0)
- {m = 2;}
- else
- {m = 0;}*/
- i = abs(c);
- p = i*9/5+320;
- M1 = p/1000;
- M2 = p%1000/100;//百位
- M3 = p%1000%100/10;//十位
- M4 = p%10; //個位
-
- DU = 0;
- WE = 0;//關閉數碼管顯示
- LCD_Init();//1602初始化
- LCD_Str(0, 0, &TestStr[0]); //顯示字符串
- LCD_Str(0, 1, &TestStr1[0]); //顯示字符串
- LCD_OneChar(6 , 0, 43+s);//顯示正負
- LCD_OneChar(7, 0, M1+48); //顯示溫度
- LCD_OneChar(8, 0, M2+48);
- LCD_OneChar(9, 0, M3+48);
- LCD_OneChar(10, 0, 46);
- LCD_OneChar(11, 0, M4+48);
- LCD_OneChar(12, 0, 39);
- LCD_OneChar(13, 0, 67+FF);
- LCD_OneChar(15, 0, 78+DD*10); //顯示蜂鳴器開關
- LCD_OneChar(15, 1, 78+LL*10); //顯示指示燈開關
- }
- void displayMF(int c)
- {
- uchar M1,M2,M3,M4;
- uchar TestStr[] = {"Tem:"};
- uchar TestStr1[] = {"High"};
- uint p,m,i;
- if(c<0)
- {m = 2;}
- else
- {m = 0;}
- i = abs(c);
- p = i*9/5+320;
- M1 = p/1000;
- M2 = p%1000/100;//百位
- M3 = p%1000%100/10;//十位
- M4 = p%10; //個位
-
- DU = 0;
- WE = 0;//關閉數碼管顯示
- LCD_Init();//1602初始化
- LCD_Str(0, 0, &TestStr[0]); //顯示字符串
- LCD_Str(7, 1, &TestStr1[0]); //顯示字符串
- LCD_OneChar(6 , 0, 43+m);//顯示正負
- LCD_OneChar(7, 0, M1+48); //顯示溫度
- LCD_OneChar(8, 0, M2+48);
- LCD_OneChar(9, 0, M3+48);
- LCD_OneChar(10, 0, 46);
- LCD_OneChar(11, 0, M4+48);
- LCD_OneChar(12, 0, 39);
- LCD_OneChar(13, 0, 67+FF);
- LCD_OneChar(15, 0, 78+DD*10); //顯示蜂鳴器開關
- LCD_OneChar(15, 1, 78+LL*10); //顯示指示燈開關
- }
- void displayLF(int c)
- {
- uchar M1,M2,M3,M4;
- uchar TestStr[] = {"Tem:"};
- uchar TestStr1[] = {"Low"};
- uint p,m,i;
- if(c<0)
- {m = 2;}
- else
- {m = 0;}
- i = abs(c);
- p = i*9/5+320;
- M1 = p/1000;
- M2 = p%1000/100;//百位
- M3 = p%1000%100/10;//十位
- M4 = p%10; //個位
-
- DU = 0;
- WE = 0;//關閉數碼管顯示
- LCD_Init();//1602初始化
- LCD_Str(0, 0, &TestStr[0]); //顯示字符串
- LCD_Str(7, 1, &TestStr1[0]); //顯示字符串
- LCD_OneChar(6 , 0, 43+m);//顯示正負
- LCD_OneChar(7, 0, M1+48); //顯示溫度
- LCD_OneChar(8, 0, M2+48);
- LCD_OneChar(9, 0, M3+48);
- LCD_OneChar(10, 0, 46); //.
- LCD_OneChar(11, 0, M4+48);
- LCD_OneChar(12, 0, 39); //'
- LCD_OneChar(13, 0, 67+FF);//C或F
- LCD_OneChar(15, 0, 78+DD*10);//X或者N
- LCD_OneChar(15, 1, 78+LL*10); //顯示指示燈開關
- }
- void displayLE()
- {
- uchar TestSt1[] = {"Error"};
- uchar TestSt2[] = {"Low#High"};
- LCD_Init();
- LCD_Str(5, 0, &TestSt1[0]);
- LCD_Str(4, 1, &TestSt2[0]);
- LCD_OneChar(15, 0, 78+DD*10); //顯示蜂鳴器開關
- LCD_OneChar(15, 1, 78+LL*10); //顯示指示燈開關
-
- }
- void write_byte(uchar dat)//寫一個字節
- {
- uchar i;
- for(i=0;i<8;i++)//一次寫一位,一個字節循環8次
- {
- DS = 0;
- _nop_();//產生寫時序(15US內滿足要求)
- DS = dat&0X01; //與
- delayus(9);//延時大于60US 9*6.5+11.95=70.45us 同時滿足寫0寫1
- DS = 1;//釋放總線
- _nop_();
- dat>>=1;//右移一位
- }
- }
- uchar read_byte()//讀一個字節
- {
- uchar i,j,dat;
- for(i=0;i<8;i++)
- {
- DS = 0;
- _nop_();//產生讀時序
- DS = 1;
- _nop_();//釋放總線
- j = DS;
- delayus(9);//讀取數據大于60US 9*6.5+11.95=70.45us
- DS = 1;
- _nop_();
- dat = (j<<7)|(dat>>1);
- }
- return(dat);
- }
- void beep(int m,gao,di)//按鍵與警報程序
- {
- if(m>=gao)
- {
- if(di<=gao) //判斷最低報警溫度是否低于最高報警溫度
- {
- BP = DD;
- P1 = 0XEE+LL*0X11;
- }
- else if(di>gao)
- {
- BP = 1;
- P1 = 0X7E+LL*0X81;
- }
- }
- else if(m<=di)
- {
- if(di<=gao) //判斷最低報警溫度是否低于最高報警溫度
- {
- BP = DD;
- P1=0X77+LL*0X88;
- }
- else if(di>gao)
- {
- BP = 1;
- P1 = 0X7E+LL*0X81;
- }
- }
- else
- {
- if(di<=gao) //判斷最低報警溫度是否低于最高報警溫度
- {
- BP = 1;
- P1=0XBB+LL*0X44;
- }
- else if(di>gao)
- {
- BP = 1;
- P1 = 0X7E+LL*0X81;
- }
- }
- }
- void main()
- {
- int i,h;
- uint j=0;
- float t;
- int gao=330,di=270;
- uchar L,H;
- while(1)
- {
- ds_init();//初始化函數
- write_byte(0XCC);//發送跳躍ROM指令(0xcc)
- write_byte(0X44);//發送溫度轉換指令(0X44)
- ds_init();//初始化DS18B20
- write_byte(0XCC);//發送跳躍ROM指令(0xcc)
- write_byte(0XBE);//讀取DS18B20暫存器的值(0Xbe)
- L = read_byte(); //溫度低字節
- H = read_byte();//溫度高字節
- i = H;
- i <<=8;
- i|=L;//與,把L寫到低字節里
- if(H >= 0x08) //判斷是否為負數
- {
- i = ~i + 1;//負數是以補碼的形式存放的需要我們需要取反加1
- s = 2; //顯示負數符號
- }
- else s = 0;
- t=i*0.0625;
- i = t*10;//10.125--101.25--101.75--10.2(四舍五入)
-
- if(key_s1 == 0) //第一位選程序
- {
- delayus(10);//防抖
- if(key_s1 == 0)
- {
- j=j+1 ;
- if(j>=3)
- j=0;
- }
- while(!key_s1);
- }
- if(j==1) //調最高溫度
- {
- h = gao;
- if(key_s2 == 0)//按鍵2增加溫度
- {
- delayus(20);//防抖
- if(key_s2 == 0)
- {
- h=h+1 ;
- }
- while(!key_s2);
- }
- else if(key_s3 == 0)//按鍵3減小溫度
- {
- delayus(20);
- if(key_s3 == 0)
- {
- h=h-1;
- }
- while(!key_s3);
- }
- if(K==0)
- {
- displayM(h);
- }
- else if(K==1)
- {
- // p = h*(5/9)+320;
- displayMF(h);
- }
- gao = h;
- }
- else if(j==2)//調最低溫度
- {
- h = di;
- if(key_s2 == 0)//按鍵2增加溫度
- {
- delayus(20);//防抖
- if(key_s2 == 0)
- {
- h=h+1 ;
- }
- while(!key_s2);
- }
- else if(key_s3 == 0)//按鍵3減小溫度
- {
- delayus(20);
- if(key_s3 == 0)
- {
- h=h-1;
- }
- while(!key_s3);
- }
- if(K==0)
- {
- displayL(h);
- }
- else if(K==1)
- {
- // p = h*(5/9)+320;
- displayLF(h);
- }
- di = h;
- }
- else if(j==0) //顯示溫度
- {
- if(key_s2 == 0)//溫度轉化
- {
- delayus(20);//防抖
- if(key_s2 == 0)
- {
- K=K+1 ;
- if(K>1)
- K=0;
- }
- while(!key_s2);
- }
- if(key_s3 == 0)//蜂鳴器與指示燈開關
- {
- delayus(20);//防抖
- if(key_s3 == 0)
- {
- M=M+1 ;
- if(M>3)
- M=0;
- }
- while(!key_s3);
- }
- if(K==0)
- {
- FF=0; //攝氏度
- }
- else if(K==1)
- {
- FF=3; //華氏
- }
- /****************判斷蜂鳴器與指示燈開關程序*******************/
- if(M==0) //蜂鳴器關指示燈開
- {
- DD=1;
- LL=0; //蜂鳴器關
- }
- else if(M==1) //蜂鳴器開指示燈開
- {
- DD=0;
- LL=0;
- }
- else if(M==2) //蜂鳴器開指示燈關
- {
- DD=0;
- LL=1;
- }
- else if(M==3) //蜂鳴器關指示燈關
- {
- DD=1;
- LL=1;
- }
- /*****************溫度顯示及判斷程序執行*****************/
- if(K==0) //選擇顯示攝氏度
- {
- if(di>gao)
- displayLE();
- else if(di<=gao)
- displayN(i);
- }
- else if(K==1) //選擇顯示華氏
- {
- if(di>gao)
- displayLE();
- else if(di<=gao)
- displayNF(i);
- }
- beep(i,gao,di);//報警判斷
- }
- }
- }
- //打開是85.0,因為初始值是85.
復制代碼
|