完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、项目描述
基于89C52单片机,在protues环境中开发了一个含有按键计数功能的小项目,计数最大值是999。输入是接在P32口和P3^3口的两个按键,输出是在1602显示屏上显示结果。程序在keil C51软件中编写调试。 二、硬件设计 主体是单片机一个,外围威廉希尔官方网站 有晶振威廉希尔官方网站 、复位威廉希尔官方网站 、1602液晶显示屏、两个按钮开关按键。1602的VSS接地,VDD接电源,VEE接滑动变阻器来调节电位,以此调节屏幕对比度。RS接P30,来选择数据或者命令;E接P31,控制1602使能;根据工作手册,RW可以一直为低电平,因此RW始终接地。D0~D7接到P2口作为传输总线。两个按键接在P32口和P3^3口,分别对应外部中断0和外部中断1,且低电平触发中断。晶振威廉希尔官方网站 可以提供11.0592MHZ的工作频率,复位威廉希尔官方网站 可以通过按钮开关按键复位。 三、软件代码 /********************************************************* 文 件: 1602显示屏按键计数* 作 者: * 外部晶振: 11.0592MHZ * 编译环境: Keil μVisio4 * 功 能: 数码管静态显示 * 注意事项: ********************************************************/#include《reg52.h》unsigned char code table1[]=“COUNT:”; //命名数组用来显示字符“COUNT:”int count = 0; //全局变量初始化***it RS = P3^0; //数据/命令选择接口***it EN = P3^1; //使能接口***it button1 = P3^2; //按键1接在P3^2接口,对应外部中断0***it button2 = P3^3; //按键2接在P3^3接口,对应外部中断1/********************************************************函数名:毫秒级CPU延时函数调 用:delay_ms(?);参 数:1~65535(参数不可为0)返回值:无结 果:占用CPU方式延时与参数数值相同的毫秒时间备 注:应用于1T单片机时i《600,应用于12T单片机时i《125/********************************************************/void delay(unsigned int a){ unsigned int i; while( --a != 0){ for(i = 0; i 《 125; i++); }}/********************************************************函数名:写指令函数调 用:writeinstruction(x);参 数:无符号十六进制数0x??返回值:无结 果:将指令发送给1602控制器/********************************************************/void writeinstruction(unsigned char x){ RS = 0; EN = 0; P2 = x; delay(5); EN = 1; delay(5); EN = 0;}/*********************************************************函数名:写数据函数调 用:writedata(y);参 数:无符号十六进制数0x??返回值:无结 果:将数据发送至1602内部的显示内存中/*********************************************************/void writedata(unsigned char y){ RS = 1; EN = 0; P2 = y; delay(5); EN = 1; delay(5); EN = 0;}/*********************************************************函数名:写变量函数调 用:writechar(z);参 数:无符号十六进制数0x??返回值:无结 果:将数据发送至1602内部的显示内存中备 注:不能将整数型变量count直接作为writedata的参数,需要将个、十、百位分别+48(0x30)转化成ascii码。/*********************************************************/void writechar(unsigned char z) { unsigned char A; unsigned char B; unsigned char C; RS = 1; EN = 0; A = z/1%10; //取个位 B = z/10%10; //取十位 C = z/100%10; //取百位 writedata(C+48); delay(5); writedata(B+48); //分离出变量的每一位数,再将每一位加上0x30, delay(5); writedata(A+48); //这样就变成了ASCII码了,再送给LCD才能显示出来变量的每一位的值。 delay(5);}/*********************************************************函数名:1602设置初始化函数调 用:init1602();参 数:无返回值:无结 果:初始化。具体指令在手册中查询。/*********************************************************/void init1602(){ writeinstruction(0x38); //设置显示模式 指令码 00111000 =》 0x38 delay(5); writeinstruction(0x0C); //[00001DCB]:D为显示开关,B为光标开关,C为光标闪烁开关。0x0C:开显示 不显示光标 不闪烁 delay(5); writeinstruction(0x06); //写一个字符后地址指针加一 delay(5); writeinstruction(0x01); //清屏 delay(5); }/**********************************************************函数名:主函数main/**********************************************************/void main(){ char i; init1602(); writeinstruction(0x80); //设置数据地址指针从第一个开始 delay(5); /* 初始化中断 */ EA = 1; EX0 = 1; EX1 = 1; /* 写初始字符:COUNT:0 */ for (i = 0; i 《 6; ++i) //逐个写入第一行数据 { writedata(table1); delay(20); } writeinstruction(0x02); //第一行光标返回 writeinstruction(0x80 + 0x40); //数据地址指针指向第二行第一个 writechar(count); /*砸瓦鲁多 */ while(1); //程序停在这里,等待中断到来}/*********************************************************函数名:中断显示计数值函数调 用:按下button1参 数:无返回值:无结 果:显示当前计数值。具体指令在手册中查询。/*********************************************************/void Display()interrupt 0 using 1{ int i; if(button1==0) { delay(10); if(button1==0) { count++; //按键松开后,程序会运行到这里,计数值加1 while(!button1); //如果按键没有松开,程序会停在这里 } writeinstruction(0x01); //清屏 for (i = 0; i 《 6; ++i) //逐个写入第一行数据 { writedata(table1); delay(20); } writeinstruction(0x02); //回车 writeinstruction(0x80 + 0x40); //换行 writechar(count); }/*********************************************************函数名:中断清零函数调 用:按下button2;参 数:无返回值:无结 果:计数值清零。具体指令在手册中查询。/*********************************************************/}void Clear() interrupt 2 using 1{ int i; writeinstruction(0x01); count=0; //count计数清零 for (i = 0; i 《 6; ++i) //逐个写入第一行数据 { writedata(table1); delay(20); } writeinstruction(0x02); //回车 writeinstruction(0x80 + 0x40); //换行 writechar(count);} 四、结果展示 五、经验总结 在硬件连接方面,最初是用P0口作为数据传输总线,但1602每次都出现乱码,经排查后发现原因是未接上拉电阻。在接了上拉电阻之后依然不能正常显示,于是转为P2口作为数据传输总线,同时发现了RW口可以一直接地,省去了一个接口。 在软件调试方面,在向1602发送数据时不能用写数据函数writedata()直接将变量写入,因此我又编写了一个writechar()函数,通过将变量的个、十、百位分别转为char型,再加上+48(+0x30)转成ascii码,便可以用writedata()函数将十六进制数写入。1602可以将ascii码直接转为对应的字符再屏幕上显示。 4.4 更新:按键后的刷新很慢是因为延迟函数时间过长了,之前调试的时候没注意到这里用的是毫秒级延时,所以延时设置短一点就可以变得丝滑顺畅了。RST复位也有问题,把复位电阻改成1k就可以复位了,10k太大了。 |
|
|
|
|
|
只有小组成员才能发言,加入小组>>
2591 浏览 0 评论
783浏览 1评论
218浏览 1评论
548浏览 0评论
298浏览 0评论
499浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-14 08:18 , Processed in 2.675585 second(s), Total 79, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号