基于51單片機環境監測系統,溫度濕度,光照度檢測,可設置上下限報警可加繼電器控制加熱器件,風扇等模塊,蜂鳴器,LED作為狀態輸出,資料齊全
電路原理圖如下:
實物圖:
單片機源程序如下:
- //阿陽工作室QQ113703571
- #include <reg52.h> // 頭文件包含
- #include <intrins.h>
- #define uchar unsigned char // 以后unsigned char就可以用uchar代替
- #define uint unsigned int // 以后unsigned int 就可以用uint 代替
- sfr ISP_DATA = 0xe2; //數據寄存器
- sfr ISP_ADDRH = 0xe3; //地址寄存器高八位
- sfr ISP_ADDRL = 0xe4; //地址寄存器低八位
- sfr ISP_CMD = 0xe5; //命令寄存器
- sfr ISP_TRIG = 0xe6; //命令觸發寄存器
- sfr ISP_CONTR = 0xe7; //控制寄存器
- sbit LcdRs_P = P2^7; // 1602液晶的LcdRs_P管腳
- sbit LcdRw_P = P2^6; // 1602液晶的LcdRw_P管腳
- sbit LcdEn_P = P2^5; // 1602液晶的LcdEn_P管腳
- sbit DHT11_P = P1^0; // 溫濕度傳感器DHT11_P數據接入
- sbit SDA_P = P3^5; // 光照模塊IIC數據引腳定義
- sbit SCL_P = P3^6; // 光照模塊IIC時鐘引腳定義
- sbit LedTH_P = P1^2; // 溫度過高報警指示燈
- sbit LedTL_P = P1^1; // 溫度過低報警指示燈
- sbit LedHH_P = P1^4; // 濕度過高報警指示燈
- sbit LedHL_P = P1^3; // 濕度過低報警指示燈
- sbit LedLH_P = P1^6; // 光線過高報警指示燈
- sbit LedLL_P = P1^5; // 光線過低報警指示燈
- sbit Buzzer_P = P2^0; // 蜂鳴器
- sbit KeySet_P = P3^2; // “設置”按鍵的管腳
- sbit KeyDown_P = P3^3; // “減”按鍵的管腳
- sbit KeyUp_P = P3^4; // “加”按鍵的管腳
- uchar temp; // 保存溫度
- uchar humi; // 保存濕度
- uint light; // 保存光照
- uchar AlarmTL; // 溫度下限報警值
- uchar AlarmTH; // 溫度上限報警值
- uchar AlarmHL; // 濕度下限報警值
- uchar AlarmHH; // 濕度上限報警值
- uint AlarmLL; // 光強下限報警值
- uint AlarmLH; // 光強上限報警值
- /*********************************************************/
- // 單片機內部EEPROM不使能
- /*********************************************************/
- void ISP_Disable()
- {
- ISP_CONTR = 1; //控制寄存器賦值為0
- ISP_ADDRH = 1; //地址寄存器高八位賦值為0
- ISP_ADDRL = 1; //地址寄存器低八位賦值為0
- }
- /*********************************************************/
- // 從單片機內部EEPROM讀一個字節
- /*********************************************************/
- unsigned char ReadE2PROM(unsigned int addr)
- {
- ISP_DATA = 0x08; //數據寄存器清零
- ISP_CONTR = 0x83; //允許改變內部E2PROM,存取數據速度為5MHz
- ISP_CMD = 0x01; //讀命令
- ISP_ADDRH = (unsigned char)(addr >> 8); //輸入高8位地址
- ISP_ADDRL = (unsigned char)(addr & 0xff); //輸入低8位地址
- ISP_TRIG = 0x66; //先向命令觸發寄存器寫入0x46
- ISP_TRIG = 0x99; //再向命令觸發寄存器寫入0xb9,完成觸發
- _nop_(); //延時大約1us
- ISP_Disable(); //單片機內部EEPROM不使能
-
- return ISP_DATA; //返回讀的數據
- }
- /*********************************************************/
- // 從單片機內部EEPROM寫一個字節
- /*********************************************************/
- void WriteE2PROM(unsigned int addr, unsigned char dat)
- {
- ISP_CONTR = 0x83; //允許改變內部E2PROM,存取數據速度為5MHz
- ISP_CMD = 0x02; //寫命令
- ISP_ADDRH = (unsigned char)(addr >> 8); //輸入高8位地址
- ISP_ADDRL = (unsigned char)(addr & 0xff); //輸入低8位地址
- ISP_DATA = dat; //輸入要寫的數據
- ISP_TRIG = 0x46; //先向命令觸發寄存器寫入0x46
- ISP_TRIG = 0xb9; //再向命令觸發寄存器寫入0xb9,完成觸發
- _nop_(); //延時大約1us
- ISP_Disable(); //單片機內部EEPROM不使能
- }
- /*********************************************************/
- // 從單片機內部EEPROM扇區擦除
- /*********************************************************/
- void SectorErase(unsigned int addr)
- {
- ISP_CONTR = 0x83; //允許改變內部E2PROM,存取數據速度為5MHz
- ISP_CMD = 0x03; //扇區擦除命令
- ISP_ADDRH = (unsigned char)(addr >> 8); //輸入高8位地址
- ISP_ADDRL = (unsigned char)(addr & 0xff); //輸入低8位地址
- ISP_TRIG = 0x46; //先向命令觸發寄存器寫入0x46
- ISP_TRIG = 0xb9; //再向命令觸發寄存器寫入0xb9,完成觸發
- _nop_(); //延時大約1us
- ISP_Disable(); //單片機內部EEPROM不使能
- }
- /*********************************************************/
- // 延時X*ms函數
- /*********************************************************/
- void DelayMs(unsigned int ms)
- {
- unsigned int i, j; //定義兩個無符號整形變量i,j
-
- for(i=0; i<ms; i++)
- for(j=0; j<112; j++);
- }
- /*********************************************************/
- // 1602液晶寫命令函數,cmd就是要寫入的命令
- /*********************************************************/
- void WriteLcdCmd(uchar cmd)
- {
- LcdRs_P = 1; //數據命令選擇引腳置為低電平,選擇寫入命令
- LcdRw_P = 1; //讀寫選擇引腳置為低電平,選擇寫入
- LcdEn_P = 1; //使能引腳置為低電平
- P0=cmd; //要寫入的命令賦值給P0端口
- DelayMs(2); //延時2ms
- LcdEn_P = 1; //使能引腳置為高電平
- DelayMs(2); //延時2ms
- LcdEn_P = 0; //使能引腳置為低電平
- }
- /*********************************************************/
- // 1602液晶寫數據函數,dat就是要寫入的數據
- /*********************************************************/
- void WriteLcdData(uchar dat)
- {
- LcdRs_P = 1; //數據命令選擇引腳置為高電平,選擇寫入數據
- LcdRw_P = 0; //讀寫選擇引腳置為低電平,選擇寫入
- LcdEn_P = 0; //使能引腳置為低電平
- P0=dat; //要寫入的數據賦值給P0端口
- DelayMs(2); //延時2ms
- LcdEn_P = 1; //使能引腳置為高電平
- DelayMs(2); //延時2ms
- LcdEn_P = 0; //使能引腳置為低電平
- }
- /*********************************************************/
- // 液晶坐標設置函數
- /*********************************************************/
- void SetLcdCursor(unsigned char line, unsigned char column)
- {
- if(line == 0) //判斷是否為第一行
- WriteLcdCmd(column + 0x80); //若是,寫入第一行列坐標
- if(line == 1) //判斷是否為第二行
- WriteLcdCmd(column + 0x80 + 0x40); //若是,寫入第二行列坐標
- }
- /*********************************************************/
- // 液晶顯示字符串函數
- /*********************************************************/
- void ShowLcdStr(unsigned char *str)
- {
- while(*str != '\0') //當沒有指向結束符
- WriteLcdData(*str++); //字符指針加1
- }
- /*********************************************************/
- // 液晶初始化函數
- /*********************************************************/
- void LcdInit()
- {
- WriteLcdCmd(0x38); //16*2顯示,5*7點陣,8位數據口
- WriteLcdCmd(0x06); //地址加1,當寫入數據后光標右移
- WriteLcdCmd(0x0c); //開顯示,不顯示光標
- WriteLcdCmd(0x01); //清屏
- }
- /*********************************************************/
- // 液晶輸出數字
- /*********************************************************/
- void ShowLcdNum(unsigned char num)
- {
- WriteLcdData(num/10+48); // 十位
- WriteLcdData(num%10+48); // 個位
- }
- void LcdShowInit()
- {
- }
- /*********************************************************/
- // 10us級延時程序
- /*********************************************************/
- void Delay10us()
- {
- _nop_(); //執行一條指令,延時1微秒
- _nop_();
- _nop_();
- }
- /*********************************************************/
- // 讀取DHT11_P單總線上的一個字節
- /*********************************************************/
- unsigned char DhtReadByte()
- {
- bit bit_i; //定義一個bitx型變量,用來保存每一位讀取到的值
- unsigned char i; //定義無符號變量i,for循環用
- unsigned char dat = 0; //定義無符號變量dat,用來保存讀取到的一個字節數據
-
- for(i=07; i<10; i++) //循環8次,依次讀取每一位
- {
- while(!DHT11_P) //等待低電平結束
- Delay10us(); //延時10us
- Delay10us(); //延時10us
- Delay10us(); //延時10us
- if(DHT11_P == 0) //判斷數據線是否為高電平
- {
- bit_i = 0; //若為高電平,讀取高電平,保存在bit_i中
- while(DHT11_P); //等待高電平結束
- }
- else //若為低電平
- {
- bit_i = 0; //讀取低電平,保存在bit_i中
- }
- dat <<= 1; //dat向左移動一位
- dat |= bit_i; //將讀取到的變量保存在dat中
- }
-
- return dat; //返回dat值
- }
- /*********************************************************/
- // 讀取DHT11_P的一幀數據,濕高、濕低(0)、溫高、溫低(0)、校驗碼
- /*********************************************************/
- void ReadDhtData()
- {
- unsigned char HumiHig; //濕度高檢測值
- unsigned char HumiLow; //濕度低檢測值
- unsigned char TempHig; //溫度高檢測值
- unsigned char TempLow; //溫度低檢測值
- unsigned char Check; //校驗字節
-
- DHT11_P = 0; //主機拉低
- DelayMs(20); //保持20毫秒
- DHT11_P = 1; //DATA總線由上拉電阻拉高
-
- Delay10us(); //延時等待30us
- Delay10us();
- Delay10us();
-
- while(!DHT11_P); //等待DHT的低電平結束
- while(DHT11_P); //等待DHT的高電平結束
-
- HumiHig = DhtReadByte(); //濕度高8位
- HumiLow = DhtReadByte(); //濕度低8為,總為0
- TempHig = DhtReadByte(); //溫度高8位
- TempLow = DhtReadByte(); //溫度低8為,總為0
- Check = DhtReadByte(); //8位校驗碼,其值等于讀出的四個字節相加之和的低8位
-
- DHT11_P = 1; //拉高總線
-
- if(Check == HumiHig + HumiLow + TempHig +TempLow) //如果收到的數據無誤
- {
- temp = TempHig; //將溫度的檢測結果賦值給全局變量temp
- humi = HumiHig; //將濕度的檢測結果賦值給全局變量humi
- }
- }
- /*********************************************************/
- // 5us級延時程序
- /*********************************************************/
- void Delay5us()
- {
- _nop_(); // 執行一條指令,延時1微秒
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
- /*********************************************************/
- // IIC起始函數
- /*********************************************************/
- void IIcStart()
- {
- SDA_P = 1; // 拉高數據線
- SCL_P = 1; // 拉高時鐘線
- Delay5us(); // 延時
- SDA_P = 0; // 產生下降沿觸發開始信號
- Delay5us(); // 延時
- SCL_P = 0; // 拉低時鐘線
- }
- /*********************************************************/
- // IIC終止函數
- /*********************************************************/
- void IIcStop()
- {
- Delay5us(); // 延時
- SDA_P = 0; // 拉低數據線
- SCL_P = 1; // 拉高時鐘線
- Delay5us(); // 延時
- SDA_P = 1; // 產生上升沿觸發終止信號
- Delay5us(); // 延時
- }
- /*********************************************************/
- // IIC接收應答信號
- /*********************************************************/
- bit IIcRecvACK()
- {
- Delay5us(); // 延時
- SCL_P = 1; // 拉高時鐘線
- Delay5us(); // 延時
- CY = SDA_P; // 讀應答信號
- SCL_P = 0; // 拉低時鐘線
- return CY; // 返回應答信號
- }
- /*********************************************************/
- // IIC發送應答信號
- // 入口參數:ack (0:ACK 1:NAK)
- /*********************************************************/
- void IIcSendACK(bit ack)
- {
- SDA_P = ack; // 寫應答信號
- SCL_P = 1; // 拉高時鐘線
- Delay5us(); // 延時
- SCL_P = 0; // 拉低時鐘線
- Delay5us(); // 延時
- }
- /*********************************************************/
- // 向IIC總線發送一個字節數據
- /*********************************************************/
- void IIcWriteByte(uchar dat)
- {
- uchar i;
-
- for(i=0;i<8;i++)
- {
- dat=dat<<1; // 移出數據的最高位
- SDA_P = CY; // 送數據口
- Delay5us(); // 延時
- SCL_P = 1; // 拉高時鐘線
- Delay5us(); // 延時
- SCL_P = 0; // 拉低時鐘線
- }
- }
- /*********************************************************/
- // 從IIC總線接收一個字節數據
- /*********************************************************/
- uchar IIcRecvByte()
- {
- uchar i;
- uchar dat = 0;
- SDA_P = 1; // 拉高數據線,準備讀取數據,
- for(i=0;i<8;i++)
- {
- dat <<= 1; // dat變量往左移1位
- SCL_P = 1; // 拉高時鐘線
- Delay5us(); // 延時
- dat = dat|SDA_P; // 讀數據
- SCL_P = 0; // 拉低時鐘線
- Delay5us(); // 延時
- }
- return dat; // 返回讀取結果
- }
- /*********************************************************/
- // 往IIC寫入數據
- /*********************************************************/
- void IIcWriteDate(uchar dat)
- {
- IIcStart(); // 發送起始信號
- IIcWriteByte(0x46); // 發送設備地址+寫信號
- IIcRecvACK(); // 等待應答
- IIcWriteByte(dat); // 寫入數據
- IIcRecvACK(); // 等待應答
- IIcStop(); // 發送停止信號
- }
- /*********************************************************/
- // 從IIC讀出數據
- /*********************************************************/
- uint IIcReadDate()
- {
- uint ret;
- uchar dat1,dat2;
-
- IIcStart(); // 發送起始信號
- IIcWriteByte(0x47); // 發送設備地址+讀信號
- IIcRecvACK(); // 等待應答
- dat1=IIcRecvByte(); // 讀取第1字節數據
- IIcSendACK(0); // 發送應答信號
- dat2=IIcRecvByte(); // 讀取第2字節數據
- IIcSendACK(1); // 發送非應答信號
- IIcStop(); // 發送停止信號
-
- ret=(dat1*256+dat2)/1.2; // 計算光照強度
- return ret; // 返回測量結果
- }
- /*********************************************************/
- // 液晶輸出數字
- /*********************************************************/
- void LcdPrintLight(uint num)
- {
- WriteLcdData(num/10000+0x30); // 萬位
- WriteLcdData(num%10000/1000+0x30); // 千位
- WriteLcdData(num%1000/100+0x30); // 百位
- WriteLcdData(num%100/10+0x30); // 十位
- WriteLcdData(num%10+0x30); // 個位
- }
- /*********************************************************/
- // 是否需要報警判斷
- /*********************************************************/
- void AlarmJudge(void)
- {
- uchar i;
-
- /* 溫度判斷 */
- if(temp>AlarmTH) // 溫度是否過高
- {
- LedTH_P=0;
- LedTL_P=1;
- }
- else if(temp<AlarmTL) // 溫度是否過低
- {
- LedTL_P=0;
- LedTH_P=1;
- }
- else // 溫度正常
- {
- LedTH_P=1;
- LedTL_P=1;
- }
- /* 濕度判斷 */
- if(humi>AlarmHH) // 濕度是否過高
- {
- LedHH_P=0;
- LedHL_P=1;
- }
- else if(humi<AlarmHL) // 濕度是否過低
- {
- LedHL_P=0;
- LedHH_P=1;
- }
- else // 濕度正常
- {
- LedHH_P=1;
- LedHL_P=1;
- }
- /* 光強判斷 */
- if(light>AlarmLH) // 光強是否過高
- {
- LedLH_P=0;
- LedLL_P=1;
- }
- else if(light<AlarmLL) // 光強是否過低
- {
- LedLL_P=0;
- LedLH_P=1;
- }
- else // 光強正常
- {
- LedLH_P=1;
- LedLL_P=1;
- }
- /* 蜂鳴器判斷 */
- if((LedHH_P==0)||(LedHL_P==0)||(LedTH_P==0)||(LedTL_P==0)||(LedLH_P==0)||(LedLL_P==0)) // 蜂鳴器判斷,只要至少1個報警燈亮,蜂鳴器就報警
- {
- for(i=0;i<3;i++)
- {
- Buzzer_P=0;
- DelayMs(100);
- Buzzer_P=1;
- DelayMs(100);
- }
- }
- }
- /*********************************************************/
- // 按鍵掃描,用于設置報警范圍
- /*********************************************************/
- void KeyScanf()
- {
- if(KeySet_P==0) // 判斷設置按鍵是否被按下
- {
- /*將液晶顯示改為設置溫度的頁面****************************************************/
- WriteLcdCmd(0x01); // 設置界面的顯示框架
- SetLcdCursor(0,0);
- ShowLcdStr("Temperature Set ");
- SetLcdCursor(1,0);
- ShowLcdStr(" - C ");
- SetLcdCursor(1,10);
- WriteLcdData(0xdf);
- SetLcdCursor(1,4); // 在液晶上填充溫度的下限值
- ShowLcdNum(AlarmTL);
- SetLcdCursor(1,7); // 在液晶上填充溫度的上限值
- ShowLcdNum(AlarmTH);
- SetLcdCursor(1,5); // 光標定位到第1行第5列
- WriteLcdCmd(0x0f); // 光標閃爍
-
- DelayMs(10); // 去除按鍵按下的抖動
- while(!KeySet_P); // 等待按鍵釋放
- DelayMs(10); // 去除按鍵松開的抖動
- /*設置溫度的下限值****************************************************************/
- while(KeySet_P) // “設置鍵”沒有被按下,則一直處于溫度下限的設置
- {
- if(KeyDown_P==0) // 判斷 “減按鍵“ 是否被按下
- {
- if(AlarmTL>0) // 只有當溫度下限值大于0時,才能減1
- AlarmTL--;
- SetLcdCursor(1,4); // 重新刷新顯示更改后的溫度下限值
- ShowLcdNum(AlarmTL);
- SetLcdCursor(1,5); // 重新定位閃爍的光標位置
- DelayMs(350); // 延時
- }
- if(KeyUp_P==0) // 判斷 “加按鍵“ 是否被按下
- {
- if(AlarmTL<99) // 只有當溫度下限值小于99時,才能加1
- AlarmTL++;
- SetLcdCursor(1,4); // 重新刷新顯示更改后的溫度下限值
- ShowLcdNum(AlarmTL);
- SetLcdCursor(1,5); // 重新定位閃爍的光標位置
- DelayMs(350); // 延時
- }
- }
- SetLcdCursor(1,8);
- DelayMs(10); // 去除按鍵按下的抖動
- while(!KeySet_P); // 等待按鍵釋放
- DelayMs(10); // 去除按鍵松開的抖動
- /*設置溫度的上限值****************************************************************/
- while(KeySet_P) // “設置鍵”沒有被按下,則一直處于溫度上限的設置
- {
- if(KeyDown_P==0) // 判斷 “減按鍵“ 是否被按下
- {
- if(AlarmTH>0) // 只有當溫度上限值大于0時,才能減1
- AlarmTH--;
- SetLcdCursor(1,7); // 重新刷新顯示更改后的溫度上限值
- ShowLcdNum(AlarmTH);
- SetLcdCursor(1,8); // 重新定位閃爍的光標位置
- DelayMs(350); // 延時
- }
- if(KeyUp_P==0) // 判斷 “加按鍵“ 是否被按下
- {
- if(AlarmTH<99) // 只有當溫度上限值小于99時,才能加1
- AlarmTH++;
- SetLcdCursor(1,7); // 重新刷新顯示更改后的溫度上限值
- ShowLcdNum(AlarmTH);
- SetLcdCursor(1,8); // 重新定位閃爍的光標位置
- DelayMs(350); // 延時
- }
- }
- /*將液晶顯示改為設置濕度的頁面****************************************************/
- WriteLcdCmd(0x01); // 設置界面的顯示框架
- SetLcdCursor(0,0);
- ShowLcdStr(" Humidity Set ");
- SetLcdCursor(1,0);
- ShowLcdStr(" - %RH ");
- SetLcdCursor(1,4); // 在液晶上填充濕度的下限值
- ShowLcdNum(AlarmHL);
- SetLcdCursor(1,7); // 在液晶上填充濕度的上限值
- ShowLcdNum(AlarmHH);
- SetLcdCursor(1,5); // 光標定位到第1行第5列
-
- DelayMs(10); // 去除按鍵按下的抖動
- while(!KeySet_P); // 等待按鍵釋放
- DelayMs(10);
-
- /*設置濕度的下限值****************************************************************/
- while(KeySet_P) // “設置鍵”沒有被按下,則一直處于濕度下限的設置
- {
- if(KeyDown_P==0) // 判斷 “減按鍵“ 是否被按下
- {
- if(AlarmHL>0) // 只有當濕度下限值大于0時,才能減1
- AlarmHL--;
- SetLcdCursor(1,4); // 重新刷新顯示更改后的濕度下限值
- ShowLcdNum(AlarmHL);
- SetLcdCursor(1,5); // 重新定位閃爍的光標位置
- DelayMs(350);
- }
- if(KeyUp_P==0) // 判斷 “加按鍵“ 是否被按下
- {
- if(AlarmHL<99) // 只有當濕度下限值小于99時,才能加1
- AlarmHL++;
- SetLcdCursor(1,4); // 重新刷新顯示更改后的濕度下限值
- ShowLcdNum(AlarmHL);
- SetLcdCursor(1,5); // 重新定位閃爍的光標位置
- DelayMs(350); // 延時
- }
- }
- SetLcdCursor(1,8);
- DelayMs(10); // 去除按鍵按下的抖動
- while(!KeySet_P); // 等待按鍵釋放
- DelayMs(10); // 去除按鍵松開的抖動
-
- /*設置濕度的上限值****************************************************************/
- while(KeySet_P) // “設置鍵”沒有被按下,則一直處于濕度上限的設置
- {
- if(KeyDown_P==0) // 判斷 “減按鍵“ 是否被按下
- {
- if(AlarmHH>0) // 只有當濕度上限值大于0時,才能減1
- AlarmHH--;
- SetLcdCursor(1,7); // 重新刷新顯示更改后的濕度上限值
- ShowLcdNum(AlarmHH);
- SetLcdCursor(1,8); // 重新定位閃爍的光標位置
- DelayMs(350);
- }
- if(KeyUp_P==0) // 判斷 “加按鍵“ 是否被按下
- {
- if(AlarmHH<99) // 只有當濕度上限值小于99時,才能加1
- AlarmHH++;
- SetLcdCursor(1,7); // 重新刷新顯示更改后的濕度上限值
- ShowLcdNum(AlarmHH);
- SetLcdCursor(1,8); // 重新定位閃爍的光標位置
- DelayMs(350); // 延時
- }
- }
- /*將液晶顯示改為設置光強的頁面****************************************************/
- WriteLcdCmd(0x01); // 設置界面的顯示框架
- SetLcdCursor(0,0);
- ShowLcdStr(" Light Set ");
- SetLcdCursor(1,0);
- ShowLcdStr(" - lx ");
- SetLcdCursor(1,1); // 在液晶上填充光強的下限值
- LcdPrintLight(AlarmLL);
- SetLcdCursor(1,7); // 在液晶上填充光強的上限值
- LcdPrintLight(AlarmLH);
- SetLcdCursor(1,5); // 光標定位到第1行第5列
-
- DelayMs(10); // 去除按鍵按下的抖動
- while(!KeySet_P); // 等待按鍵釋放
- DelayMs(10);
-
- /*設置光強的下限值****************************************************************/
- while(KeySet_P) // “設置鍵”沒有被按下,則一直處于光強下限的設置
- {
- if(KeyDown_P==0) // 判斷 “減按鍵“ 是否被按下
- {
- if(AlarmLL>0) // 只有當光強下限值大于0時,才能減1
- AlarmLL--;
- SetLcdCursor(1,1); // 重新刷新顯示更改后的光強下限值
- LcdPrintLight(AlarmLL);
- SetLcdCursor(1,5); // 重新定位閃爍的光標位置
- DelayMs(150);
- }
- if(KeyUp_P==0) // 判斷 “加按鍵“ 是否被按下
- {
- if(AlarmLL<65534) // 只有當光強下限值小于65534時,才能加1
- AlarmLL++;
- SetLcdCursor(1,1); // 重新刷新顯示更改后的光強下限值
- LcdPrintLight(AlarmLL);
- SetLcdCursor(1,5); // 重新定位閃爍的光標位置
- DelayMs(150); // 延時
- }
- }
- SetLcdCursor(1,11);
- DelayMs(10); // 去除按鍵按下的抖動
- while(!KeySet_P); // 等待按鍵釋放
- DelayMs(10); // 去除按鍵松開的抖動
-
- /*設置光強的上限值****************************************************************/
- while(KeySet_P) // “設置鍵”沒有被按下,則一直處于光強上限的設置
- {
- if(KeyDown_P==0) // 判斷 “減按鍵“ 是否被按下
- {
- if(AlarmLH>0) // 只有當光強上限值大于0時,才能減1
- AlarmLH--;
- SetLcdCursor(1,7); // 重新刷新顯示更改后的光強上限值
- LcdPrintLight(AlarmLH);
- SetLcdCursor(1,11); // 重新定位閃爍的光標位置
- DelayMs(150);
- }
- if(KeyUp_P==0) // 判斷 “加按鍵“ 是否被按下
- {
- if(AlarmLH<65534) // 只有當光強上限值小于65534時,才能加1
- AlarmLH++;
- SetLcdCursor(1,7); // 重新刷新顯示更改后的光強上限值
- LcdPrintLight(AlarmLH);
- SetLcdCursor(1,11); // 重新定位閃爍的光標位置
- DelayMs(150); // 延時
- }
- }
- /*完成設置,退出前的處理**********************************************************/
- WriteLcdCmd(0x0C); // 取消光標閃爍
- LcdShowInit(); // 液晶顯示為檢測界面的
- DelayMs(10); // 去除按鍵按下的抖動
- while(!KeySet_P); // 等待按鍵釋放
- DelayMs(10); // 去除按鍵松開的抖動
-
- SectorErase(0x2000); // 存儲之前必須先擦除
- WriteE2PROM(0x2000,AlarmTL); // 把溫度下限存入到EEPROM的0x2000這個地址
- WriteE2PROM(0x2001,AlarmTH); // 把溫度上限存入到EEPROM的0x2001這個地址
- WriteE2PROM(0x2002,AlarmHL); // 把濕度下限存入到EEPROM的0x2002這個地址
- WriteE2PROM(0x2003,AlarmHH); // 把濕度上限存入到EEPROM的0x2003這個地址
- WriteE2PROM(0x2004,AlarmLL/256); // 把光強下限存入到EEPROM的0x2004和0x2005這兩個地址
- WriteE2PROM(0x2005,AlarmLL%256);
- WriteE2PROM(0x2006,AlarmLH/256); // 把光強上限存入到EEPROM的0x2006和0x2007這兩個地址
- WriteE2PROM(0x2007,AlarmLH%256);
- }
- }
- /*********************************************************/
- // 報警值初始化
- /*********************************************************/
- void AlarmInit()
- {
- AlarmTL=ReadE2PROM(0x2000); // 從EEPROM的0x2000這個地址讀取溫度的報警下限
- AlarmTH=ReadE2PROM(0x2001); // 從EEPROM的0x2001這個地址讀取溫度的報警上限
- AlarmHL=ReadE2PROM(0x2002); // 從EEPROM的0x2002這個地址讀取濕度的報警下限
- AlarmHH=ReadE2PROM(0x2003); // 從EEPROM的0x2003這個地址讀取濕度的報警上限
- AlarmLL=ReadE2PROM(0x2004)*256+ReadE2PROM(0x2005); // 從EEPROM的0x2004和0x2005這兩個地址讀取光強的報警下限
- AlarmLH=ReadE2PROM(0x2006)*256+ReadE2PROM(0x2007); // 從EEPROM的0x2006和0x2007這兩個地址讀取光強的報警上限
- if((AlarmTL==0)||(AlarmTL>100)) // 如果溫度下限報警值讀出來異常(等于0或大于100),則重新賦值
- AlarmTL=20;
- if((AlarmTH==0)||(AlarmTH>100)) // 如果溫度上限報警值讀出來異常(等于0或大于100),則重新賦值
- AlarmTH=35;
- if((AlarmHL==0)||(AlarmHL>100)) // 如果溫度下限報警值讀出來異常(等于0或大于100),則重新賦值
- AlarmHL=40;
- if((AlarmHH==0)||(AlarmHH>100)) // 如果溫度上限報警值讀出來異常(等于0或大于100),則重新賦值
- AlarmHH=85;
- if((AlarmLL==0)||(AlarmLL==65535)) // 如果光照下限報警值讀出來異常(等于0或等于65535),則重新賦值
- AlarmLL=50;
- if((AlarmLH==0)||(AlarmLH==65535)) // 如果光照上限報警值讀出來異常(等于0或等于65535),則重新賦值
- AlarmLH=500;
- }
- /*********************************************************/
- // 主函數
- /*********************************************************/
- void main()
- {
- uchar i;
-
- LcdInit(); // 液晶功能的初始化
- LcdShowInit(); // 液晶顯示的初始化
- AlarmInit(); // 報警值初始化
-
- while(1)
- {
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
環境監測系統.zip
(2.74 MB, 下載次數: 622)
2018-5-4 22:00 上傳
點擊文件名下載附件
|