原來的濕度換算程序和蜂鳴器程序確實有錯誤,已經調試好了,這個蜂鳴器在仿真中不會響,實物中會響的。
無標題.jpg (243.13 KB, 下載次數: 71)
下載附件
2019-5-2 13:37 上傳
- #include <AT89X52.H>
- #include<intrins.h>
- #include<stdio.h>
- #define uint unsigned int
- #define uchar unsigned char
- #define RS_CLR RS=0
- #define RS_SET RS=1
- #define RW_CLR RW=0
- #define RW_SET RW=1
- #define EN_CLR EN=0
- #define EN_SET EN=1
- #define ZERO 4.5 //濕度傳感器放空氣中的電壓值 對應濕度0%
- #define FULL 0.45 //濕度傳感器放水中的電壓值 對應濕度100%
- #define DataPort P0
- float k,b;//計算濕度用斜率
- sbit RS = P2^5; //定義LCD1602端口
- sbit RW = P2^6;
- sbit EN = P2^7;
- sbit KEY1=P1^0; //取消
- sbit KEY2=P1^1; //增加
- sbit KEY3=P1^2; //減少
- sbit KEY4=P1^3; //確認
- sbit CS = P2^0; //定義ADC0832端口
- sbit CLK = P2^1;
- sbit DIO = P2^2;
- sbit MOETOR = P3^6;//水泵控制端口
- sbit DQ = P3^5;
- sbit beep = P3^3; //蜂鳴器IO口定義
- uchar shidu; //濕度等級
- uchar s_high = 70,s_low = 25; //濕度報警參數
- uint temp;
- uchar dm;
- float d; //實時濕度值
- int RH=50; //濕度上限
- int RL=20; //濕度下限
- char KeyValue; //返回按鍵值
- float temperature; //溫度值
- unsigned char displaytemp[16];//定義顯示區域臨時存儲數組
- /*------------------------------------------------
- 18b20初始化
- ------------------------------------------------*/
- /*------------------------------------------------
- uS延時函數,含有輸入參數 unsigned char t,無返回值
- unsigned char 是定義無符號字符變量,其值的范圍是
- 0~255 這里使用晶振12M,精確延時請使用匯編,大致延時
- 長度如下 T=tx2+5 uS
- ------------------------------------------------*/
- void DelayUs2x(unsigned char t)
- {
- while(--t);
- }
- /*------------------------------------------------
- mS延時函數,含有輸入參數 unsigned char t,無返回值
- unsigned char 是定義無符號字符變量,其值的范圍是
- 0~255 這里使用晶振12M,精確延時請使用匯編
- ------------------------------------------------*/
- void DelayMs(unsigned char t)
- {
- while(t--)
- {
- //大致延時1mS
- DelayUs2x(245);
- DelayUs2x(245);
- }
- }
- /*------------------------------------------------
- 18b20初始化
- -----------------------------------------*/
- bit Init_DS18B20(void)
- {
- bit dat=0;
- DQ = 1; //DQ復位
- DelayUs2x(5); //稍做延時
- DQ = 0; //單片機將DQ拉低
- DelayUs2x(200); //精確延時 大于 480us 小于960us
- DelayUs2x(200);
- DQ = 1; //拉高總線
- DelayUs2x(50); //15~60us 后 接收60-240us的存在脈沖
- dat=DQ; //如果x=0則初始化成功, x=1則初始化失敗
- DelayUs2x(25); //稍作延時返回
- return dat;
- }
- /*------------------------------------------------
- 讀取一個字節
- ------------------------------------------------*/
- unsigned char ReadOneChar(void)
- {
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;i--)
- {
- DQ = 0; // 給脈沖信號
- dat>>=1;
- DQ = 1; // 給脈沖信號
- if(DQ)
- dat|=0x80;
- DelayUs2x(25);
- }
- return(dat);
- }
- /*------------------------------------------------
- 寫入一個字節
- ------------------------------------------------*/
- void WriteOneChar(unsigned char dat)
- {
- unsigned char i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = dat&0x01;
- DelayUs2x(25);
- DQ = 1;
- dat>>=1;
- }
- DelayUs2x(25);
- }
- /*------------------------------------------------
- 讀取溫度
- ------------------------------------------------*/
- unsigned int ReadTemperature(void)
- {
- unsigned char a=0;
- unsigned int b=0;
- unsigned int t=0;
- Init_DS18B20();
- WriteOneChar(0xCC); // 跳過讀序號列號的操作
- WriteOneChar(0x44); // 啟動溫度轉換
- DelayMs(10);
- Init_DS18B20();
- WriteOneChar(0xCC); //跳過讀序號列號的操作
- WriteOneChar(0xBE); //讀取溫度寄存器等(共可讀9個寄存器) 前兩個就是溫度
- a=ReadOneChar(); //低位
- b=ReadOneChar(); //高位
- b<<=8;
- t=a+b;
- return(t);
- }
- /*------------------------------------------------
- 判忙函數
- ------------------------------------------------*/
- bit LCD_Check_Busy(void)
- {
- unsigned char LCD_Status;
- RS = 0;
- RW = 1;
- EN = 1;
- DelayMs(1);
- LCD_Status = DataPort;
- EN = 0;
- return LCD_Status;
- }
- /*------------------------------------------------
- 寫入命令函數
- ------------------------------------------------*/
- void LCD_Write_Com(unsigned char com)
- {
- while((LCD_Check_Busy()&0x80)==0x80);
- RS = 0;
- RW = 0;
- EN = 0;
- DataPort = com;
- EN = 1;
- DelayMs(1);
- EN = 0;
- }
- /*------------------------------------------------
- 寫入數據函數
- ------------------------------------------------*/
- void LCD_Write_Data(unsigned char Data)
- {
- while((LCD_Check_Busy()&0x80)==0x80);
- RS = 1;
- RW = 0;
- EN = 0;
- DataPort = Data;
- EN = 1;
- DelayMs(1);
- EN = 0;
- }
- /*------------------------------------------------
- 清屏函數
- ------------------------------------------------*/
- /*
- void LCD_Clear(void)
- {
- LCD_Write_Com(0x01);
- DelayMs(5);
- }*/
- /*------------------------------------------------
- 寫入字符串函數
- ------------------------------------------------*/
- void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
- {
- if (y == 0)
- {
- LCD_Write_Com(0x80 + x); //表示第一行
- }
- else
- {
- LCD_Write_Com(0xC0 + x); //表示第二行
- }
- while (*s)
- {
- LCD_Write_Data( *s);
- s ++;
- }
- }
- /*------------------------------------------------
- 寫入字符函數
- ------------------------------------------------*/
- /*
- void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
- {
- if (y == 0)
- {
- LCD_Write_Com(0x80 + x);
- }
- else
- {
- LCD_Write_Com(0xC0 + x);
- }
- LCD_Write_Data( Data);
- }*/
- /*------------------------------------------------
- 初始化函數
- ------------------------------------------------*/
- void LCD_Init(void)
- {
- LCD_Write_Com(0x38); /*顯示模式設置*/
- LCD_Write_Com(0x01); /*顯示清屏*/
- LCD_Write_Com(0x06); /*顯示光標移動設置*/
- LCD_Write_Com(0x0C); /*顯示開及光標設置*/
- }
- unsigned char Get_AD_Result(unsigned char ch) //讀取AD值
- {
- uchar i=0,j,ndat=0,Vot=0;
- uint dat=0;
- if(ch==0)ch=2;
- if(ch==1)ch=3;
- DIO=1;_nop_();_nop_();
- CS=0;_nop_();_nop_(); //拉低CS端
- CLK=1;_nop_();_nop_(); //拉高CLK端
- CLK=0;_nop_();_nop_(); //拉低CLK端,形成下降沿1
- CLK=1; //拉高CLK端
- DIO=ch&0x1;_nop_();_nop_();
- CLK=0;_nop_();_nop_(); //拉低CLK端,形成下降沿2
- CLK=1; //拉高CLK端
- DIO=(ch>>1)&0x1;_nop_();_nop_();
- CLK=0; //拉低CLK端,形成下降沿3
- DIO=1;_nop_();_nop_(); //控制命令結束
- dat=0;
- for(i=0;i<8;i++)
- {
- dat|=DIO; //收數據
- CLK=1;_nop_();_nop_();
- CLK=0;_nop_();_nop_(); //形成一次時鐘脈沖
- dat<<=1;
- if(i==7)
- dat|=DIO;
- }
- for(i=0;i<8;i++)
- {
- j=0;
- j=j|DIO; //收數據
- CLK=1;_nop_();_nop_();
- CLK=0;_nop_();_nop_(); //形成一次時鐘脈沖
- j=j<<7;
- ndat=ndat|j;
- if(i<7)
- ndat>>=1;
- }
- CS=1; //拉低CS端
- CLK=0; //拉低CLK端
- DIO=1; //拉高數據端,回到初始狀態
- dat<<=8;
- dat|=ndat;
- return(dat);
- }
- void clock_h_l()
- {
- shidu=dm;
- if((shidu <= s_low)||(shidu >= s_high))
- beep = ~beep; //蜂鳴器報警
- else beep = 1; //關閉蜂鳴器
- }
- /*------------------------------------------------
- 按鍵掃描函數,返回掃描鍵值
- ------------------------------------------------*/
- unsigned char KeyScan(void)
- {
- /********************************************************/
- if(!KEY1) //如果檢測到低電平,說明按鍵按下
- {
- DelayMs(10); //延時去抖,一般10-20ms
- if(!KEY1) //再次確認按鍵是否按下,沒有按下則退出
- {
- while(!KEY1);//如果確認按下按鍵等待按鍵釋放,沒有則退出
- {
- return 1;
- }
- }
- }
- /********************************************************/
- else if(!KEY2) //如果檢測到低電平,說明按鍵按下
- {
- DelayMs(10); //延時去抖,一般10-20ms
- if(!KEY2) //再次確認按鍵是否按下,沒有按下則退出
- {
- while(!KEY2);//如果確認按下按鍵等待按鍵釋放,沒有則退出
- {
- return 2;
- }
- }
- }
- /********************************************************/
- else if(!KEY3) //如果檢測到低電平,說明按鍵按下
- {
- DelayMs(10); //延時去抖,一般10-20ms
- if(!KEY3) //再次確認按鍵是否按下,沒有按下則退出
- {
- while(!KEY3);//如果確認按下按鍵等待按鍵釋放,沒有則退出
- {
- return 3;
- }
- }
- }
- /********************************************************/
- else if(!KEY4) //如果檢測到低電平,說明按鍵按下
- {
- DelayMs(10); //延時去抖,一般10-20ms
- if(!KEY4) //再次確認按鍵是否按下,沒有按下則退出
- {
- while(!KEY4);//如果確認按下按鍵等待按鍵釋放,沒有則退出
- {
- return 4;
- }
- }
- }
- else
- return 0;
- }
- void Keyprocessing(int x) //按鍵值處理函數
- {
- switch(x)
- {
- case 1: RH++; break; //上限加
- case 2: RH--; break; //上限減
- case 3: RL++; break; //下限加
- case 4: RL--; break; //下限減
- }
- }
- /*------------------------------------------------
- 主函數
- ------------------------------------------------*/
- void main(void)
- {
- LCD_Init();
- DelayMs(10);
- // Init_Timer0();
- MOETOR = 0; //默認水泵關閉
- while (1)
- {
- KeyValue=KeyScan();
- if(KeyValue!=0)//如果有鍵按下
- {
- Keyprocessing(KeyValue); //鍵值處理
- }
- temp=ReadTemperature(); //讀取溫度值
- temperature=(float)temp*0.0625;
- sprintf(displaytemp,"T =%3.1f",temperature);//
- LCD_Write_String(0,0,displaytemp);// 顯示溫度值
- d = (float)Get_AD_Result(0)*5/255; //計算電壓值
- k = 100/(FULL-ZERO); //根據空氣中和水中的電壓值列函數y=kx+b 計算 k b
- b = 0-ZERO*k;
- d = k*d+b; //計算實際的濕度值
- if(d<0) d=0;
- if(d>100) d=100;
- sprintf(displaytemp,"R =%3.1f",d);//
- LCD_Write_String(8,0,displaytemp);// 顯示濕度
- sprintf(displaytemp,"RH=%2d",RH);//
- LCD_Write_String(0,1,displaytemp);// 顯示濕度上限
- sprintf(displaytemp,"RL=%2d",RL);//
- LCD_Write_String(10,1,displaytemp);// 顯示濕度下限
- dm=d;
- if(dm<RL) MOETOR =1; //低于下限 開水泵
- if(dm>RH) MOETOR =0; //高于上限 關水泵
- DelayMs(300);
- clock_h_l();//蜂鳴器程序
- }
- }
復制代碼
|