完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
说明
1.平台:windows10 64位教育版 2.工具:普中科技HC6800-ES V2.0 、keil uVision 2 3.注意:芯片STC89C52,8位1602液晶显示 4.实现效果: 通电之后,1602开始显示计时,按下第一个按键进入设置,按下第二个按键设置时分秒的各个位置,按下第三个按键在对应的时分秒的位置数字加1,按下第四个按键在对应的时分秒的位置数字减1 原理 笔者参考的是郭天祥的《新概念51单片机C语言教程》和网上的普中科技的单片机的使用教程,具体使用教程,在哔哩哔哩上面搜“普中科技51单片机”也有。要找到能用的代码,网上是很多的,不过笔者是自己在明白原理之后,自己编写程序实现的,自己独立思考的过程很重要。 以下是普中科技的使用教程:详细的代码里面也有 流程 我是按照一个一个功能的实现来把代码加进去的,利用单片机上面的独立模块就可以实现独立测试。 1.按键检测 这里我用到的是4个独立按键,实现的功能是第一个按键按下进入时间设置,第二个按键按下设置时分秒,第三个按键按下对应的位置加1,第四个按键按下对应位置减1,注意,这里的其他独立按键起作用的前提是第一个按键要先按下进入设置,否则按键无效。 以下是代码: I/O口声明 ***it key1 = P3^0; //第二个按键 ***it key2 = P3^1; //第一个按键 ***it key3 = P3^2; //第三个按键 ***it key4 = P3^3; //第四个按键 按键检测函数 void keyscan() { if (key1 == 0) { delay10ms(); if (key1 == 0) { //要实现的功能 while(!key1); //等待按键松开 } } if (key2 == 0) { delay10ms(); if (key2 == 0) { //要实现的功能 while(!key2); } } if (key3 == 0) { delay10ms(); if (key3 == 0) { //要实现的功能 while(!key3); } } if (key4 == 0) { delay10ms(); if (key4 == 0) { //要实现的功能 while(!key4); } } } //延时10ms以消除按键抖动 void delay10ms() { unsigned char a,b,c; for(c = 1;c > 0; c--) for(b = 38;b > 0; b--) for(a = 130;a>0;a--); } 2.定时器中断 采用的是定时器0,工作方式2 以下是代码: TMOD = 0x02; //定时器0,工作方式2 TH0 = 0x9c; //装入初值,高4位 TL0 = 0x9c; //装入初值,低4位 EA = 1; //打开总中断 ET0 = 1; //打开定时器中断 TR0 = 1; //启动定时器 void Timer() interrupt 1 { TH0 = 0x9c; //重装初值 TL0 = 0x9c; num++; //num = 10000时为1s } 3.1602液晶显示 这里使用是8位的1602液晶,如果有人用的是4位的,详细代码在之前的普中科技的官方教程里面有。 以下是代码: I/O口声明 ***it LED_RS = P2^6; //0为写命令,1为写数据 ***it LED_WR = P2^5; //0为从1602液晶写数据,1为读数据 ***it LED_EN = P2^7; //使能接口,置为0 初始化函数 void init() { write_data(0x38,0); //设置16*2显示,5*7点阵 write_data(0x0c,0); //设置开显示,不显示光标 write_data(0x06,0); //写一个字符后地址指针加1 write_data(0x01,0); //显示清零,数据指针清零 write_data(0x80,0); //开始写的地址 } 写命令和数据函数,通过传入0和1来控制写命令或者数据 void write_data(uchar dat,uchar wr) { if(wr == 0) LED_RS = 0; //写命令 else LED_RS = 1; //写命令 LED_WR = 0; LED_EN = 0; P0 = dat; delay(5); //延时等待数据稳定 LED_EN = 1; delay(5); LED_EN = 0; } void delay(uchar t) { uchar i; for(;t>0;t--) for(i=199;i>0;i--); } 在进行测试之前,要连接一下威廉希尔官方网站 ,因为对于普中的这款单片机,它是通过U2锁存器来控制数据方向的,如下图所示,要把三个排针中的最右边两个短接在一起。 独立模块测试完成之后就是进行完整的功能组合,即代码组合。 4.完整代码 #include #define uchar unsigned char #define uint unsigned int ***it key1 = P3^0; //第二个按键 ***it key2 = P3^1; //第一个按键 ***it key3 = P3^2; //第三个按键 ***it key4 = P3^3; //第四个按键 ***it LED_RS = P2^6; //用来确定是选择写命令还是数据 ***it LED_WR = P2^5; //读写选择,1表示读,0表示写 ***it LED_EN = P2^7; //使能信号,置为0 void keyscan(); //检测按键是否按下 void init(); void delay(uchar ); void write_data(uchar ,uchar ); void display(uchar ,uchar ,uchar ); //只有当按下第一个按键时(key_flag),其他按键才起作用 //position 用来记录光标位置 uchar sec,min,hour,key_flag,position; uchar timer_op;//定时器启动和关闭标志 uchar timedis[8];//保存秒、分、时的各个位的数字 uint num; //定时器计数使用 void main() { init(); while(1) { keyscan(); if(num == 10000) //是否到了1s { sec++; if(sec > 59) { sec = 0; min++; if(min > 59) { min = 0; hour++; if(hour > 59) hour = 0; } } num = 0; display(sec,min,hour); } } } void init() { //1602液晶显示初始化 write_data(0x38,0); //设置16*2显示,8位数据口 write_data(0x0f,0); //开显示,光标闪烁 write_data(0x06,0); //写入一个字符,地址指针加1 write_data(0x01,0); //显示清零,指针清零 write_data(0x80,0); //写入的起始地址 //定时器初始化 TMOD = 0x02; //设置定时器工作方式 TH0 = 0x9c; //装入初值,高四位 TL0 = 0x9c; //装入初值,低四位 EA = 1; //打开总中断 ET0 = 1; //打开定时器中断 TR0 = 1; //启动定时器 } void keyscan() { uchar i; if (key1 == 0) { delay(25); //延时10ms if (key1 == 0) { position = 0; key_flag = 1; timer_op++; if(timer_op == 1) TR0 = 0; //关闭定时器 else { TR0 = 1; //开启定时器 timer_op = 0; key_flag = 0; //再按一次离开设置 } write_data(0x80,0); while(!key1); //等待按键松开 } } if (key2 == 0) { delay(25); if (key2 == 0) { if(key_flag == 1) { add_num = 0; position++; if(position == 8) position = 0; write_data(position+0x80,0); //更新光标位置 } while(!key2); } } if (key3 == 0) { //按下一次加1 delay(25); if (key3 == 0) { if(key_flag == 1) { timedis[position]++; if((position == 1)||(position == 4)||(position == 7)) { if(timedis[position] == 10) timedis[position] = 0; } else if((position == 0)||(position == 3)||(position == 6)) { if(timedis[position] == 6) timedis[position] = 0; } } hour = timedis[0]*10 + timedis[1]; min = timedis[3]*10 + timedis[4]; sec = timedis[6]*10 + timedis[7]; //按下一次按键更新一次液晶显示 write_data(0x80,0); for(i=0;i<8;i++) write_data(0x30+timedis,1); while(!key3); } } if (key4 == 0) { //按下一次减1 delay(25); if (key4 == 0) { if(key_flag == 1) { timedis[position]--; if((position == 1)||(position == 4)||(position == 7)) { if(timedis[position] == -1) timedis[position] = 9; } else if((position == 0)||(position == 3)||(position == 6)) { if(timedis[position] == -1) timedis[position] = 5; } } hour = timedis[0]*10 + timedis[1]; min = timedis[3]*10 + timedis[4]; sec = timedis[6]*10 + timedis[7]; write_data(0x80,0); for(i=0;i<8;i++) write_data(0x30+timedis,1); while(!key4); } } } void delay(uchar t) { uchar i; for(;t>0;t--) for(i=199;i>0;i--); } void write_data(uchar dat,uchar wr) { if(wr == 0) LED_RS = 0; //写命令 else LED_RS = 1; //写数据 LED_WR = 0; LED_EN = 0; P0 = dat; delay(5); LED_EN = 1; delay(5); LED_EN = 0; } void Timer() interrupt 1 { TH0 = 0x9c; //重装初值 TL0 = 0x9c; num++; } void display(uchar sec_,uchar min_,uchar hour_) { uchar i; timedis[2] = 10; timedis[5] = 10; timedis[0] = hour_/10; timedis[1] = hour_%10; timedis[3] = min_/10; timedis[4] = min_%10; timedis[6] = sec_/10; timedis[7] = sec_%10; write_data(0x80,0); for(i=0;i<8;i++) write_data(0x30+timedis,1); } |
|
|
|
只有小组成员才能发言,加入小组>>
2591 浏览 0 评论
783浏览 1评论
218浏览 1评论
548浏览 0评论
297浏览 0评论
498浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-13 22:26 , Processed in 1.145922 second(s), Total 79, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号