zl2168 发表于 2017-11-4 21:47 请问有程序吗? |
zl2168 发表于 2017-11-9 19:34 已经找到问题了,写入1602液晶的数据加‘0’,转化为对应的字符型数据就可以了! |
探路 发表于 2017-11-5 00:43 “其实有些资料我可以找到”,资料与资料不一样!你能看懂就行,就怕看不懂,看不懂就看我的吧,能让你看懂才叫“资料”!!! |
|
你这个不是程序的问题,是显示器接触不良了,换个显示器试试看 |
给你改了一下,现在显示正常了
|
给你修改了一下,现在显示正常了
|
| 交给你个办法,不会的去淘宝店铺搜索用法。 |
探路 发表于 2017-11-5 14:14 声明一个字符数组unsigned char table[] ="0123456789";与0~9数字数组一样用 10进制变量按位分解 shi= table[x/10]; gei= table[x%10]; |
探路 发表于 2017-11-5 14:14 很简单啊: 你显示的都是数字吧,那么,每个值加上0x30 如:要显示1,则输入显示值为0x30+1=0x31,1的ASCII码就是0x31 再如:显示9,则输入显示值为0x30+9=0x39。 |
探路 发表于 2017-11-5 01:09 冗长程序一般人是不会去看的。只有读懂正确有效程序,自己对照查错。 |
HC6800-ES-V2.0 发表于 2017-11-5 09:42 你好像提醒了我,我写入的数据应该是字符型或是ASCLL码,而我写的是十进制数,但变量的十进制怎么转化为字符型呢? disp[2]=time_data[0]%16; //年十位 disp[3]=time_data[0]/16; //年个位 write_data(disp[j]); |
wulin 发表于 2017-11-5 10:20 我只是个刚入门的菜鸟,有些不一定看得懂,如果可以,我很希望大佬帮我看看我的问题出在哪里 |
|
给你一个成熟例程参考 /******************************* 描述:LCD万年历,TX-1C实验板 STC89C52RC,晶振11.0592MHz (如果晶振12MHz时间更准些) ********************************/ #include<reg52.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int sbit LCD_EN=P3^4; //定义1602液晶LCDEN端,使能信号 sbit LCD_RS=P3^5; //定义1602液晶RS端,数据/命令选择端(H/L) //sbit LCD_RW=P3^6; //定义1602液晶RW端,读/写选择端(H/L)已接地禁止读 sbit BUZZ=P2^3; //定义蜂鸣器端,按键释放和整点响 sbit dula=P2^6; //段端口 sbit wela=P2^7; //位端口 sbit key_1=P3^0; //进入调试方式 sbit key_2=P3^1; //调试+ sbit key_3=P3^2; //调试- sbit key_4=P3^3; //退出调试方式 sbit MND_1=P3^7; //矩阵键盘模拟地 uchar code keycode[] = {0x11,0x12,0x14,0x18,0x21,0x22,0x24,0x28,//按键键值 0x41,0x42,0x44,0x48,0x81,0x82,0x84,0x88}; uchar yue,ri,shi,fen,miao,week,nian; //月、日、时、分、秒、周、年变量 uchar flag=0; //功能键计数变量 uint count=0; //中断计数变量 bit Cnt1s=0; //秒标志 uchar code table[7][3]={"MON","TUE","WED","THU","FRI","SAT","SUN"};//显示周 /***********毫秒级延时函数**********/ void delay(uint x) { uint y,z; for(y=x;y>0;y--) for(z=110;z>0;z--); } /***********蜂鸣器发声函数**********/ void di(uint dd) { BUZZ=0; delay(dd); BUZZ=1; } /***********LCD1602忙等待**********/ /* uchar busycheck() { uchar s; //临时变量 LCD_RS=0; //允许写指令 // LCD_RW=1; //允许读数据(读写端已接地,禁止读) LCD_EN=1; //高电平使能读数据 delay(1); //延时 s=P0; //读P0数据赋值s LCD_EN=0; //低跳变执行 return s; //返回s值 s=0x80有效 } */ /***********液晶写指令函数**********/ void write_com(uchar com) { // while((busycheck()&0x80)==0x80);//忙等待 LCD_RS=0; //允许写指令 // LCD_RW=0; //读写端已接地,禁止读 LCD_EN=0; //初始设置LCD_EN低电平 P0=com; //传递指令 delay(5); //延时 LCD_EN=1; //使能写入 delay(5); //延时 LCD_EN=0; //低跳变执行 } /***********液晶写数据函数**********/ void write_date(uchar date) { // while((busycheck()&0x80)==0x80);//忙等待 LCD_RS=1; //允许写数据 // LCD_RW=0; //读写端已接地,禁止读 LCD_EN=0; //初始设置LCD_EN低电平 P0 =date; //传递数据 delay(5); //延时 LCD_EN=1; //使能写入 delay(5); //延时 LCD_EN=0; //低跳变执行 } /***********写年函数**********/ void write_nian(uchar add,uchar date)reentrant //reentrant定义为可重入函数,允许被递归调用 { uint bai,shi,ge; //定义百、十、个变量 bai=date/100; //分解百 shi=date%100/10; //分解十 ge=date%100%10; //分解个 write_com(0x80+add); //写指令、设置显示位置 write_date(0x30+bai);//写数据百位0~9对应的字符码是0x30~0x39 write_date(0x30+shi);//写数据十位 write_date(0x30+ge); //写数据个位 /*write_date(dat[bai]); write_date(dat[shi]); write_date(dat[ge]);*/ } /***********大小月份设置**********/ uchar dxy(uchar r) { uchar k; switch(r) { case 1: k=31; break; case 2: //闰年29天, 平年28天 if((2000+nian)%100==0) if((2000+nian)%400==0) k=29; else k=28; else if((2000+nian)%4==0) k=29; else k=28; break; case 3:k=31;break; case 4:k=30;break; case 5:k=31;break; case 6:k=30;break; case 7:k=31;break; case 8:k=31;break; case 9:k=30;break; case 10:k=31;break; case 11:k=30;break; case 12:k=31;break; } return k; } /***********写月、日、时、分、秒函数**********/ void write_yrsfm(uchar add,uchar date) { uchar shi,ge; shi=date/10; ge=date%10; write_com(0x80+add); //设置显示位置 write_date(0x30+shi); write_date(0x30+ge); /*write_date(dat[shi]); write_date(dat[ge]);*/ } /***********写星期函数**********/ void write_week(uchar add,uchar date) { uchar i; write_com(0x80+add); //设置显示位置 for(i=0;i<3;i++) { write_date(table[date][i]); delay(5); } } /***********初始化函数**********/ void init() { count=0; // dula=0; //关闭数码管段端口 wela=0; //关闭数码管位端口 // P0=0xff; //关闭发光二极管 write_com(0x38); //设置16*2显示,5*7点阵,8位数据接口 write_com(0x0c); //设置开显示,不显示光标 write_com(0x06); //写一个字符后地址指针加1 write_com(0x01); //显示清零,数据指针清零 write_com(0x80); //设置显示初始位置 write_com(0x80+1); //写出年份的最高位“2” write_date('2'); //写数据'2' write_com(0x80+5); //写指令,显示位置 日期显示部分的的两'-' write_date('-'); //写数据'-' write_com(0x80+8); //写指令,显示位置 日期显示部分的的两'-' write_date('-'); //写数据'-' write_com(0x80+0x40+6); //写指令,时间显示部分的的两个“:” write_date(':'); //写数据':' write_com(0x80+0x40+9); //写指令,时间显示部分的的两个“:” write_date(':'); //写数据':' miao=0; //秒 fen=0; //分 shi=0; //时 week=5; //星期 ri=20; //日 yue=5; //月 nian=17; //年 write_yrsfm(0x40+10,miao); //写入秒 write_yrsfm(0x40+7,fen); //写入分 write_yrsfm(0x40+4,shi); //写入时 write_week(12,week); //写入星期 write_yrsfm(9,ri); //写入日 write_yrsfm(6,yue); //写入月 write_nian(2,nian); //写入年 } /***********按键扫描函数**********/ void keyscan() { if(key_1==0) //功能键按下 { delay(10); //消抖 if(key_1==0)//功能键确认按下 { flag++; //记录功能键按下次数 while(!key_1); //确认释放功能键 di(100); //每当有按键释放蜂鸣器发出滴声提醒 if((flag==1)||(flag==8)) //第一次按下功能键光标闪烁到秒位置 { TR0=0; //关闭定时器 write_com(0x80+0x40+11); //光标定位到秒位置 write_com(0x0f); //光标开始闪烁 } if(flag==2) //第二次按下功能键光标闪烁到分钟位置 { write_com(0x80+0x40+8); } if(flag==3) //第三次按下功能键光标闪烁到时位置 { write_com(0x80+0x40+5); } if(flag==4) //第四次按下功能键光标闪烁到星期位置 { write_com(0x80+12); } if(flag==5) //第五次按下功能键光标闪烁到日位置 { write_com(0x80+10); } if(flag==6) //第六次按下功能键光标闪烁到月位置 { write_com(0x80+7); } if(flag==7) //第七次按下功能键光标闪烁到年位置 { write_com(0x80+4); } if(flag==8) //第八次按下功能键退出功能键 flag=1; //记录变成1;光标重新回到秒位置 } } if(key_4==0) //退出调节 { delay(10); if(key_4==0) { while(!key_4); //释放按键 if(TR0==0) di(100); //只在调节时有按键释放蜂鸣器发出滴声 flag=0; //功能键按键次数清零 write_com(0x0c); //取消光标闪烁 count=0; Cnt1s=0; TR0=1; //启动定时器 } } if(flag!=0) //功能键按下后flag=1 { //增大键 if(key_2==0) //只有功能键按下后,增大和减少键才有效 { delay(10); if(key_2==0)//确认增加按下 { while(!key_2); //释放按键 di(100); //每当有按键释放蜂鸣器发出滴声提醒 if(flag==1) //功能键第一次按下调节秒 { miao++; //秒加1 if(miao>59) miao=0; write_yrsfm(0x40+10,miao); //每调节一次送液晶显示一下 write_com(0x80+0x40+11); //显示位置重新回到调节处 } if(flag==2) //功能键第二次按下调节分 { fen++; if(fen>59) fen=0; write_yrsfm(0x40+7,fen); write_com(0x80+0x40+8); } if(flag==3) //功能键第三次按下调节时 { shi++; if(shi>23) shi=0; write_yrsfm(0x40+4,shi); write_com(0x80+0x40+5); } if(flag==4) //功能键第四次按下调节星期 { week++; if(week>6) week=0; write_week(12,week); write_com(0x80+12); } if(flag==5) //功能键第五次按下调节日 { ri++; if(ri>(dxy(yue))) ri=1; write_yrsfm(9,ri); write_com(0x80+10); } if(flag==6) //功能键第六次按下调节月份 { yue++; if(yue>12) yue=1; write_yrsfm(6,yue); write_com(0x80+7); } if(flag==7) //功能键第七次按下调节年份 { nian++; write_nian(2,nian); write_com(0x80+4); } } } //减少键 if(key_3==0) //减少键被按下 { delay(10); if(key_3==0)//确认减少键被按下 { while(!key_3);//按键释放 di(100); //每当有按键释放蜂鸣器发出滴声 if(flag==1) //功能键第一次按下调节秒 { //秒减1 miao--; if((miao==(-1))||(miao>59)) //59到0循环递减; miao=59; write_yrsfm(0x40+10,miao); //每调节一次送液晶显示一下 write_com(0x80+0x40+11); //显示位置重新回到调节处 } if(flag==2) //功能键第二次按下调节分 { fen--; if((fen==(-1))||(fen>59)) fen=59; write_yrsfm(0x40+7,fen); write_com(0x80+0x40+8); } if(flag==3) //功能键第三次按下调节时 { shi--; if((shi==(-1))||(shi>23)) shi=23; write_yrsfm(0x40+4,shi); write_com(0x80+0x40+5); } if(flag==4) //功能键第四次按下调节星期 { week--; if((week==(-1))||(week>6)) week=6; write_week(12,week); write_com(0x80+12); } if(flag==5) //功能键第五次按下调节日 { ri--; if((ri==0)||ri>dxy(yue)) ri=dxy(yue); write_yrsfm(9,ri); write_com(0x80+10); } if(flag==6) //功能键第六次按下调节月份 { yue--; if((yue==0)||(yue>12)) yue=12; write_yrsfm(6,yue); write_com(0x80+7); } if(flag==7) //功能键第七次按下调节年份 { nian--; write_nian(2,nian); write_com(0x80+4); } } } } } void LCD_Refresh() { if(flag==0) //调整时停止刷新 { if((ri>dxy(yue))||(ri<1)) //大小月匹配 ri=1; write_yrsfm(9,ri); //日若变化则重新写入 if(Cnt1s==1) //1秒时间到 { Cnt1s=0; //清零 miao++; //秒、分、时、星期、日、月、年自动调节功能运行 if(miao==60) { miao=0; fen++; if(fen==60) { fen=0; di(500); //整点提醒 shi++; if(shi==24) { shi=0; week++; ri++; if(week>6) week=0; write_week(12,week); //星期若变化则重新写入 if(ri>dxy(yue)) { ri=1; yue++; if(yue==13) { yue=1; nian++; write_nian(2,nian); //年份若变化则重新写入 } write_yrsfm(6,yue); //月份若变化则重新写入 } write_yrsfm(9,ri); //日若变化则重新写入 } write_yrsfm(0x40+4,shi); //时若变化则重新写入 } write_yrsfm(0x40+7,fen); //分若变化则重新写入 } write_yrsfm(0x40+10,miao); //秒若变化则重新写入 } } } void Timer0Init() //100微秒@12.000MHz { TMOD = 0x02; //设置定时器自动重载模式 // TL0 = 0x9C; //设置定时初值 // TH0 = 0x9C; //设置定时重载值 TL0=0xA4; //定时器装初值 100微秒@11.0592MHz TH0=0xA4; //定时器装初值 100微秒@11.0592MHz TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 EA=1; //开总中断 ET0=1; //开定时器0中断 } /***********主函数**********/ void main() { MND_1=0; //矩阵键盘模拟地 init(); //初始化程序 Timer0Init(); //初始化定时器 di(100); //开机蜂鸣器提示音 while(1) //不停地检测按键是否被按下 { keyscan(); //按键扫描程序 LCD_Refresh(); //液晶屏显示刷新 } } /***********中断函数**********/ void timer0() interrupt 1 { count++; //11.0592MHz误差0.17%,12MHz误差0 if(count>=10017) //1秒/11.0592MHz // if(count>=10000) //1秒/12MHz { count=0; //清0 Cnt1s=1; //1秒标标志置1 } } |
HC6800-ES-V2.0 发表于 2017-11-5 09:42 谢谢,我刚才试了一下,结果还是如图所示 ,而且我觉得程序中有将十进制转化为BCD码的,这里为何要用十六进制呢? |
|
我对照了我的程序,仔细看了你说的过程,有了以下判断,你觉得怎么样? 第一:你说用数码管是成功的,那么,1302是没有问题的。 第二:1602与数码管的显示,不同在于编码。看到你的截图,可以认为,只是1602的显示码出问题了。 综上所述,我认为你的问题,就是这个地方: uchar time_data[7]={17,11,1,20,40,30}; //年周月日时分秒 改为:uchar time_data[7]={0x17,0x11,0x01,0x20,0x40,0x30}; |
zl2168 发表于 2017-11-4 21:47 还是很希望前辈能帮我看看我自己的代码,毕竟这个花了一段时间了,我不想就这么放弃,拜托! 先前在数码管上可以正常显示,但在1602液晶就如图所示了! |
cjjcjj1 发表于 2017-11-4 21:43 我刚开始有六位数码管显示I时分秒完全没问题,但在1602液晶上显示就是乱码了 |
zl2168 发表于 2017-11-4 21:47 好吧,其实有些资料我可以找到,我就想把这个调出来,看看问题出在哪里,对于像我这样初学的菜鸟,这些调试的过程就是一种提高的过程 |
cjjcjj1 发表于 2017-11-4 21:43 检查过好几遍了,是一致的 |
|
本帖最后由 zl2168 于 2017-11-4 21:49 编辑 介绍你一个正确有效的案例,自己对照查错吧! 实例91 具有校正功能的时钟1302(LCD1602显示) 先Proteus仿真,确认有效。
实例91 带校正时钟1302(LCD1602显示).rar
(52.68 KB, 下载次数: 21)
以上摘自张志良编著《80C51单片机仿真设计实例教程——基于Keil C和Proteus》清华大学出版社ISBN 978-7-302-41682-1,书中电路和程序设计有详细说明,程序语句条条有注解。仿真电路和Hex文件能在清华出版社网站免费下载,程序源代码只能到书上看了。到图书馆借,或到新华书店翻阅,或到网上书店打折购买。 |