求大神帮忙看一下这个程序哪里不对?倒数计时 + LCD
时间:10-02
整理:3721RD
点击:
要求是这样的,有四个独立按键,按下key1,进入时间设置,此时按下key2,倒计时加一分钟,按下key3,倒计时减一分钟,调好时间之后,按下key4,开始倒计时。
我定义了四种工作状态,WAIT,SET,WORK,FINISH,我把一开始的状态定为WAIT,进入时间设置为SET,开始倒计时为WORK,倒计时结束为FINISH。
可是我写的程序在按下key1之后,头两三秒按下key2或者key3去调整时间,显示正常,可是过来两三秒之后,LCD屏幕第一行会显示一行方块,然后怎么按程序都没反应了。如果按下key1之后什么也不按就没事,过两三秒一按任何键,就显示不正常了。
看了很久程序,似乎逻辑都没有问题,会是硬件的问题吗?
我定义了四种工作状态,WAIT,SET,WORK,FINISH,我把一开始的状态定为WAIT,进入时间设置为SET,开始倒计时为WORK,倒计时结束为FINISH。
可是我写的程序在按下key1之后,头两三秒按下key2或者key3去调整时间,显示正常,可是过来两三秒之后,LCD屏幕第一行会显示一行方块,然后怎么按程序都没反应了。如果按下key1之后什么也不按就没事,过两三秒一按任何键,就显示不正常了。
看了很久程序,似乎逻辑都没有问题,会是硬件的问题吗?
- #include <reg52.h>
- #include <intrins.h>
- /* 定义端口 */
- sbit RS = P2^7;
- sbit RW = P2^6;
- sbit EN = P2^5;
- // LCD D0-D7 数据端口
- #define DataPort P0
- /* 按键端口 */
- #define KEY P2
- /* 工作模式 */
- enum {WAIT, SET, WORK, FINISH} mode = WAIT;
- /********************
- * ms延时函数 *
- ********************/
- void delay_ms(int n)
- {
- int i;
- TMOD = 0x10; // T1 工作方式 1
- for(i=0;i<n;i++)
- {
- TH1 = 0xFC;
- TL1 = 0x18;
- TR1 = 1;
- while(!TF1);
- TR1 = 0;
- }
- }
- /********************
- * LCD判忙函数 *
- ********************/
- bit lcd_check_busy()
- {
- DataPort = 0xFF;
- RS = 0;
- RW = 1;
- EN = 0;
- _nop_();
- EN = 1;
- return (bit)(DataPort & 0x80);
- }
- /*****************************
- * LCD写入命令函数 *
- *****************************/
- void lcd_write_com(unsigned char com)
- {
- while(lcd_check_busy()); //忙则等待
- RS = 0;
- RW = 0;
- EN = 1;
- DataPort = com;
- _nop_();
- EN = 0;
- }
- /************************
- * 写入数据函数 *
- ************************/
- void lcd_write_data(unsigned char dat)
- {
- while(lcd_check_busy()); //忙则等待
- RS = 1;
- RW = 0;
- EN = 1;
- DataPort = dat;
- _nop_();
- EN = 0;
- }
- /*******************
- * LCD初始化函数 *
- *******************/
- void lcd_init()
- {
- lcd_write_com(0x38); // 显示模式设置
- delay_ms(5);
- lcd_write_com(0x38);
- delay_ms(5);
- lcd_write_com(0x38);
- delay_ms(5);
- lcd_write_com(0x38);
- lcd_write_com(0x08); // 显示关闭
- lcd_write_com(0x01); // 显示清屏
- lcd_write_com(0x06); // 显示光标移动设置
- delay_ms(5);
- lcd_write_com(0x0C); // 显示开及光标设置
- }
- /*******************
- * 清屏函数 *
- *******************/
- void lcd_clear()
- {
- lcd_write_com(0x01);
- delay_ms(5);
- }
- /************************
- * 写入字符串函数 *
- ************************/
- void lcd_print_string(unsigned char x,unsigned char y,unsigned char *s)
- {
- if (y == 0) // y == 0则显示在第一行
- {
- lcd_write_com(0x80 + x);
- }
- else // 否则显示在第二行
- {
- lcd_write_com(0xC0 + x);
- }
- while(*s)
- {
- lcd_write_data(*s);
- s++;
- }
- }
- /**********************
- * 写入字符函数 *
- **********************/
- void lcd_print_char(unsigned char x,unsigned char y,unsigned char DataPort)
- {
- if(y == 0)
- {
- lcd_write_com(0x80 + x);
- }
- else
- {
- lcd_write_com(0xC0 + x);
- }
- lcd_write_data(DataPort);
- }
- /*********************
- * 键盘扫描函数 *
- *********************/
- int key;
- int min = 0, sec = 0;
- void keyscan()
- {
- if((KEY|0xF0)!=0xFF) // 有键按下
- {
- delay_ms(10); // 按键去抖
- if((KEY|0xF0)!=0xFF)
- {
- key = KEY|0xF0;
- switch(key)
- {
- case 0xFE:
- if(mode == WAIT)
- {
- mode = SET;
- lcd_clear();
- }
- break;
- case 0xFD:
- if(mode == SET && min<60)
- {
- min++;
- }
- break;
- case 0xFB:
- if(mode == SET && min>0)
- {
- min--;
- }
- break;
- case 0xF7:
- if(mode == SET)
- {
- mode = WORK;
- lcd_clear();
- }
- break;
- }
- while((KEY|0xF0) == 0xFF ? 0:1); // 等待按键释放
- }
- }
- }
- /****************
- * 计时函数 *
- ****************/
- unsigned char count = 0;
- void ticktock()
- {
- if(mode != WORK) // 只在WORK模式下计时
- {
- return;
- }
- if(count == 50) // 延时50次20ms之后,sec减1
- {
- count = 0;
- if(--sec<0)
- {
- sec = 59;
- min--;
- }
- if(min<0)
- {
- lcd_clear();
- mode = FINISH; // 倒计时结束后,进入 FINISH 模式
- }
- }else
- {
- count++;
- }
- delay_ms(20); // 每次延时20ms
- }
- /**************
- * 显示函数 *
- **************/
- unsigned char m_h, m_l, s_h, s_l;
- void display()
- {
- if(mode == WAIT) // WAIT 模式
- {
- lcd_print_string(0,1,"waitting");
- }else if(mode == FINISH)
- {
- lcd_print_string(0,0,"finish");
- delay_ms(2000);
- lcd_clear();
- mode = WAIT;
- }else
- {
- m_h = min/10 + 0x30;
- m_l = min%10 + 0x30;
- s_h = sec/10 + 0x30;
- s_l = sec%10 + 0x30;
- lcd_print_char(4,0,m_h);
- lcd_print_char(5,0,m_l);
- lcd_print_char(6,0,':');
- lcd_print_char(7,0,s_h);
- lcd_print_char(8,0,s_l);
- if(mode == SET)
- {
- lcd_print_string(4,1,"setting");
- }
- }
- }
- /*****************
- * 主函数 *
- *****************/
- void main(void)
- {
- lcd_init(); // LCD初始化
- lcd_clear(); // 清屏
- while(1)
- {
- keyscan();
- ticktock();
- display();
- }
- }