|
- #include <reg52.h>
- #include <intrins.h>
- #define T_MAX 25 // 最大溫度限定值
- #define T_MIN 22 // 最小溫度限定值
- sbit BUZZ = P1^6;
- //_nop_()函數所在頭文件
- /*----------------音樂函數申明------------------------------*/
- void InitBuzz();
- bit isBuzz = 0; //蜂鳴器是否在響
- /*----------------溫度傳感器申明----------------------------*/
- bit Start18B20(); //初始化DS18B20
- bit Get18B20Temp(int *temp);//讀取溫度
- bit isGetTemp = 0; //是否在獲取溫度
- /*----------------LCD1602顯示模塊申明------------------------*/
- void InitLcd1602(); //LCD1602初始化函數
- void display(); //顯示控制模塊
- /*-------------------LCD1602顯示緩存-------------------------*/
- //LCD1602函數調用申明
- void LcdShowStr(unsigned char x, unsigned char y,unsigned char *str, unsigned char len);
- unsigned char strbuff[4];//格式:“25°C”
- unsigned char code waringStrHot[] = " Hot! ";//報警顯示文字
- unsigned char code waringStrCol[] = " Cold! ";//報警顯示文字
- unsigned char code striswaring[] = " ";//取消報警顯示文字
- /*----------------------其他全局變量-------------------------*/
- int Temp = 0; //讀取到的當前溫度值(16bit二進制)
- int intT; //溫度值的整數和小數部分
- bit iswaring = 0; //是否報警標志位
- void main()
- {
- // int n = 0;
- // char s[1];
- bit isReay = 0;
- bit sta; //是否成功讀取標志
- unsigned int cnt = 0; //檢測標志,主要用于控制檢測溫度的頻率
-
- InitBuzz(); //蜂鳴器初始化
- Start18B20(); //啟動DS18B20
- InitLcd1602(); //初始化LCD1602液晶模塊
-
- while(1)
- {
- if(isReay == 0)
- {
- cnt++;
- }
- if((cnt>28000&&isBuzz == 0)||(cnt>14000&&isBuzz == 1)) //大約0.8s(仿真得到) DS18B20最多750ms轉化好
- {
- cnt = 0;
- isReay = 1;
- }
-
- if(isReay == 1 && isBuzz == 0)
- {
- // n++;
- // s[0] = n+'0';
- // LcdShowStr(0, 0,s, 1);
- isGetTemp = 1;
- sta = Get18B20Temp(&Temp); //讀取當前溫度
- isGetTemp = 0;
- if (sta) //讀取成功時,刷新當前溫度顯示
- {
- intT = Temp >> 4; //分離出溫度值整數部分
- }
- Start18B20(); //重新啟動下一次轉換
-
- if(intT > T_MAX || intT < T_MIN)
- {
- iswaring = 1;
- }else{
- iswaring = 0;
- }
- isReay = 0;
- }
- display();//顯示
- }
- }
- /*-----------------------以下是LCD1602顯示驅動------------------*/
- //定義LCD1602顯示相關的IO接口
- #define LCD1602_DB P0
- sbit LCD1602_RS = P1^0;
- sbit LCD1602_RW = P1^1;
- sbit LCD1602_E = P1^5;
- //顯示控制模塊
- void display()
- {
- static int intTb; //溫度值的整數部分備份
- static bit isBuzzb;
- if(isBuzzb != isBuzz)
- {
- if(isBuzz == 0 && iswaring == 1)
- {
- if(intT > T_MAX)
- {
- LcdShowStr(0,1,waringStrHot,16);
- }else{
- LcdShowStr(0,1,waringStrCol,16);
- }
-
- }else{
- LcdShowStr(0,1,striswaring,11);
- }
- isBuzzb = isBuzz;
- }
- if(intTb != intT)//如果有變化
- {
- /*備份當前值*/
- intTb = intT;
-
- if((intT/10) == 0)strbuff[0] = ' ';else strbuff[0] = ((intT/10)%10)+0x30;//十位
- strbuff[1] = ((intT/1)%10)+0x30;//個位
- LcdShowStr(6,0,strbuff,4); //顯示,初始位置隨意,只要能顯示完整就好
- }
- }
- //等待液晶準備好
- void LcdWaitReady()
- {
- unsigned char sta;
-
- LCD1602_DB = 0xFF;
- LCD1602_RS = 0;
- LCD1602_RW = 1;
- do {
- LCD1602_E = 1; //使能LCD1602
- sta = LCD1602_DB; //讀取狀態字
- LCD1602_E = 0; //避免干擾其他器件
- } while (sta & 0x80); //第七位等于1表示液晶正忙,重復檢測直到第七位等于0為止
- }
- //向LCD1602液晶寫入一字節命令,cmd為待寫入命令值
- void LcdWriteCmd(unsigned char cmd)
- {
- LcdWaitReady();
- LCD1602_RS = 0;
- LCD1602_RW = 0;
- LCD1602_DB = cmd;
- LCD1602_E = 1;
- LCD1602_E = 0;
- }
- //向LCD1602液晶寫入一字節數據,dat為待寫入數據值
- void LcdWriteDat(unsigned char dat)
- {
- LcdWaitReady();
- LCD1602_RS = 1;
- LCD1602_RW = 0;
- LCD1602_DB = dat;
- LCD1602_E = 1;
- LCD1602_E = 0;
- }
- //設置顯示RAM起始地址,亦即光標位置,(x,y)對應屏幕上的字符的坐標
- void LcdSetCursor(unsigned char x, unsigned char y)
- {
- unsigned char addr;
-
- if (y == 0) //由輸入的屏幕坐標計算顯示RAM的地址
- addr = 0x00 + x; //第一行字符地址從0x00起始
- else
- addr = 0x40 + x; //第二行字符地址從0x40起始
- LcdWriteCmd(addr | 0x80); //設置RAM地址
- }
- //在液晶上顯示字符串,(x,y)-對應屏幕上的起始坐標,
- //str-字符串指針,len-需顯示的字符長度
- void LcdShowStr(unsigned char x, unsigned char y,unsigned char *str, unsigned char len)
- {
- LcdSetCursor(x, y); //設置起始地址
- while (len--) //連續寫入len個字符數據
- {
- LcdWriteDat(*str++); //先取str指向的數據,然后str自加1
- }
- }
- void InitLcd1602()//初始化1602液晶
- {
- strbuff[2] = 0XDF;
- strbuff[3] = 'C';
- LcdWriteCmd(0x38); //16*2顯示,5*7點陣,8位數據接口
- LcdWriteCmd(0x0C); //顯示器開,光標關閉
- LcdWriteCmd(0x06); //文字不動,地址自動+1
- LcdWriteCmd(0x01); //清屏
- }
- /*-----------------------以下是溫度傳感器驅動------------------*/
- //DS18B20通信引腳
- sbit IO_18B20 = P3^2;
- void DelayX10us(unsigned char t)
- {
- do {
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- } while (--t);
- /*_nop_()函數在12M晶振中延遲1us,為什么這里是8個_nop_()
- 因為while和--t也是需要時間的,這里不一定是準確的10us/循環
- 只是大致的時間*/
- }
- bit Get18B20Ack() //DS18B20存在檢測函數
- {
- bit ack;
- EA = 0; //關中斷
- IO_18B20 = 0; //拉低引腳
- DelayX10us(50); //延時500us(480us - 960us)
- IO_18B20 = 1; //釋放總線
- DelayX10us(6); //延時60us(15us - 60us)
- ack = IO_18B20; //讀取響應(60us - 240us)
- while(!IO_18B20); //等待DS18B20釋放總線 (60us - 240us)
- EA = 1; //取消關中斷
- return ack; //返回是否存在 (0:存在 1:不存在)
- }
- void Write18B20(unsigned char dat) //寫DS18B20
- {
- unsigned char mask; //臨時變量定義
- EA = 0; //關中斷
- for(mask=0x01; mask!= 0; mask<<=1) //循環發送單個bit位
- {
- IO_18B20 = 0; //拉低(請求讀寫操作)
- _nop_(); //延時(1us < time <= 15us)
- _nop_();
- if((mask&dat) == 0) //按位讀取dat
- IO_18B20 = 0; //本位是0,拉低
- else
- IO_18B20 = 1; //本位是1,拉高
- //上面這個操作DS18B20讀。ㄗ钚r間 0us<time<15us,
- //典型時間 15us,最大時間45us)
- DelayX10us(6); //等待60us(足夠DS18B20讀取)
- IO_18B20 = 1; //釋放總線
- }
- EA = 1; //取消關中斷
- }
- unsigned char Read18B20() //讀DS18B20
- {
- unsigned char dat; //數據緩存變量
- unsigned char mask; //臨時變量
- EA = 0; //關中斷
- for(mask=0x01; mask!=0; mask<<=1)//同上循環按位操作
- {
- IO_18B20 = 0; //讀寫請求
- _nop_(); //等待(1us < time < 15us)
- _nop_();
- IO_18B20 = 1; //初始化讀操作
- _nop_(); //等待DS18B20輸出
- _nop_();
- if(!IO_18B20) //讀
- dat &= ~mask; //“0”
- else
- dat |= mask; //“1”
- DelayX10us(6); //等待DS18B20釋放總線
- }
- EA = 1; //取消關中斷
- return dat; //返回數據
- }
- bit Start18B20() //初始化DS18B20
- {
- bit ack; //存在標志
- ack = Get18B20Ack();//檢測存在
- if(ack == 0) //存在
- { //寫命令使工作
- Write18B20(0xCC); //跳過ROM檢測
- Write18B20(0x44); //啟動溫度轉換
- }
- return ~ack; //返回是否成功(1是,0否)
- }
- bit Get18B20Temp(int *temp) //獲取DS18B20溫度存于temp
- {
- bit ack; //存在標志
- unsigned char LSB, MSB; //數據低/高位
- ack = Get18B20Ack(); //檢測存在
- if(ack == 0) //存在
- { //寫指令
- Write18B20(0xCC); //跳過ROM檢測
- Write18B20(0xBE); //讀寄存器
- LSB = Read18B20(); //讀低位
- MSB = Read18B20(); //讀高位
- *temp = ((int)MSB<<8) + LSB; //合并
- }
- return ~ack; //返回結果(1成功,0失敗)
- }
- //下面是蜂鳴器
- void InterruptTimer0() interrupt 1
- {
- static unsigned int timer;
- TH0 = 0x00;
- TL0 = 0x00;
- timer++;
- if(iswaring)
- {
- if(timer>3000)
- {
- isBuzz = 1;
- if(timer%5==1)
- {
- BUZZ = ~BUZZ;
- }
- if(timer>6000)
- {
- timer = 0;
- }
- }else{
- isBuzz = 0;
- }
- }else{
- isBuzz = 0;
- }
- }
- void InitBuzz()
- {
- TMOD = 0x02;
- TR0 = 1;
- ET0 = 1;
- }
復制代碼
|
|