89c52rc单片机控制超声波测距和读取实时的温湿度情况,按键控制切换注释准确。
详情见文件
单片机源程序如下:
- #include <reg52.h> //51 的头文件
- #include <intrins.h> //超声波的固有函数头文件
- #define uchar unsigned char //表示之后代码中的“uchar”全部代表“unsigned char”
- #define uint unsigned int //定义uint为无符号整型。
- #define LCD_databus P2 //定义LCD的数据口为P2
- //全局变量定义
- unsigned int time; //声明无符号类型 time
- unsigned int S,s_false; //声明无符号类型
- unsigned long num1; //声明无符号长整数
- bit flag;
- //12864液晶显示定义
- uchar code sj1[]={"<<超声波测距仪>>"};
- uchar code sj4[]={"当前距离:"};
- uchar code sj5[]={"错误 "};
- uchar dht_num=0; //用于while循环中计数,超时则跳出循环
- uchar code table[]={"温度:"};
- uchar code table1[]={"湿度:"};
- uchar code table2[]={"℃"};
- uchar dht_d1=0,dht_d2=0 ; //依次为湿度整数部分和湿度小数部
- uchar dht_t1=0,dht_t2=0 ; //依次为温度整数部分和温度小数部分
- uchar dht_j=0; //和校验,可选择是否使用,具体参照数据手
- uchar i,t11,t12,d11,d12;
- uchar t21,t22,d21,d22;
- //超声波引脚定义
- sbit Trig =P1^0; //定义引脚
- sbit Echo =P1^1;
- //12864液晶引脚定义
- sbit RS=P0^7; //命令数据
- sbit RW=P0^6; //读写
- sbit EN =P0^5;
- sbit dht_dat=P1^2; //用哪个I/O口自选,注意不要用P2口
- //定义按键
- sbit key1 = P3^5;
- sbit key2 = P3^4;
- /*****************ms延时函数*********************************/
- void delay(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- /*****************20us延时函数*********************************/
- void delay_20us()
- {
- uchar a;
- for(a=0;a<100;a++);
- }
- /*****************ms延时函数*********************************/
- void dh11delayms(uint xms)
- {
- uint i,j;
- for(i=xms;i>0;i--)
- for(j=110;j>0;j--);
- }
- /*****************us延时函数*****************************/
- void delay_10us()
- {
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
- /*写指令函数*/
- /*rs=l,rw=l,en=高脉冲,D0-D7=指令码。*/
- void write_cmd(uchar cmd)
- {
- RS=0;
- RW=0;
- EN=0;
- LCD_databus=cmd;
- dh11delayms(5);
- EN=1;
- dh11delayms(5);
- EN=0;
- }
- /***************************写显示数据************************/
- /*rs=h,rw=l,*/
- void write_dat(uchar date)
- {
- RS=1;
- RW=0;
- EN=0;
- LCD_databus=date;
- dh11delayms(5);
- EN=1;
- dh11delayms(5);
- EN=0;
- }
- /*****************初始化************************/
- void DH11init()
- {
- EN=0;
- RW=0;
-
- write_cmd(0x30); //基本指令操作
- dh11delayms(5);
- write_cmd(0x0c); //显示开,关光标
- dh11delayms(5);
- write_cmd(0x06);
- dh11delayms(2);
- write_cmd(0x01); //清除显示内容
- dh11delayms(5);
-
-
- }
- void dht_init()
- {
- dh11delayms(1000); //DHT11上电前准备时间,大概1s
- dht_dat=1; // //总线准备
- }
- uchar read_date() //接收一个8位数据,先高位后低位
- {
- uchar i,dat;
- for(i=0;i<8;i++) //也就是说程序是循环八次,把判断有“1”输出到dat中,然后输出一个八位的数据。
- {
- dht_num=2;
- while((dht_dat==0)&&(dht_num++)); //dht_dat 数据线由DH11拉低准备发送数据
- delay_10us();
- delay_10us();
- delay_10us();
- delay_10us();
- dat=dat<<1;
- if(dht_dat==1)
- {
- dht_num=2;
- dat=dat|0x01; //如果来自DQ的数据是高电平1,则把1放到dat的最低位
- while((dht_dat==1)&&(dht_num++));
- }
- }
- return dat;
- }
- void get_temp() //给DHT11一个开始信号,然后读取一次数据,共五个8位字节
- {
- dht_dat=0;
- dh11delayms(25);
- dht_dat=1; //单片机给起始脉冲信号
- delay_10us();
- delay_10us();
- delay_10us();
- delay_10us();
- dht_dat=1; //稍作延时,等待DHT11返回响应(响应为低电 平)
- if(dht_dat==0) //有响应才接收数据,否则不作处理
- {
- dht_num=2;
- while((dht_dat==0)&&(dht_num++));
- dht_num=2;
- while((dht_dat==1)&&(dht_num++));
- dht_d1=read_date();
- dht_d2=read_date();
- dht_t1=read_date();
- dht_t2=read_date();
- dht_j=read_date(); //一次读出五个数据
- }
- dht_dat=1; //释放总线
- dh11delayms(10);
- d11=dht_d1/10;
- d12=dht_d1%10;
- t11=dht_t1/10;
- t12=dht_t1%10;
-
- d21=dht_d2/10;
- d22=dht_d2%10;
- t21=dht_t2/10;
- t22=dht_t2%10;
-
- }
- //2864液晶写命令函数
- void xmn(unsigned char com)
- {
- RS=0;
- LCD_databus=com;
- delay(5);
- EN=1;
- delay(5);
- EN=0;
- }
- //2864液晶写数据函数
- void xsj(unsigned char zifu)
- {
- RS=1;
- LCD_databus=zifu;
- delay(5);
- EN=1;
- delay(5);
- EN=0;
- }
- //2864液晶显示函数1
- void xs1()
- {
- uchar i;
- xmn(0x80);
- for(i=0;i<16;i++)
- {
- xsj(sj1[i]);
- }
-
-
- xmn(0x88);
- for(i=0;i<16;i++)
- {
- xsj(sj4[i]);
- }
- }
- //2864液晶显示函数2
- void xs2(uint t_emp)
- {
- uchar qian,bai,shi,ge;
- qian=t_emp/1000;
- bai=(t_emp%1000)/100;
- shi=(t_emp%100)/10;
- ge=t_emp%10;
- xmn(0x8d);
- xsj(0x30+qian);
- delay(1);
- xsj(0x30+bai);
- delay(1);
- xsj(0x30+shi);
- delay(1);
- xsj(0x30+ge);
- delay(1);
- xsj('c');
- delay(1);
- xsj('m');
- delay(100);
- }
- //超声波计数函数
- void T0_time() interrupt 1 //T0中断用来计数器溢出,超过测距范围
- {
- flag=0; //中断溢出标志,失败
- TH0=0;
- TL0=0;
- TR0=0; //关闭计数
- }
- //中断定时函数
- void T1_timer() interrupt 3 //中断
- {
- TH1=(65536-50000)/256;
- TL1=(65536-50000)%256;
- num1++;
- }
- //超声波模块启动函数
- void StartModule() //启动模块
- {
- Trig=1; //启动一次模块
- _nop_();_nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();_nop_();
- _nop_();
- Trig=0;
- }
- //超声波测试距离计算函数
- void Count(void)
- {
- uchar i;
- time=TH0*256+TL0;
- TH0=0;
- TL0=0;
- S=(time*1.7)/100; //算出来是CM
- if(((S<1)||(S>=600))||flag==0) //超出测量范围显示“-”失败
- {
-
- s_false=1000;
- xmn(0x8d);
- for(i=0;i<6;i++)
- {
- xsj(sj5[i]);
- }
-
- }
- else
- {
- xs2(S);
- }
- }
- //12864液晶初始化函数
- void init()
- {
- delay(100);
- xmn(0x30);
- delay_20us();
- xmn(0x30);
- delay_20us();
- xmn(0x0c);
- delay_20us();
- xmn(0x01);
- delay_20us();
- xmn(0x06);
- delay_20us();
- }
- void WSD()
- {
- dht_init();
- DH11init();
- while(1)
- {
- get_temp();
-
-
-
-
- write_cmd(0x80);
- for(i=0;i<6;i++)
- {
- write_dat(table[i]);
- }
- write_cmd(0x83);
- write_dat(0x30+t11);
- write_dat(0x30+t12);
- write_cmd(0x80+4);
- write_dat('.');
- write_dat(0x30+t21);
- write_cmd(0x85);
- write_dat(0x30+t22);
- write_cmd(0x86);
- for(i=0;i<4;i++)
- {
- write_dat(table2[i]);
- }
- write_cmd(0x90);
- for(i=0;i<6;i++)
- {
- write_dat(table1[i]);
- }
- write_cmd(0x93);
- write_dat(0x30+d11);
- write_dat(0x30+d12);
- write_cmd(0x94);
- write_dat('.');
- write_dat(0x30+d21);
- write_cmd(0x95);
- write_dat(0x30+d22);
- write_cmd(0x96);
- write_dat('%');
- }
- }
- void CSB()
- {
- delay(500); //启动等待,等LCM讲入工作状态
- RW=0;
- init(); //LCM初始化
- delay(500); //延时片刻(可不要)
- while(1)
- {
- TMOD=0x11; //设T0为方式1,GATE=1;
- TH0=0;
- TL0=0;
- ET0=1; //允许T0中断
- ET1=1;
- TR1=1;
- EA=1; //开启总中断
- xs1();
- Trig=0;
- Echo=0;
- while(1)
- {
- StartModule();
- flag=1;
- //while(!Echo); //当echo为零时等待
- while((!Echo)&&flag);//当echo为零时等待,中断flag跳出等待
- TR0=1; //开启计数
- while(Echo&&flag); //当echo为1计数并等待
- TR0=0; //关闭计数
- Count(); //计算
- delay(120); //80MS
- }
- }
- }
- void keyscan()
- {
-
- if(key1 == 0)
- {
-
- if(key1 == 0)
- {
- CSB();
- }
- }
-
- if(key2 == 0)
- {
-
- if(key2 == 0)
- WSD();
- }
- }
-
- void main(void)
-
- {
- while(1)
-
- {
-
- keyscan();}
- }
复制代码
以上的代码51hei提供下载:
整合版本加按键.zip
(61.35 KB, 下载次数: 129)
|