原来的湿度换算程序和蜂鸣器程序确实有错误,已经调试好了,这个蜂鸣器在仿真中不会响,实物中会响的。
- #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();//蜂鸣器程序
- }
- }
复制代码
|