自己做的,有不足的地方請指出,一起學習進步!
這個設計由單片機最小系統、溫度傳感模塊 (DS18B20)、顯示模塊(LCD1602)、按鍵模塊和聲光報警模塊組成。
功能:①顯示 時—分—秒和實時溫度;②可以通過按鍵調整顯示時間,還可以調整聲光報警(7秒后自動關閉)的時間,并且還可以手動關閉聲光報警
電路圖和系統各框圖:
各模塊.png (52.78 KB, 下載次數: 33)
下載附件
2019-1-31 21:33 上傳
1.png (9.69 KB, 下載次數: 46)
下載附件
2019-1-31 21:34 上傳
3 (1).png (14.99 KB, 下載次數: 53)
下載附件
2019-1-31 21:34 上傳
3 (2).png (10.8 KB, 下載次數: 42)
下載附件
2019-1-31 21:34 上傳
4.png (34.16 KB, 下載次數: 33)
下載附件
2019-1-31 21:34 上傳
單片機程序:
- #include <reg51.h>
- #include <intrins.h> //包含_nop_空函數指令的頭文件
- #include <stdio.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define out P0
- uchar date[20]; //存放溫度值
- sbit RS=P3^5; // 寄存器選擇(1——數據寄存器;0——命令/狀態寄存器)
- sbit RW=P3^6; // 讀/寫操作選擇(1——讀;0——寫)
- sbit E=P3^4; // 使能信號
- sbit voise=P2^3; //蜂鳴器鏈接口
- sbit beeled=P1^7; //LED燈接口
- sbit CON = P3^0;
- sbit UP = P3^1;
- sbit DOWN = P3^2;
- sbit START= P3^3;
- sbit ds = P2^2; //溫度傳感器的輸入/輸出引腳
- void keyScan(); //按鍵調時間
- void keyclockdown(); //按下按鍵關閉鬧鐘
-
- void init(); //定時器T0的初始化
- void TIME(); //實現時間變化
- void lcd_initial(); //lcd1602初始化
- void check_busy(); //檢查忙碌標志位
- void write_command(uchar com); //寫命令
- void wtite_data(uchar dat); //寫數據
- void string(uchar ad,uchar *s); //顯示字符串
- uchar dis[ ]={0x30,0x38,0x2d,0x35,0x39,0x2d,0x35,0x37,'\0'}; //dis[]={0,8,-,5,9,-,5,7}
- void delayMs(uint a);
- void delay(uint);
- void bee(); //蜂鳴器
- uchar flag;
- uchar num;
- uchar over=0;
- void aoto(); //7s后自動關閉鬧鈴
- uchar a=0x30,b=0x38,c=0x30,d=0x30,e=0x30,f=0x30;
- void dsInit(); //DS18B20復位,初始化函數
- void dsWait();
- bit readBit(); //讀一位數據函數
- unsigned char readByte(); //讀一個字節數據函數
- void writeByte(unsigned char dat); //向DS18B20寫一個字節數據函數
- void sendChangeCmd(); //DS18B20開始獲取溫度并轉換
- void sendReadCmd(); //讀取寄存器中存儲的溫度數據
- int getTmpValue(); //得到溫度
- //*************************************************************
- void main()
- {
- float temp=0.0;
- lcd_initial (); //液晶顯示初始化
- init(); //定時器的初始化
- while(1)
- {
- bee();
- keyScan(); //按鍵調時間
- keyclockdown(); //按下按鍵關閉鬧鐘
- aoto();
- delay(200);
- string(0x80,"TIME:");
- delay(200);
- string(0xcb,"^C");
- string(0x86,dis);
- delay(200);
- temp=getTmpValue()/100.0;
- sendChangeCmd();
- sprintf(date,"TEMP: %0.2f",temp);
- string(0xc0,date);
- delay(200);
- }
- }
- //**************************************************************
- //延遲函數
- void delayMs(uint a)
- {
- uint i, j;
- for(i = a; i > 0; i--)
- for(j = 100; j > 0; j--);
- }
- void delay (uint j) //延遲
- {
- uchar i=10;
- for(;j>0;j--)
- {
- while(--i);
- i=10;
- while(--i);
- i=10;
-
- }
- }
- //********************************************************
- void init() //定時器的初始化
- {
- TMOD=0x01; //定時器T0的方式1
- TH0=(65536-50000)/256; //50ms
- TL0=(65536-50000)%256;
- EA=1; //總中斷允許
- ET0=1; //啟動定時器T0中斷
- TR0=1; //啟動定時器T0
- }
- void timer0() interrupt 1 //T0中斷程序
- {
- TH0=(65536-50000)/256; //50ms
- TL0=(65536-50000)%256;
- num++ ;
- TIME(); //實現時間變化
- }
- //***********************************************************
- void lcd_initial () //液晶顯示初始化
- {
- write_command(0x38); //寫入命令0x38;8位2行顯示,5×7點陣字符
- _nop_();
- write_command(0x0c); //寫入命令0x0c;整體顯示,光標關閉,無閃爍
- _nop_();
- write_command(0x06); //寫入命令0x05;光標右移
- _nop_();
- write_command(0x01); //寫入命令0x01;清屏
- delay(1);
- }
- void check_busy () //檢查忙標志
- {
- uchar dt; //dt變量單元 ,忙狀態標志 0:不忙,0x80:忙
- do
- {
- dt=0xff; // 先往數據端口賦高電平,便于讀數據
- E=0;
- RS=0;
- RW=1; //讀
- E=1; // 數據端口讀寫使能
- dt=out; // 讀數據端口的值
- }while(dt&0x80); // 如果忙位BF為1,就一直讀端口數據,直到為0才退出忙判斷。
- // BF:忙標志位,為數據端口的BIT7位。所以為0x80。
- E=0;
- }
- void write_command (uchar com) //寫命令
- {
- check_busy();
- E=0; //RS=E=0;才可以寫入命令
- RS=0;
- RW=0;
- out=com;
- E=1;
- _nop_(); //空操作1個機械周期
- E=0;
- delay(1);
- }
- void write_data (uchar dat) //寫數據
- {
- check_busy(); //檢測忙標志位BF=1則等待,BF=0則可對LCD寫入
- E=0; //寫數據時,E為正脈沖,所以E置0
- RS=1; //RS=1,RW=1時,才可以寫入數據
- RW=0;
- out=dat; //將數據dat從P0口輸出,即寫入LCD
- E=1; //E產生正跳變
- _nop_(); //空操作1個機械周期
- E=0; //E由高電平變低電平,寫操作結束
- delay(1);
- }
- void string(uchar ad,uchar *s)
- {
- write_command(ad);
- while(*s>0)
- {
- write_data(*s++); //輸出字符傳,指針加1
- delay(1);
- }
- }
- //*****************************************************
- void TIME() //實現時分秒變化
- {
- if(num==20)
- {
- num=0;
- over++;
- dis[7]++;
- if(dis[7]>0x39) //秒
- {
- dis[7]=0x30;
- dis[6]++;
- }
- if(dis[6]==0x36)
- {
- dis[6]=0x30;
- dis[4]++;
- }
- if(dis[4]>0x39) //分
- {
- dis[4]=0x30;
- dis[3]++;
- }
- if(dis[3]==0x36)
- {
- dis[3]=0x30;
- dis[1]++;
- }
- if(dis[1]>0x39) //時
- {
- dis[1]=0x30;
- dis[0]++;
- }
- if(dis[0]==0x32)
- {
- if(dis[1]>0x33)
- {
- dis[0]=0x30;
- dis[1]=0x30;
- }
- }
- }
- }
- //*******************************************************
- //掃描鍵盤程序
- void keyScan()
- {
- static uchar key;
- if(!CON){ while(!CON);key++;}
- if(key)
- {
- TR0=0; //時間先停下,再調整
- P1=~(key%7); //指示燈
- switch(key%7)
- {
- case 6: if(!UP) //秒的個位
- {
- while(!UP);
- dis[7]++;
- if(dis[7]>0x39) dis[7]=0x30;
- }
- if(!DOWN)
- {
- while(!DOWN);
- dis[7]--;
- if(dis[7]<0x30) dis[7]=0x39;
- }
- break;
- case 5: if(!UP) //秒的十位
- {
- while(!UP);
- dis[6]++;
- if(dis[6]>0x35) dis[6]=0x30;
- }
- if(!DOWN)
- {
- while(!DOWN);
- dis[6]--;
- if(dis[6]<0x30) dis[6]=0x35;
- }
- break;
- case 4: if(!UP) //分的個位
- {
- while(!UP);
- dis[4]++;
- if(dis[4]>0x39) dis[4]=0x30;
- }
- if(!DOWN)
- {
- while(!DOWN);
- dis[4]--;
- if(dis[4]<0x30) dis[4]=0x39;
- }
- break;
- case 3: if(!UP) //分的十位
- {
- while(!UP);
- dis[3]++;
- if(dis[3]>0x35) dis[3]=0x30;
- }
- if(!DOWN)
- {
- while(!DOWN);
- dis[3]--;
- if(dis[3]<0x30) dis[3]=0x35;
- }
- break;
- case 2: if(!UP) // 時的個位
- {
- while(!UP);
- dis[1]++;
- if(dis[0]==0x30||dis[0]==0x31)
- {
- if(dis[1]>0x39) dis[1]=0x30;
- }
- if(dis[0]==0x32)
- {
- if(dis[1]>0x33) dis[1]=0x30;
- }
- }
- if(!DOWN)
- {
- while(!DOWN);
- dis[1]--;
- if(dis[0]==0x30||dis[0]==0x31)
- {
- if(dis[1]<0x30) dis[1]=0x39;
- }
- if(dis[0]==0x32)
- {
- if(dis[1]<0x30) dis[1]=0x33;
- }
- }
- break;
- case 1: if(!UP) //時的十位
- {
- while(!UP);
- dis[0]++;
- if(dis[0]>0x32) dis[0]=0x30;
- }
- if(!DOWN)
- {
- while(!DOWN);
- dis[0]--;
- if(dis[0]<0x30) dis[0]=0x32;
- }
- break;
- }
- }
- if(!START)
- {
- while(!START);
- TR0=1;
- key=0;
- P0=0xff;
- }
- }
- //*******************************************************************************蜂鳴器
- void bee()
- {
- keyclockdown();
- if(dis[0]==a&&dis[1]==0x38&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //8點
- {
- flag=1;
- }
- if(dis[0]==a&&dis[1]==0x39&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //9點
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x30&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //10點
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x31&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) // 11點
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x32&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) // 12點
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x33&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //13點
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x34&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //14點
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x35&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //15點
- {
- flag=1;
- }if(dis[0]==0x31&&dis[1]==0x36&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //16點
- {
- flag=1;
- }if(dis[0]==0x31&&dis[1]==0x37&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //17點
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x38&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //18點
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x39&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //19點
- {
- flag=1;
- }
- if(dis[0]==0x32&&dis[1]==0x30&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //20點
- {
- flag=1;
- }
- if(flag==1)
- {voise=0;beeled=0;}
- else
- {voise=1;beeled=1; }
- }
- //*************************按下按鍵關閉鬧鐘
- void keyclockdown()
- {
- if(!START) {flag=0;beeled=1;}
- }
- //*********************************************
- void aoto() //7s后自動關閉鬧鈴
- {
- if(flag==1)
- {
- if(over==10) {flag=0;over=0;}
- }
- }
- /******************溫度部分**********************/
- void dsInit() //DS18B20復位,初始化函數
- {
-
- unsigned int i;
- ds = 0;
- i = 100;
- while(i>0) i--;
- ds = 1;
- i = 4;
- while(i>0) i--;
- }
-
- void dsWait() //
- {
- unsigned int i;
- while(ds);
- while(~ds);
- i = 4;
- while(i > 0) i--;
- }
- bit readBit() //讀一位數據函數
- {
- unsigned int i;
- bit b;
- ds = 0;
- i++;
- ds = 1;
- i++; i++;
- b = ds;
- i = 8;
- while(i>0) i--;
- return b;
- }
- unsigned char readByte() //讀一個字節數據函數
- {
- unsigned int i;
- unsigned char j, dat;
- dat = 0;
- for(i=0; i<8; i++)
- {
- j = readBit();
-
- dat = (j << 7) | (dat >> 1); //讀出的數據最低位在最前面,這樣剛好一個字節在dat里
- }
- return dat;
- }
- void writeByte(unsigned char dat) //向DS18B20寫一個字節數據函數
- {
- unsigned int i;
- unsigned char j;
- bit b;
- for(j = 0; j < 8; j++)
- {
- b = dat & 0x01;
- dat >>= 1;
-
- if(b) //寫1
- {
- ds = 0;i++; i++;
- ds = 1;
- i = 8; while(i>0) i--;
- }
- else
- {
- ds = 0; //寫0
- i = 8; while(i>0) i--;
- ds = 1;
- i++; i++;
- }
- }
- }
- void sendChangeCmd() //DS18B20開始獲取溫度并轉換
- {
- dsInit();
- dsWait();
- delayMs(1);
- writeByte(0xcc); //寫跳過讀ROM指令
- writeByte(0x44); //寫溫度轉換指令
- }
- void sendReadCmd() //讀取寄存器中存儲的溫度數據
- {
- dsInit();
- dsWait();
- delayMs(1);
- writeByte(0xcc);
- writeByte(0xbe);
- }
- int getTmpValue() //得到溫度
- {
- unsigned int tmpvalue;
- int value;
- float t;
- unsigned char low, high;
- sendReadCmd();
-
- low = readByte(); //讀低8位
- high = readByte(); //讀高8位
-
- tmpvalue = high;
- tmpvalue <<= 8; //兩個字節組合為1個字節
- tmpvalue |= low;
- value = tmpvalue;
- t = value * 0.0625; //溫度在寄存器中為12位,分辨率為0.0625度
- value = t * 100 + (value > 0 ? 0.5 : -0.5); //乘以100表示小數點后面只取1位,加0.5是四舍五入,大于0加0.5, 小于0減0.5。
- return value; //value是整型
- }
- //*****************************************************
復制代碼
全部資料51hei下載地址:
ds18b20 lcd1602 聲光報警_仿真電路.zip
(21.9 KB, 下載次數: 21)
2019-1-31 21:50 上傳
點擊文件名下載附件
仿真電路 下載積分: 黑幣 -5
ds18b20 lcd1602 聲光報警_程序.zip
(101.46 KB, 下載次數: 24)
2019-1-31 21:50 上傳
點擊文件名下載附件
程序 下載積分: 黑幣 -5
系統框圖.zip
(62.43 KB, 下載次數: 9)
2019-1-31 21:45 上傳
點擊文件名下載附件
系統框圖 下載積分: 黑幣 -5
|