微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 求大神帮忙看一下这个程序哪里不对?倒数计时 + LCD

求大神帮忙看一下这个程序哪里不对?倒数计时 + LCD

时间:10-02 整理:3721RD 点击:
要求是这样的,有四个独立按键,按下key1,进入时间设置,此时按下key2,倒计时加一分钟,按下key3,倒计时减一分钟,调好时间之后,按下key4,开始倒计时。
我定义了四种工作状态,WAIT,SET,WORK,FINISH,我把一开始的状态定为WAIT,进入时间设置为SET,开始倒计时为WORK,倒计时结束为FINISH。
可是我写的程序在按下key1之后,头两三秒按下key2或者key3去调整时间,显示正常,可是过来两三秒之后,LCD屏幕第一行会显示一行方块,然后怎么按程序都没反应了。如果按下key1之后什么也不按就没事,过两三秒一按任何键,就显示不正常了。
看了很久程序,似乎逻辑都没有问题,会是硬件的问题吗?

  1. #include <reg52.h>
  2. #include <intrins.h>

  3. /* 定义端口        */
  4. sbit RS = P2^7;       
  5. sbit RW = P2^6;
  6. sbit EN = P2^5;


  7. // LCD D0-D7 数据端口
  8. #define DataPort P0

  9. /* 按键端口        */
  10. #define KEY P2

  11. /* 工作模式 */
  12. enum {WAIT, SET, WORK, FINISH} mode = WAIT;

  13. /********************
  14. * ms延时函数 *
  15. ********************/
  16. void delay_ms(int n)
  17. {
  18. int i;
  19. TMOD = 0x10; // T1 工作方式 1
  20. for(i=0;i<n;i++)
  21. {
  22. TH1 = 0xFC;
  23. TL1 = 0x18;
  24. TR1 = 1;
  25. while(!TF1);
  26. TR1 = 0;
  27. }
  28. }

  29. /********************
  30. * LCD判忙函数 *
  31. ********************/
  32. bit lcd_check_busy()
  33. {
  34. DataPort = 0xFF;
  35. RS = 0;
  36. RW = 1;
  37. EN = 0;
  38. _nop_();
  39. EN = 1;
  40. return (bit)(DataPort & 0x80);
  41. }

  42. /*****************************
  43. * LCD写入命令函数         *
  44. *****************************/
  45. void lcd_write_com(unsigned char com)
  46. {
  47. while(lcd_check_busy()); //忙则等待
  48. RS = 0;
  49. RW = 0;
  50. EN = 1;
  51. DataPort = com;
  52. _nop_();
  53. EN = 0;
  54. }

  55. /************************
  56. * 写入数据函数 *
  57. ************************/
  58. void lcd_write_data(unsigned char dat)
  59. {
  60. while(lcd_check_busy()); //忙则等待
  61. RS = 1;
  62. RW = 0;
  63. EN = 1;
  64. DataPort = dat;
  65. _nop_();
  66. EN = 0;
  67. }

  68. /*******************
  69. * LCD初始化函数 *
  70. *******************/
  71. void lcd_init()
  72. {
  73. lcd_write_com(0x38); // 显示模式设置
  74. delay_ms(5);
  75. lcd_write_com(0x38);
  76. delay_ms(5);
  77. lcd_write_com(0x38);
  78. delay_ms(5);
  79. lcd_write_com(0x38);
  80. lcd_write_com(0x08); // 显示关闭
  81. lcd_write_com(0x01); // 显示清屏
  82. lcd_write_com(0x06); // 显示光标移动设置
  83. delay_ms(5);
  84. lcd_write_com(0x0C); // 显示开及光标设置
  85. }

  86. /*******************
  87. * 清屏函数 *
  88. *******************/
  89. void lcd_clear()
  90. {
  91. lcd_write_com(0x01);
  92. delay_ms(5);
  93. }

  94. /************************
  95. * 写入字符串函数        *
  96. ************************/
  97. void lcd_print_string(unsigned char x,unsigned char y,unsigned char *s)
  98. {
  99. if (y == 0) // y == 0则显示在第一行
  100. {
  101. lcd_write_com(0x80 + x);
  102. }
  103. else // 否则显示在第二行
  104. {
  105. lcd_write_com(0xC0 + x);
  106. }
  107. while(*s)
  108. {
  109. lcd_write_data(*s);
  110. s++;
  111. }
  112. }

  113. /**********************
  114. * 写入字符函数         *
  115. **********************/
  116. void lcd_print_char(unsigned char x,unsigned char y,unsigned char DataPort)
  117. {
  118. if(y == 0)
  119. {
  120. lcd_write_com(0x80 + x);
  121. }
  122. else
  123. {
  124. lcd_write_com(0xC0 + x);
  125. }
  126. lcd_write_data(DataPort);
  127. }

  128. /*********************
  129. *         键盘扫描函数 *
  130. *********************/
  131. int key;
  132. int min = 0, sec = 0;
  133. void keyscan()
  134. {
  135. if((KEY|0xF0)!=0xFF) // 有键按下
  136. {
  137. delay_ms(10); // 按键去抖
  138. if((KEY|0xF0)!=0xFF)
  139. {       
  140. key = KEY|0xF0;
  141. switch(key)
  142. {
  143. case 0xFE:
  144. if(mode == WAIT)
  145. {
  146. mode = SET;
  147. lcd_clear();
  148. }
  149. break;

  150. case 0xFD:
  151. if(mode == SET && min<60)
  152. {
  153. min++;
  154. }
  155. break;

  156. case 0xFB:
  157. if(mode == SET && min>0)
  158. {
  159. min--;
  160. }
  161. break;

  162. case 0xF7:
  163. if(mode == SET)
  164. {
  165. mode = WORK;
  166. lcd_clear();
  167. }
  168. break;
  169. }
  170. while((KEY|0xF0) == 0xFF ? 0:1);        // 等待按键释放
  171. }
  172. }
  173. }

  174. /****************
  175. *         计时函数 *
  176. ****************/
  177. unsigned char count = 0;
  178. void ticktock()
  179. {
  180. if(mode != WORK) // 只在WORK模式下计时
  181. {
  182. return;
  183. }
  184. if(count == 50)         // 延时50次20ms之后,sec减1
  185. {
  186. count = 0;
  187. if(--sec<0)
  188. {
  189. sec = 59;
  190. min--;
  191. }
  192. if(min<0)
  193. {
  194. lcd_clear();
  195. mode = FINISH; // 倒计时结束后,进入 FINISH 模式
  196. }
  197. }else
  198. {
  199. count++;
  200. }
  201. delay_ms(20);         // 每次延时20ms
  202. }

  203. /**************
  204. * 显示函数 *
  205. **************/
  206. unsigned char m_h, m_l, s_h, s_l;
  207. void display()
  208. {
  209. if(mode == WAIT) // WAIT 模式
  210. {
  211. lcd_print_string(0,1,"waitting");       
  212. }else if(mode == FINISH)
  213. {
  214. lcd_print_string(0,0,"finish");       
  215. delay_ms(2000);
  216. lcd_clear();
  217. mode = WAIT;
  218. }else
  219. {
  220. m_h = min/10 + 0x30;
  221. m_l = min%10 + 0x30;
  222. s_h = sec/10 + 0x30;
  223. s_l = sec%10 + 0x30;

  224. lcd_print_char(4,0,m_h);
  225. lcd_print_char(5,0,m_l);
  226. lcd_print_char(6,0,':');
  227. lcd_print_char(7,0,s_h);
  228. lcd_print_char(8,0,s_l);

  229. if(mode == SET)
  230. {
  231. lcd_print_string(4,1,"setting");
  232. }       
  233. }       
  234. }

  235. /*****************
  236. * 主函数 *
  237. *****************/
  238. void main(void)
  239. {
  240. lcd_init(); // LCD初始化
  241. lcd_clear(); // 清屏
  242. while(1)
  243. {
  244. keyscan();
  245. ticktock();
  246. display();
  247. }
  248. }

复制代码



Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top