好了吗,请求楼主分享经验 |
修改一下延时时间 |
字符之间不要有空格,英文状态输入 |
既然仿真没有问题,那说明这个程序应该是没什么大问题的,建议楼主修改一下延时时间或者换一个晶体振荡器一下 |
黑块是一闪一闪的,下面是我的程序 #include<intrins.h> #include<AT89X52.H> #define uchar unsigned char #define uint unsigned int uchar code digit[]={"0123456789"}; //定义字符数组显示数字 uchar code Error[]="Error!Check!"; //说明没有检测到DS18B20 uchar code table[]="Alarm Clock"; uchar code table1[]="0123456789"; uchar code table2[]="WEEK"; uchar code table3[]="Today is fine!"; uchar code table4[]="HELLO!"; uchar code table5[]="Made by Kaili"; uchar code table6[]="Happy new year!!";//1.1 //uchar code table7[]="Valentine's Day"; //2.14 /******************************************************************************* 以下是对液晶模块的操作程序 *******************************************************************************/ sbit RS=P2^5; //寄存器选择位,将RS位定义为P2.0引脚 sbit RW=P2^6; //读写选择位,将RW位定义为P2.1引脚 sbit E=P2^7; //使能信号位,将E位定义为P2.2引脚 sbit BF=P0^7; //忙碌标志位,,将BF位定义为P0.7引脚 sbit ceshi=P1^0; sbit T_RST=P1^6; sbit T_CLK=P1^4; sbit T_IO=P1^5; sbit beep=P1^7; sbit key1=P3^0; //调闹钟的小时即x sbit key2=P3^1; //调闹钟的分钟即y sbit key4=P3^5; //显示切换 sbit key3=P3^2; sbit ACC0=ACC^0; sbit ACC7=ACC^7; sbit io=P1^1; uchar time; //设置全局变量,专门用于严格延时 static uchar x=0x08,y=30; uchar t_sec,sec1,sec2; uchar t_min,min1,min2; uchar t_hour,hour1,hour2; uchar t_mon,mon1,mon2; uchar t_day,day1,day2; uchar t_year,year1,year2; uchar week,week1; uchar com,inf; /*定义变量*/ uchar data_byte=0,count,SHISHI,SHIGE,WENSHI,WENGE; uint TH_data,TL_data,RH_data,RL_data,CK_data; uint TH_temp,TL_temp,RH_temp,RL_temp,CK_temp; uchar num; /*10微妙延时程序*/ void delay1() { unsigned char i; for(i=0; i<3; i++); } /***************************************************** 函数功能:延时若干微秒 入口参数:n *************************************************** void delaynus(unsigned char n) { unsigned char i; for(i=0;i<n;i++) ; } /***************************************************** 函数功能:延时1ms (3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒 ***************************************************/ void delay1ms() { uchar i,j; for(i=0;i<10;i++) for(j=0;j<33;j++) ; } /***************************************************** 函数功能:延时若干毫秒 入口参数:n ***************************************************/ void delaynms(uchar n) { uchar i; for(i=0;i<n;i++) delay1ms(); } /**********************DHT11模块**********************/ uchar receive_byte()//接收一个字节 { uchar i,temp; for(i=0;i<8; i++) { count = 2; while((!io)&&count++)//等待50us低电平结束并防止死循环 temp = 0; delay1(); delay1(); delay1(); if (io==1) { temp = 1; count = 2; while(io && count++); } else temp = 0; data_byte<<=1; data_byte|=temp; } return (data_byte); } /*DHT11开始函数*/ void read_io()//开始信号读数据并校验 { io = 0; delaynms(18);//主机拉低18ms io=1;//DATA总线由上拉电阻拉高 主机延时20us delay1(); delay1(); delay1(); delay1(); io = 1;//主机设置为输入高电平判断从机响应信号 if(!io) { count = 2; while((!io)&&count++);//判断DHT11发出80us低电平响应信号是否结束 count = 2; while(io && count++);//判断DHT11拉高总线80us高电平是否结束 RH_temp = receive_byte(); RL_temp = receive_byte(); TH_temp = receive_byte(); TL_temp = receive_byte(); CK_temp = receive_byte(); io = 1; num = (RH_temp+RL_temp+TH_temp+TL_temp);//数据校验 if(num==CK_temp) { RH_data=RH_temp; RL_data=RL_temp; TH_data=TH_temp; TL_data=TL_temp; CK_data=CK_temp; } } //湿度整数部分 SHISHI = RH_data/10; SHIGE = RH_data%10; //温度整数部分 WENSHI =(char) TH_data/10; WENGE = (char) TH_data%10; } /***************************************************** 函数功能:判断液晶模块的忙碌状态 返回值:result。result=1,忙碌;result=0,不忙 ***************************************************/ bit BusyTest(void) { bit result; RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态 RW=1; E=1; //E=1,才允许读写 _nop_(); //空操作 _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 delaynms(5); result=BF; //将忙碌标志电平赋给result E=0; //将E恢复低电平 return result; } /***************************************************** 函数功能:将模式设置指令或显示地址写入液晶模块 入口参数:dictate ***************************************************/ void WriteInstruction (uchar dictate) { while(BusyTest()==1); //如果忙就等待 P0=dictate; //将数据送入P0口,即写入指令或地址 RS=0; //根据规定,RS和R/W同时为低电平时,可以写入指令 RW=0; E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲, // 就是让E从0到1发生正跳变,所以应先置"0" delaynms(5); _nop_(); _nop_(); //空操作两个机器周期,给硬件反应时间 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 delaynms(5); E=1; //E置高电平 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 delaynms(5); E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令 delay1ms(); } /***************************************************** 函数功能:指定字符显示的实际地址 入口参数:x ***************************************************/ void WriteAddress(unsigned char x) { WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x" } /***************************************************** 函数功能:将数据(字符的标准ASCII码)写入液晶模块 入口参数:y(为字符常量) ***************************************************/ void WriteData(uchar y) { while(BusyTest()==1); P0=y; //将数据送入P0口,即将数据写入液晶模块 RS=1; //RS为高电平,RW为低电平时,可以写入数据 RW=0; E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲, // 就是让E从0到1发生正跳变,所以应先置"0" delaynms(5); delaynms(5); _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 delaynms(5); E=1; //E置高电平 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令 } /***************************************************** 函数功能:对LCD的显示模式进行初始化设置 ***************************************************/ void LcdInitiate(void) { delaynms(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间 WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口 delaynms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x38); delaynms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x38); //连续三次,确保初始化成功 delaynms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x0c); //显示模式设置:显示开,无光标,光标不闪烁 delaynms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x06); //显示模式设置:光标右移,字符不移 delaynms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x01); //清屏幕指令,将以前的显示内容清除 delaynms(5); //延时5ms ,给硬件一点反应时间 } void write_com(uchar com)//向1602写指令 { while(BusyTest()==1); P0=com; delaynms(5); RS=0; RW=0; delaynms(5); delaynms(10); E=1; delaynms(10); E=0; } /***************************************************** 函数功能:显示温度的小数点 *************************************************** void display_dot(void) { WriteAddress(0x80+0x40+0x03); //写显示地址,将在第2行第10列开始显示 WriteData('.'); //将小数点的字符常量写入LCD delaynms(50); //延时1ms给硬件一点反应时间 } /***************************************************** 函数功能:显示温度的单位(Cent) ***************************************************/ void display_cent(void) { WriteAddress(0x80+0x40+0x02); //写显示地址,将在第2行第13列开始显示 WriteData(0xdf); WriteAddress(0x80+0x40+0x03); WriteData('C'); } /******************************************* 向1302写一个字节 *******************************************/ void input_BYTE(uchar dat) { uchar i; ACC=dat; for(i=8;i>0;i--) { T_IO=ACC0; T_CLK=1; delaynms(5); T_CLK=0; ACC=(ACC>>1); } } /******************************************* 1302读出一个字节 *******************************************/ uchar output_BYTE() { uchar i; for(i=8;i>0;i--) { ACC=(ACC>>1); ACC7=T_IO; T_CLK=1; T_CLK=0; } return (ACC); } /******************************************* 写数据 *******************************************/ void write_1302(uchar add,uchar dat) { T_RST=0; //禁止数据传输 T_CLK=0; //确保写数据之前SCLK被拉低 T_RST=1; //启动数据传输 delaynms(5); input_BYTE(add); //写入命令字 input_BYTE(dat); //写数据 delaynms(5); T_CLK=1; //将时钟电平至于已知状态 T_RST=0; } /******************************************* 读数据 *******************************************/ uchar read_1302(uchar add) { uchar inf; T_RST=0; T_CLK=0; T_RST=1; delaynms(5); input_BYTE(add); inf=output_BYTE(); delaynms(5); T_CLK=1; T_RST=0; return (inf); } void init_1302() { write_1302(0x8e,0x00);//关闭写保护; // write_1302(0x90,0xaa);//设置充电方式; write_1302(0x80,0x00);//秒寄存器初始化; write_1302(0x82,0x29);//分....... write_1302(0x84,0x08);//时....... write_1302(0x86,0x10);//日........ write_1302(0x88,0x11);//月....... write_1302(0x8a,0x02);//星期... write_1302(0x8c,0x15);//年...... write_1302(0x8e,0x80);//打开写保护; } /********************************** 闹钟显示子程序 **********************************/ void show_naozhong(uchar x,uchar y) { uchar i,x1,x2,y1,y2; x1=x/10; //十位 x2=x%10;//个位 WriteAddress(0x80+0x0b); //显示闹钟的小时部分 WriteData(table1[x1]); WriteAddress(0x80+0x0c); WriteData(table1[x2]); y1=y/10; //十位 y2=y%10;//个位 WriteAddress(0x80+0x0e); //显示闹钟的分钟部分 WriteData(table1[y1]); WriteAddress(0x80+0x0f); WriteData(table1[y2]); WriteAddress(0x80+0x0d); //显示小时与分钟之间的那个冒号 WriteData(':'); WriteAddress(0x80); //显示字符串:Alarm Clock for(i=0;i<11;i++) { WriteData(table[i]); } WriteAddress(0x80+0x40); //显示字符串:Today is fine! for(i=0;i<14;i++) { WriteData(table3[i]); } } void main(void) { uchar i; // ceshi=0; LcdInitiate(); //将液晶初始化 delaynms(5); //延时5ms给硬件一点反应时间 init_1302(); delaynms(5); //延时5ms给硬件一点反应时间 EA=1;//开总中断 EX0=1; //开外部中断1 IT0=0; //下降沿触发 delaynms(5); //延时5ms给硬件一点反应时间 WriteAddress(0x80+0x50); for(i=0;i<13;i++) { WriteData(table5[i]); } for(i=0;i<30;i++) { write_com(0x18); delaynms(250); } delaynms(250); write_com(0x01); while(1) { read_io(); t_sec=read_1302(0x81);//读秒 ; sec1=t_sec&0x0f; sec2=(t_sec>>4); t_min=read_1302(0x83);//读分 ; min1=t_min&0x0f; min2=(t_min>>4); t_hour=read_1302(0x85);//读小时 ; hour1=t_hour&0x0f; hour2=(t_hour>>4); t_day=read_1302(0x87);//读日; day1=t_day&0x0f; day2=(t_day>>4); t_mon=read_1302(0x89);//读月 ; mon1=t_mon&0x0f; mon2=(t_mon>>4); week=read_1302(0x8b);//读星期 ; week1=week&0x0f; t_year=read_1302(0x8d);//读年 ; year1=t_year&0x0f; year2=(t_year>>4); WriteAddress(0x80+0x06); WriteData('2'); WriteAddress(0x80+0x07); WriteData('0'); WriteAddress(0x80); //显示星期(0x80~0x80+0x05) for(i=0;i<4;i++) { WriteData(table2[i]); } WriteAddress(0x80+0x04); WriteData(table1[week1]); WriteAddress(0x80+0x08);//显示年 WriteData(table1[year2]); WriteAddress(0x80+0x09); WriteData(table1[year1]); WriteAddress(0x80+0x0a); //显示‘/’ WriteData('/'); WriteAddress(0x80+0x0b);//显示月 WriteData(table1[mon2]); WriteAddress(0x80+0x0c); WriteData(table1[mon1]); WriteAddress(0x80+0x0d); //显示‘/’ WriteData('/'); WriteAddress(0x80+0x0e);//显示日 WriteData(table1[day2]); WriteAddress(0x80+0x0f); WriteData(table1[day1]); /*第一行在此显示完毕*/ // display_dot(); //显示温度的小数点 display_cent(); //显示温度的单位 WriteAddress(0x80+0x40); //温度 WriteData(table1[WENSHI]); WriteAddress(0x80+0x40+0x01);// WriteData(table1[WENGE]); WriteAddress(0x80+0x40+0x05); //温度 WriteData(table1[SHISHI]); WriteAddress(0x80+0x40+0x06);// WriteData(table1[SHIGE]); WriteAddress(0x80+0x40+0x08); //显示小时 WriteData(table1[hour2]); WriteAddress(0x80+0x40+0x09); WriteData(table1[hour1]); WriteAddress(0x80+0x40+0x0a); //显示':' WriteData(':'); WriteAddress(0x80+0x40+0x0b); //显示分钟 WriteData(table1[min2]); WriteAddress(0x80+0x40+0x0c); WriteData(table1[min1]); WriteAddress(0x80+0x40+0x0d); //显示':' WriteData(':'); WriteAddress(0x80+0x40+0x0e); //显示秒 WriteData(table1[sec2]); WriteAddress(0x80+0x40+0x0f); WriteData(table1[sec1]); /*第二行在此显示完毕*/ //以下部分是闹钟键盘检测程序 if((x==hour2*10+hour1)&&(y==min2*10+min1))//若时间到了,则开启闹钟 { beep=0; } else //否则,关闭闹钟 { beep=1; } delaynms(10); } } void exter0()interrupt 0 { uint k; write_com(0x01); for(k=0;k<2000;k++) { while(key1==0) //键盘扫描.当key1按下时, { //闹钟的小时部分加一 delaynms(10); if(key1==0) //消抖 { delaynms(10); while(key1==0); //松手检测 x++; if(x==24) //小时部分加到24后自动清零 x=0; } } while(key2==0) //键盘检测。当key2按下时, { delaynms(10); //闹钟的分钟部分加一 if(key2==0) //消抖 { delaynms(10); while(key2==0);//松手检测 y++; if(y==60) //若分钟部分加到60,则自动清零 y=0; } } show_naozhong(x,y); //调用闹钟显示程序 } write_com(0x01); } |