您的位置 首页 观点

第79节:经过主菜单移动光标来进入子菜单窗口的液晶屏程序

开场白:其实主菜单窗口与子菜单窗口本质都是多窗口菜单程序,只不过我在按键服务程序里面建立起来了一条主窗口与子窗口的关系链。这个

开场白:
其实主菜单窗口与子菜单窗口实质都是多窗口菜单程序,只不过我在按键服务程序里边建立起来了一条主窗口与子窗口的联系链。这个联系链仍是用switch句子建立起来的,在某个窗口某个部分显现上,操作某个按键就会切换到不同的窗口显现。
持续稳固上一节教给我们的两个知识点:
榜首个知识点:我在前面讲数码管显现的时分就提出了一个 “一二级菜单显现理论”:但凡人机界面显现,不管是数码管仍是液晶屏,都能够把显现的内容分红不同的窗口来显现,每个显现的窗口中又能够分红不同的部分显现。其间窗口便是一级菜单,用ucWd变量表明。部分便是二级菜单,用ucWdxPart来表明。不同的窗口,会有不同的更新显现变量ucWdXUpdate来对应,表明整屏悉数更新显现。不同的部分,也会有不同的更新显现变量ucWdXPartYUpdate来对应,表明部分更新显现。把每一个窗口的内容分为两种类型,一种类型是那些不必常常改写显现的内容,只需在切换窗口的时分才需求更新的,这种内容放在整屏更新显现的括号里,比方清屏操作等内容。别的一种是那些常常需求改写显现的内容,这种内容放在部分更新显现的括号里。
第二个知识点:按键怎么跟液晶屏显现有机的结合起来?只需遵从鸿哥总结出来的一个规则“在不同的窗口下,依据不同的部分变量来操作不同的参数”,这样再杂乱的人机交互程序都会显得很简单明晰。

具体内容,请看源代码解说。

(1)硬件渠道:依据朱兆祺51单片机学习板。加按键对应S1键,减按键对应S5键,切换“光标”移动按键对应S9键,设置参数按键对应S13键。

(2)完成功用:
经过按键设置6个不同的参数。
有4个窗口。第1个窗口是主菜单界面,经过光标切换能够进去设置不同参数的子菜单界面。第2个窗口是设置时刻规模界面。第3个窗口是设置速度规模界面。第4个窗口是设置频率规模界面。每个设置界面显现2个参数。每个参数的规模是从0到99。
有4个按键:
(a) 一个是进入和退出S13按键,按一次进入选中的子菜单。再按一次退出子菜单。
(b) 一个是移动光标S9按键,顺次按下此按键,液晶屏上的光标会从上往下移动,表明选中不同的参数。当移动到每个窗口最下边那一行时,再按下此按键会把光标移动到榜首个参数。
(c) 一个是减数S5按键,在设置参数模式下,顺次按下此按键,被选中的参数会逐步减小。
(d) 一个是加数S1按键,在设置参数形式下,顺次按下此按键,被选中的参数会逐步加大。

(3)源代码解说如下:

  1. #include “REG52.H”
  2. /* 注释一:
  3. * 本程序用到的变量比较多,所以在keil编译形式里要设置一下编译形式memory model,
  4. * 不然编译会犯错.右键单击Target挑选“Options for TargetTarget1”就会出来一个框
  5. * 在memory model中挑选compact:variables in pdata 就能够了。
  6. */
  7. #define const_voice_short40 //蜂鸣器短叫的持续时刻
  8. #define const_key_time120 //按键去颤动延时的时刻
  9. #define const_key_time220 //按键去颤动延时的时刻
  10. #define const_key_time320 //按键去颤动延时的时刻
  11. #define const_key_time420 //按键去颤动延时的时刻
  12. sbit key_sr1=P0^0; //对应朱兆祺学习板的S1键
  13. sbit key_sr2=P0^1; //对应朱兆祺学习板的S5键
  14. sbit key_sr3=P0^2; //对应朱兆祺学习板的S9键
  15. sbit key_sr4=P0^3; //对应朱兆祺学习板的S13键
  16. sbit key_gnd_dr=P0^4; //模仿独立按键的地GND,因而有必要一向输出低电平
  17. sbit beep_dr=P2^7; //蜂鸣器的驱动IO口
  18. sbitLCDCS_dr= P1^6;//片选线
  19. sbitLCDSID_dr = P1^7;//串行数据线
  20. sbitLCDCLK_dr = P3^2;//串行时钟线
  21. sbitLCDRST_dr = P3^4;//复位线
  22. void SendByteToLcd(unsigned char ucData);//发送一个字节数据到液晶模块
  23. void SPIWrite(unsigned char ucWData, unsigned char ucWRS); //模仿SPI发送一个字节的指令或许数据给液晶模块的底层驱动
  24. void WriteCommand(unsigned char ucCommand); //发送一个字节的指令给液晶模块
  25. void LCDWriteData(unsigned char ucData); //发送一个字节的数据给液晶模块
  26. void LCDInit(void);//初始化函数内部包含液晶模块的复位
  27. void display_clear(unsigned char ucFillDate); // 清屏 悉数显现空填充0x00 悉数显现点阵用0xff
  28. void insert_buffer_to_canvas(unsigned int x,unsigned int y,const unsigned char*ucArray,unsigned char ucFbFlag,unsigned int x_amount,unsigned int y_amount);//把字模刺进画布.
  29. void display_lattice(unsigned int x,unsigned int y,const unsigned char*ucArray,unsigned char ucFbFlag,unsigned int x_amount,unsigned int y_amount,unsigned int uiOffSetAddr); //显现恣意点阵函数
  30. unsigned char *number_to_matrix(unsigned charucBitNumber); //把一位数字转化成字模首地址的函数
  31. void delay_short(unsigned int uiDelayshort); //延时
  32. void delay_long(unsigned int uiDelayLong);
  33. void T0_time(); //守时中止函数
  34. void key_service(void); //按键服务的应用程序
  35. void key_scan(void);//按键扫描函数 放在守时中止里
  36. void initial_myself();
  37. void initial_peripheral();
  38. void lcd_display_service(void); //应用层面的液晶屏显现程序
  39. void clear_all_canvas(void);//把画布悉数清零
  40. void wd1(void);//窗口1主菜单
  41. void wd2(void);//窗口2设置时刻
  42. void wd3(void);//窗口3设置速度
  43. void wd4(void);//窗口4设置频率
  44. code unsigned char Zf816_0[]=
  45. {
  46. /*–文字:0–*/
  47. /*–宋体12;此字体下对应的点阵为:宽x高=8×16 –*/
  48. 0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00,
  49. };
  50. code unsigned char Zf816_1[]=
  51. {
  52. /*–文字:1–*/
  53. /*–宋体12;此字体下对应的点阵为:宽x高=8×16 –*/
  54. 0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00,
  55. };
  56. code unsigned char Zf816_2[]=
  57. {
  58. /*–文字:2–*/
  59. /*–宋体12;此字体下对应的点阵为:宽x高=8×16 –*/
  60. 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x04,0x04,0x08,0x10,0x20,0x42,0x7E,0x00,0x00,
  61. };
  62. code unsigned char Zf816_3[]=
  63. {
  64. /*–文字:3–*/
  65. /*–宋体12;此字体下对应的点阵为:宽x高=8×16 –*/
  66. 0x00,0x00,0x00,0x3C,0x42,0x42,0x04,0x18,0x04,0x02,0x02,0x42,0x44,0x38,0x00,0x00,
  67. };
  68. code unsigned char Zf816_4[]=
  69. {
  70. /*–文字:4–*/
  71. /*–宋体12;此字体下对应的点阵为:宽x高=8×16 –*/
  72. 0x00,0x00,0x00,0x04,0x0C,0x14,0x24,0x24,0x44,0x44,0x7E,0x04,0x04,0x1E,0x00,0x00,
  73. };
  74. code unsigned char Zf816_5[]=
  75. {
  76. /*–文字:5–*/
  77. /*–宋体12;此字体下对应的点阵为:宽x高=8×16 –*/
  78. 0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x58,0x64,0x02,0x02,0x42,0x44,0x38,0x00,0x00,
  79. };
  80. code unsigned char Zf816_6[]=
  81. {
  82. /*–文字:6–*/
  83. /*–宋体12;此字体下对应的点阵为:宽x高=8×16 –*/
  84. 0x00,0x00,0x00,0x1C,0x24,0x40,0x40,0x58,0x64,0x42,0x42,0x42,0x24,0x18,0x00,0x00,
  85. };
  86. code unsigned char Zf816_7[]=
  87. {
  88. /*–文字:7–*/
  89. /*–宋体12;此字体下对应的点阵为:宽x高=8×16 –*/
  90. 0x00,0x00,0x00,0x7E,0x44,0x44,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,
  91. };
  92. code unsigned char Zf816_8[]=
  93. {
  94. /*–文字:8–*/
  95. /*–宋体12;此字体下对应的点阵为:宽x高=8×16 –*/
  96. 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x42,0x3C,0x00,0x00,
  97. };
  98. code unsigned char Zf816_9[]=
  99. {
  100. /*–文字:9–*/
  101. /*–宋体12;此字体下对应的点阵为:宽x高=8×16 –*/
  102. 0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x26,0x1A,0x02,0x02,0x24,0x38,0x00,0x00,
  103. };
  104. code unsigned char Zf816_nc[]=//空字模
  105. {
  106. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  107. };
  108. code unsigned char Zf816_mao_hao[]=//冒号
  109. {
  110. /*–文字::–*/
  111. /*–宋体12;此字体下对应的点阵为:宽x高=8×16 –*/
  112. 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,
  113. };
  114. code unsigned char Hz1616_zhu[]=
  115. {
  116. /*–文字:主–*/
  117. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  118. 0x02,0x00,0x01,0x80,0x01,0x00,0x00,0x08,0x3F,0xFC,0x01,0x00,0x01,0x00,0x01,0x08,
  119. 0x3F,0xFC,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x04,0x7F,0xFE,0x00,0x00,0x00,0x00,
  120. };
  121. code unsigned char Hz1616_cai[]=
  122. {
  123. /*–文字:菜–*/
  124. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  125. 0x04,0x40,0xFF,0xFE,0x04,0x40,0x04,0x40,0x3F,0xF8,0x22,0x08,0x11,0x10,0x08,0x20,
  126. 0x01,0x00,0x7F,0xFE,0x03,0x80,0x05,0x40,0x09,0x30,0x11,0x1C,0x61,0x08,0x01,0x00,
  127. };
  128. code unsigned char Hz1616_dan[]=
  129. {
  130. /*–文字:单–*/
  131. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  132. 0x08,0x20,0x06,0x30,0x04,0x40,0x3F,0xF8,0x21,0x08,0x3F,0xF8,0x21,0x08,0x21,0x08,
  133. 0x3F,0xF8,0x21,0x08,0x01,0x00,0xFF,0xFE,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
  134. };
  135. code unsigned char Hz1616_she[]=
  136. {
  137. /*–文字:设–*/
  138. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  139. 0x40,0x00,0x21,0xF0,0x31,0x10,0x21,0x10,0x01,0x10,0x01,0x10,0xE2,0x0E,0x25,0xF8,
  140. 0x21,0x08,0x21,0x08,0x20,0x90,0x20,0x90,0x28,0x60,0x30,0x90,0x23,0x0E,0x0C,0x04,
  141. };
  142. code unsigned char Hz1616_zhi[]=
  143. {
  144. /*–文字:置–*/
  145. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  146. 0x3F,0xF8,0x24,0x48,0x24,0x48,0x3F,0xF8,0x01,0x00,0x7F,0xFC,0x02,0x00,0x1F,0xF0,
  147. 0x10,0x10,0x1F,0xF0,0x10,0x10,0x1F,0xF0,0x10,0x10,0x1F,0xF0,0x10,0x10,0xFF,0xFE,
  148. };
  149. code unsigned char Hz1616_su[]=
  150. {
  151. /*–文字:速–*/
  152. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  153. 0x00,0x80,0x40,0x80,0x2F,0xFC,0x20,0x80,0x00,0x80,0x07,0xF8,0xE4,0x88,0x24,0x88,
  154. 0x27,0xF8,0x21,0xA0,0x22,0x98,0x2C,0x88,0x20,0x80,0x50,0x80,0x8F,0xFE,0x00,0x00,
  155. };
  156. code unsigned char Hz1616_du[]=
  157. {
  158. /*–文字:度–*/
  159. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  160. 0x01,0x00,0x00,0x80,0x3F,0xFE,0x22,0x20,0x22,0x20,0x2F,0xFC,0x22,0x20,0x23,0xE0,
  161. 0x20,0x00,0x27,0xF8,0x22,0x10,0x21,0x20,0x20,0xC0,0x41,0x30,0x46,0x0E,0x98,0x04,
  162. };
  163. code unsigned char Hz1616_shi[]=
  164. {
  165. /*–文字:时–*/
  166. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  167. 0x00,0x10,0x00,0x10,0x7C,0x10,0x44,0x10,0x47,0xFE,0x44,0x10,0x7C,0x10,0x45,0x10,
  168. 0x44,0x90,0x44,0x90,0x7C,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x50,0x00,0x20,
  169. };
  170. code unsigned char Hz1616_jian[]=
  171. {
  172. /*–文字:间–*/
  173. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  174. 0x20,0x00,0x13,0xFC,0x10,0x04,0x40,0x04,0x47,0xE4,0x44,0x24,0x44,0x24,0x47,0xE4,
  175. 0x44,0x24,0x44,0x24,0x47,0xE4,0x40,0x04,0x40,0x04,0x40,0x04,0x40,0x14,0x40,0x08,
  176. };
  177. code unsigned char Hz1616_pin[]=
  178. {
  179. /*–文字:频–*/
  180. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  181. 0x08,0x00,0x08,0xFE,0x4E,0x20,0x48,0x40,0x48,0xFC,0xFE,0x84,0x00,0xA4,0x08,0xA4,
  182. 0x4A,0xA4,0x4A,0xA4,0x84,0xA4,0x08,0x50,0x10,0x48,0x20,0x86,0xC3,0x02,0x00,0x00,
  183. };
  184. code unsigned char Hz1616_lv[]=
  185. {
  186. /*–文字:率–*/
  187. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  188. 0x02,0x00,0x01,0x00,0x7F,0xFE,0x41,0x00,0x22,0x28,0x17,0xD0,0x04,0x80,0x11,0x10,
  189. 0x22,0x48,0x47,0xC4,0x01,0x20,0xFF,0xFE,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
  190. };
  191. code unsigned char Hz1616_fan[]=
  192. {
  193. /*–文字:范–*/
  194. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  195. 0x04,0x20,0x04,0x20,0xFF,0xFE,0x04,0x60,0x40,0x00,0x31,0xF8,0x91,0x08,0x61,0x08,
  196. 0x49,0x08,0x09,0x38,0x11,0x10,0xE1,0x00,0x21,0x04,0x21,0x04,0x20,0xFC,0x20,0x00,
  197. };
  198. code unsigned char Hz1616_wei[]=
  199. {
  200. /*–文字:围–*/
  201. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  202. 0x7F,0xFC,0x42,0x04,0x42,0x04,0x5F,0xF4,0x42,0x04,0x4F,0xE4,0x42,0x04,0x5F,0xE4,
  203. 0x42,0x24,0x42,0x24,0x42,0x24,0x42,0xA4,0x42,0x44,0x40,0x04,0x7F,0xFC,0x40,0x04,
  204. };
  205. code unsigned char Hz1616_shang[]=
  206. {
  207. /*–文字:上–*/
  208. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  209. 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0xF8,0x01,0x00,
  210. 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x04,0x7F,0xFE,0x00,0x00,
  211. };
  212. code unsigned char Hz1616_xia[]=
  213. {
  214. /*–文字:下–*/
  215. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  216. 0x00,0x04,0x7F,0xFE,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0xC0,0x01,0x60,0x01,0x30,
  217. 0x01,0x20,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
  218. };
  219. code unsigned char Hz1616_xian[]=
  220. {
  221. /*–文字:限–*/
  222. /*–宋体12;此字体下对应的点阵为:宽x高=16×16 –*/
  223. 0x00,0x00,0xFB,0xF8,0x92,0x08,0x93,0xF8,0xA2,0x08,0xA2,0x08,0x93,0xF8,0x8A,0x80,
  224. 0x8A,0x48,0xAA,0x50,0x92,0x20,0x82,0x20,0x82,0x10,0x82,0x8E,0x83,0x04,0x82,0x00,
  225. };
  226. unsigned char ucCanvasBuffer[]= //画布显现数组。留意,这儿没有code关键字,是全局变量。初始化悉数填充0x00
  227. {
  228. 0x00,0x00,0x00,0x00,//上半屏
  229. 0x00,0x00,0x00,0x00,
  230. 0x00,0x00,0x00,0x00,
  231. 0x00,0x00,0x00,0x00,
  232. 0x00,0x00,0x00,0x00,
  233. 0x00,0x00,0x00,0x00,
  234. 0x00,0x00,0x00,0x00,
  235. 0x00,0x00,0x00,0x00,
  236. //————上半屏和下半屏的分割线———–
  237. 0x00,0x00,0x00,0x00,//下半屏
  238. 0x00,0x00,0x00,0x00,
  239. 0x00,0x00,0x00,0x00,
  240. 0x00,0x00,0x00,0x00,
  241. 0x00,0x00,0x00,0x00,
  242. 0x00,0x00,0x00,0x00,
  243. 0x00,0x00,0x00,0x00,
  244. 0x00,0x00,0x00,0x00,
  245. };
  246. unsigned char ucKeySec=0; //被触发的按键编号
  247. unsigned intuiVoiceCnt=0;//蜂鸣器鸣叫的持续时刻计数器
  248. unsigned char ucWd=1; //窗口变量
  249. unsigned char ucWd1Part=1;//窗口1的部分变量,代表选中某一行。
  250. unsigned char ucWd1Update=1; //窗口1的整屏更新显现变量 1代表更新显现,呼应函数内部会清零
  251. unsigned char ucWd1Part1Update=0; //窗口1的第1个部分更新显现变量1代表更新显现,呼应函数内部会清零
  252. unsigned char ucWd1Part2Update=0; //窗口1的第2个部分更新显现变量1代表更新显现,呼应函数内部会清零
  253. unsigned char ucWd1Part3Update=0; //窗口1的第3个部分更新显现变量1代表更新显现,呼应函数内部会清零
  254. unsigned char ucWd2Part=1;//窗口2的部分变量,代表选中某一行。
  255. unsigned char ucWd2Update=0; //窗口2的整屏更新显现变量 1代表更新显现,呼应函数内部会清零
  256. unsigned char ucWd2Part1Update=0; //窗口2的第1个部分更新显现变量1代表更新显现,呼应函数内部会清零
  257. unsigned char ucWd2Part2Update=0; //窗口2的第2个部分更新显现变量1代表更新显现,呼应函数内部会清零
  258. unsigned char ucWd3Part=1;//窗口3的部分变量,代表选中某一行。
  259. unsigned char ucWd3Update=0; //窗口3的整屏更新显现变量 1代表更新显现,呼应函数内部会清零
  260. unsigned char ucWd3Part1Update=0; //窗口3的第1个部分更新显现变量1代表更新显现,呼应函数内部会清零
  261. unsigned char ucWd3Part2Update=0; //窗口3的第2个部分更新显现变量1代表更新显现,呼应函数内部会清零
  262. unsigned char ucWd4Part=1;//窗口4的部分变量,代表选中某一行。
  263. unsigned char ucWd4Update=0; //窗口4的整屏更新显现变量 1代表更新显现,呼应函数内部会清零
  264. unsigned char ucWd4Part1Update=0; //窗口4的第1个部分更新显现变量1代表更新显现,呼应函数内部会清零
  265. unsigned char ucWd4Part2Update=0; //窗口4的第2个部分更新显现变量1代表更新显现,呼应函数内部会清零
  266. unsigned char ucTimeH=2;//设置时刻的上限数据
  267. unsigned char ucTimeL=1;//设置时刻的下限数据
  268. unsigned char ucSpeedH=4;//设置速度的上限数据
  269. unsigned char ucSpeedL=3;//设置速度的下限数据
  270. unsigned char ucFreqH=6;//设置频率的上限数据
  271. unsigned char ucFreqL=5;//设置频率的下限数据
  272. void main()
  273. {
  274. initial_myself(); //榜首区,上电后立刻初始化
  275. delay_long(100); //一线,延时线。延时一段时刻
  276. initial_peripheral();//第二区,上电后延时一段时刻再初始化
  277. while(1) //第三区
  278. {
  279. key_service(); //按键服务的应用程序
  280. lcd_display_service(); //应用层面的液晶屏显现程序
  281. }
  282. }
  283. void initial_myself()//榜首区 上电后立刻初始化
  284. {
  285. /* 注释二:
  286. * 矩阵键盘也能够做独立按键,条件是把某一根公共输出线输出低电平,
  287. * 模仿独立按键的触发地,本程序中,把key_gnd_dr输出低电平。
  288. * 朱兆祺51学习板的S1和S5两个按键便是本程序中用到的两个独立按键。
  289. */
  290. key_gnd_dr=0; //模仿独立按键的地GND,因而有必要一向输出低电平
  291. beep_dr=1; //用PNP三极管操控蜂鸣器,输出高电平时不叫。
  292. TMOD=0x01;//设置守时器0为工作方式1
  293. TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f
  294. TL0=0x2f;
  295. }
  296. void initial_peripheral() //第二区 上电后延时一段时刻再初始化
  297. {
  298. LCDInit(); //初始化12864 内部包含液晶模块的复位
  299. EA=1; //开总中止
  300. ET0=1; //答应守时中止
  301. TR0=1; //发动守时中止
  302. }
  303. void T0_time() interrupt 1
  304. {
  305. TF0=0;//铲除中止标志
  306. TR0=0; //关中止
  307. key_scan(); //按键扫描函数
  308. if(uiVoiceCnt!=0)
  309. {
  310. uiVoiceCnt–; //每次进入守时中止都自减1,直到等于零中止。才中止鸣叫
  311. beep_dr=0;//蜂鸣器是PNP三极管操控,低电平就开端鸣叫。
  312. }
  313. else
  314. {
  315. ; //此处多加一个空指令,想保持跟if括号句子的数量对称,都是两条指令。不加也能够。
  316. beep_dr=1;//蜂鸣器是PNP三极管操控,高电平就中止鸣叫。
  317. }
  318. TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f
  319. TL0=0x2f;
  320. TR0=1;//开中止
  321. }
  322. void key_scan(void)//按键扫描函数 放在守时中止里
  323. {
  324. static unsigned intuiKeyTimeCnt1=0; //按键去颤动延时计数器
  325. static unsigned char ucKeyLock1=0; //按键触发后自锁的变量标志
  326. static unsigned intuiKeyTimeCnt2=0; //按键去颤动延时计数器
  327. static unsigned char ucKeyLock2=0; //按键触发后自锁的变量标志
  328. static unsigned intuiKeyTimeCnt3=0; //按键去颤动延时计数器
  329. static unsigned char ucKeyLock3=0; //按键触发后自锁的变量标志
  330. static unsigned intuiKeyTimeCnt4=0; //按键去颤动延时计数器
  331. static unsigned char ucKeyLock4=0; //按键触发后自锁的变量标志
  332. if(key_sr1==1)//IO是高电平,阐明按键没有被按下,这时要及时清零一些标志位
  333. {
  334. ucKeyLock1=0; //按键自锁标志清零
  335. uiKeyTimeCnt1=0;//按键去颤动延时计数器清零,此行十分奇妙,是我实战中探索出来的。
  336. }
  337. else if(ucKeyLock1==0)//有按键按下,且是榜首次被按下
  338. {
  339. uiKeyTimeCnt1++; //累加守时中止次数
  340. if(uiKeyTimeCnt1>const_key_time1)
  341. {
  342. uiKeyTimeCnt1=0;
  343. ucKeyLock1=1;//自锁按键置位,防止一向触发
  344. ucKeySec=1; //触发1号键
  345. }
  346. }
  347. if(key_sr2==1)//IO是高电平,阐明按键没有被按下,这时要及时清零一些标志位
  348. {
  349. ucKeyLock2=0; //按键自锁标志清零
  350. uiKeyTimeCnt2=0;//按键去颤动延时计数器清零,此行十分奇妙,是我实战中探索出来的。
  351. }
  352. else if(ucKeyLock2==0)//有按键按下,且是榜首次被按下
  353. {
  354. uiKeyTimeCnt2++; //累加守时中止次数
  355. if(uiKeyTimeCnt2>const_key_time2)
  356. {
  357. uiKeyTimeCnt2=0;
  358. ucKeyLock2=1;//自锁按键置位,防止一向触发
  359. ucKeySec=2; //触发2号键
  360. }
  361. }
  362. if(key_sr3==1)//IO是高电平,阐明按键没有被按下,这时要及时清零一些标志位
  363. {
  364. ucKeyLock3=0; //按键自锁标志清零
  365. uiKeyTimeCnt3=0;//按键去颤动延时计数器清零,此行十分奇妙,是我实战中探索出来的。
  366. }
  367. else if(ucKeyLock3==0)//有按键按下,且是榜首次被按下
  368. {
  369. uiKeyTimeCnt3++; //累加守时中止次数
  370. if(uiKeyTimeCnt3>const_key_time3)
  371. {
  372. uiKeyTimeCnt3=0;
  373. ucKeyLock3=1;//自锁按键置位,防止一向触发
  374. ucKeySec=3; //触发3号键
  375. }
  376. }
  377. if(key_sr4==1)//IO是高电平,阐明按键没有被按下,这时要及时清零一些标志位
  378. {
  379. ucKeyLock4=0; //按键自锁标志清零
  380. uiKeyTimeCnt4=0;//按键去颤动延时计数器清零,此行十分奇妙,是我实战中探索出来的。
  381. }
  382. else if(ucKeyLock4==0)//有按键按下,且是榜首次被按下
  383. {
  384. uiKeyTimeCnt4++; //累加守时中止次数
  385. if(uiKeyTimeCnt4>const_key_time4)
  386. {
  387. uiKeyTimeCnt4=0;
  388. ucKeyLock4=1;//自锁按键置位,防止一向触发
  389. ucKeySec=4; //触发4号键
  390. }
  391. }
  392. }
  393. void key_service(void) //按键服务的应用程序
  394. {
  395. switch(ucKeySec) //按键服务状况切换
  396. {
  397. case 1:// 加按键 对应朱兆祺学习板的S1键
  398. switch(ucWd)//在不同的窗口下,设置不同的参数
  399. {
  400. case 2://窗口2设置时刻
  401. switch(ucWd2Part)//在窗口2下,依据不同的部分变量来设置不同的参数
  402. {
  403. case 1: //设置时刻上限
  404. ucTimeH++;
  405. if(ucTimeH>99)
  406. {
  407. ucTimeH=99;
  408. }
  409. ucWd2Part1Update=1; //1代表更新显现,呼应函数内部会清零
  410. break;
  411. case 2: //设置时刻下限
  412. ucTimeL++;
  413. if(ucTimeL>99)
  414. {
  415. ucTimeL=99;
  416. }
  417. ucWd2Part2Update=1; //1代表更新显现,呼应函数内部会清零
  418. break;
  419. }
  420. break;
  421. case 3://窗口3设置速度
  422. switch(ucWd3Part)//在窗口3下,依据不同的部分变量来设置不同的参数
  423. {
  424. case 1: //设置速度上限
  425. ucSpeedH++;
  426. if(ucSpeedH>99)
  427. {
  428. ucSpeedH=99;
  429. }
  430. ucWd3Part1Update=1; //1代表更新显现,呼应函数内部会清零
  431. break;
  432. case 2: //设置速度下限
  433. ucSpeedL++;
  434. if(ucSpeedL>99)
  435. {
  436. ucSpeedL=99;
  437. }
  438. ucWd3Part2Update=1; //1代表更新显现,呼应函数内部会清零
  439. break;
  440. }
  441. break;
  442. case 4://窗口4设置速度
  443. switch(ucWd4Part)//在窗口4下,依据不同的部分变量来设置不同的参数
  444. {
  445. case 1: //设置频率上限
  446. ucFreqH++;
  447. if(ucFreqH>99)
  448. {
  449. ucFreqH=99;
  450. }
  451. ucWd4Part1Update=1; //1代表更新显现,呼应函数内部会清零
  452. break;
  453. case 2: //设置频率下限
  454. ucFreqL++;
  455. if(ucFreqL>99)
  456. {
  457. ucFreqL=99;
  458. }
  459. ucWd4Part2Update=1; //1代表更新显现,呼应函数内部会清零
  460. break;
  461. }
  462. break;
  463. }
  464. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  465. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  466. break;
  467. case 2:// 减按键 对应朱兆祺学习板的S5键
  468. switch(ucWd)//在不同的窗口下,设置不同的参数
  469. {
  470. case 2://窗口2 设置时刻
  471. switch(ucWd2Part)//在窗口2下,依据不同的部分变量来设置不同的参数
  472. {
  473. case 1: //设置时刻上限
  474. ucTimeH–;
  475. if(ucTimeH>99) //一向减到最终,单片机C言语编译器有一个特征,0减去1会溢出变成255(0xff)
  476. {
  477. ucTimeH=0;
  478. }
  479. ucWd2Part1Update=1; //1代表更新显现,呼应函数内部会清零
  480. break;
  481. case 2: //设置时刻下限
  482. ucTimeL–;
  483. if(ucTimeL>99) //一向减到最终,单片机C言语编译器有一个特征,0减去1会溢出变成255(0xff)
  484. {
  485. ucTimeL=0;
  486. }
  487. ucWd2Part2Update=1; //1代表更新显现,呼应函数内部会清零
  488. break;
  489. }
  490. break;
  491. case 3://窗口3设置速度
  492. switch(ucWd3Part)//在窗口3下,依据不同的部分变量来设置不同的参数
  493. {
  494. case 1: //设置速度上限
  495. ucSpeedH–;
  496. if(ucSpeedH>99) //一向减到最终,单片机C言语编译器有一个特征,0减去1会溢出变成255(0xff)
  497. {
  498. ucSpeedH=0;
  499. }
  500. ucWd3Part1Update=1; //1代表更新显现,呼应函数内部会清零
  501. break;
  502. case 2: //设置速度下限
  503. ucSpeedL–;
  504. if(ucSpeedL>99) //一向减到最终,单片机C言语编译器有一个特征,0减去1会溢出变成255(0xff)
  505. {
  506. ucSpeedL=0;
  507. }
  508. ucWd3Part2Update=1; //1代表更新显现,呼应函数内部会清零
  509. break;
  510. }
  511. break;
  512. case 4://窗口4设置频率
  513. switch(ucWd4Part)//在窗口4下,依据不同的部分变量来设置不同的参数
  514. {
  515. case 1: //设置频率上限
  516. ucFreqH–;
  517. if(ucFreqH>99) //一向减到最终,单片机C言语编译器有一个特征,0减去1会溢出变成255(0xff)
  518. {
  519. ucFreqH=0;
  520. }
  521. ucWd4Part1Update=1; //1代表更新显现,呼应函数内部会清零
  522. break;
  523. case 2: //设置频率下限
  524. ucFreqL–;
  525. if(ucFreqL>99) //一向减到最终,单片机C言语编译器有一个特征,0减去1会溢出变成255(0xff)
  526. {
  527. ucFreqL=0;
  528. }
  529. ucWd4Part2Update=1; //1代表更新显现,呼应函数内部会清零
  530. break;
  531. }
  532. break;
  533. }
  534. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  535. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  536. break;
  537. case 3:// 切换”光标”移动按键 对应朱兆祺学习板的S9键
  538. switch(ucWd)//在不同的窗口下,设置不同的参数
  539. {
  540. case 1: //窗口1 主菜单
  541. switch(ucWd1Part)//在窗口1下,依据不同的部分变量来设置不同的参数
  542. {
  543. case 1: //设置时刻
  544. ucWd1Part=2; //光标切换到下一行
  545. ucWd1Part1Update=1; //更新显现本来那一行,意图是更新反显光标的状况
  546. ucWd1Part2Update=1; //更新显现下一行, 意图是更新反显光标的状况
  547. break;
  548. case 2: //设置速度
  549. ucWd1Part=3; //光标切换到下一行
  550. ucWd1Part2Update=1; //更新显现本来那一行,意图是更新反显光标的状况
  551. ucWd1Part3Update=1; //更新显现下一行, 意图是更新反显光标的状况
  552. break;
  553. case 3: //设置第3行参数
  554. ucWd1Part=1; //光标回来到榜首行
  555. ucWd1Part3Update=1; //更新显现本来那一行,意图是更新反显光标的状况
  556. ucWd1Part1Update=1; //更新显现下一行, 意图是更新反显光标的状况
  557. break;
  558. }
  559. break;
  560. case 2: //窗口2 设置时刻
  561. switch(ucWd2Part)//在窗口2下,依据不同的部分变量来设置不同的参数
  562. {
  563. case 1: //时刻上限
  564. ucWd2Part=2; //光标切换到下一行
  565. ucWd2Part1Update=1; //更新显现本来那一行,意图是更新反显光标的状况
  566. ucWd2Part2Update=1; //更新显现下一行, 意图是更新反显光标的状况
  567. break;
  568. case 2: //时刻下限
  569. ucWd2Part=1; //光标回来到榜首行
  570. ucWd2Part2Update=1; //更新显现本来那一行,意图是更新反显光标的状况
  571. ucWd2Part1Update=1; //更新显现下一行, 意图是更新反显光标的状况
  572. break;
  573. }
  574. break;
  575. case 3: //窗口3 设置速度
  576. switch(ucWd3Part)//在窗口3下,依据不同的部分变量来设置不同的参数
  577. {
  578. case 1: //速度上限
  579. ucWd3Part=2; //光标切换到下一行
  580. ucWd3Part1Update=1; //更新显现本来那一行,意图是更新反显光标的状况
  581. ucWd3Part2Update=1; //更新显现下一行, 意图是更新反显光标的状况
  582. break;
  583. case 2: //速度下限
  584. ucWd3Part=1; //光标回来到榜首行
  585. ucWd3Part2Update=1; //更新显现本来那一行,意图是更新反显光标的状况
  586. ucWd3Part1Update=1; //更新显现下一行, 意图是更新反显光标的状况
  587. break;
  588. }
  589. break;
  590. case 4: //窗口4 设置频率
  591. switch(ucWd4Part)//在窗口4下,依据不同的部分变量来设置不同的参数
  592. {
  593. case 1: //频率上限
  594. ucWd4Part=2; //光标切换到下一行
  595. ucWd4Part1Update=1; //更新显现本来那一行,意图是更新反显光标的状况
  596. ucWd4Part2Update=1; //更新显现下一行, 意图是更新反显光标的状况
  597. break;
  598. case 2: //频率下限
  599. ucWd4Part=1; //光标回来到榜首行
  600. ucWd4Part2Update=1; //更新显现本来那一行,意图是更新反显光标的状况
  601. ucWd4Part1Update=1; //更新显现下一行, 意图是更新反显光标的状况
  602. break;
  603. }
  604. break;
  605. }
  606. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  607. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  608. break;
  609. case 4: // 进入和退出按键对应朱兆祺学习板的S13键,按一次进入选中的子菜单。再按一次退出子菜单。
  610. switch(ucWd)//在不同的窗口下,设置不同的参数
  611. {
  612. case 1://窗口1
  613. switch(ucWd1Part)//在窗口1下,依据不同的部分变量来设置不同的参数
  614. {
  615. case 1: //设置时刻
  616. ucWd=2; //进入设置时刻的窗口2
  617. ucWd2Update=1; //窗口2整屏更新
  618. break;
  619. case 2: //设置速度
  620. ucWd=3; //进入设置速度的窗口3
  621. ucWd3Update=1; //窗口3整屏更新
  622. break;
  623. case 3: //设置频率
  624. ucWd=4; //进入设置频率的窗口4
  625. ucWd4Update=1; //窗口4整屏更新
  626. break;
  627. }
  628. break;
  629. case 2://窗口2
  630. ucWd=1; //回来主菜单窗口1
  631. ucWd1Update=1; //窗口1整屏更新
  632. break;
  633. case 3://窗口3
  634. ucWd=1; //回来主菜单窗口1
  635. ucWd1Update=1; //窗口1整屏更新
  636. break;
  637. case 4://窗口4
  638. ucWd=1; //回来主菜单窗口1
  639. ucWd1Update=1; //窗口1整屏更新
  640. break;
  641. }
  642. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  643. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  644. break;
  645. }
  646. }
  647. unsigned char *number_to_matrix(unsigned charucBitNumber)
  648. {
  649. unsigned char *p_ucAnyNumber;//此指针依据ucBitNumber数值的巨细,别离调用不同的字库。
  650. switch(ucBitNumber)//依据ucBitNumber数值的巨细,别离调用不同的字库。
  651. {
  652. case 0:
  653. p_ucAnyNumber=Zf816_0;
  654. break;
  655. case 1:
  656. p_ucAnyNumber=Zf816_1;
  657. break;
  658. case 2:
  659. p_ucAnyNumber=Zf816_2;
  660. break;
  661. case 3:
  662. p_ucAnyNumber=Zf816_3;
  663. break;
  664. case 4:
  665. p_ucAnyNumber=Zf816_4;
  666. break;
  667. case 5:
  668. p_ucAnyNumber=Zf816_5;
  669. break;
  670. case 6:
  671. p_ucAnyNumber=Zf816_6;
  672. break;
  673. case 7:
  674. p_ucAnyNumber=Zf816_7;
  675. break;
  676. case 8:
  677. p_ucAnyNumber=Zf816_8;
  678. break;
  679. case 9:
  680. p_ucAnyNumber=Zf816_9;
  681. break;
  682. case 10:
  683. p_ucAnyNumber=Zf816_nc;
  684. break;
  685. default: //假如上面的条件都不契合,那么默许指向空字模
  686. p_ucAnyNumber=Zf816_nc;
  687. break;
  688. }
  689. return p_ucAnyNumber;//回来转化完毕后的指针
  690. }
  691. void lcd_display_service(void) //应用层面的液晶屏显现程序
  692. {
  693. switch(ucWd)//本程序的中心变量,窗口显现变量。类似于一级菜单的变量。代表显现不同的窗口。
  694. {
  695. case 1:
  696. wd1();//主菜单
  697. break;
  698. case 2:
  699. wd2();//设置时刻
  700. break;
  701. case 3:
  702. wd3();//设置速度
  703. break;
  704. case 4:
  705. wd4();//设置频率
  706. break;
  707. //本程序只需4个窗口,所以只需4个case ,假如要添加窗口,就直接添加 case 5, case 6…
  708. }
  709. }
  710. void wd1(void)//窗口1主菜单
  711. {
  712. unsigned char ucCursorFlag;//光标标志,也便是反显的标志,它是依据部分变量ucPart来定的
  713. /* 注释三:
  714. * 把每一个窗口的内容分为两种类型,一种类型是那些不必常常改写显现的内容,只需在切换窗口的时分
  715. * 才需求更新,这种内容放在整屏更新显现的括号里,比方清屏操作等内容。别的一种是那些常常需求
  716. * 改写显现的内容,这种内容放在部分更新显现的括号里。
  717. */
  718. if(ucWd1Update==1)//窗口1整屏更新,里边只放那些不必常常改写显现的内容
  719. {
  720. ucWd1Update=0;//及时清零,防止一向更新
  721. ucWd1Part1Update=1; //激活窗口1的第1个部分更新显现变量
  722. ucWd1Part2Update=1; //激活窗口1的第2个部分更新显现变量
  723. ucWd1Part3Update=1; //激活窗口1的第3个部分更新显现变量
  724. display_clear(0x00); // 清屏操作, 悉数显现空填充0x00,悉数显现点阵用0xff。
  725. clear_all_canvas();//把画布悉数清零
  726. insert_buffer_to_canvas(0,0,Zf816_mao_hao,0,1,16);//把冒号的字模刺进画布
  727. display_lattice(2,0,Hz1616_zhu,0,2,16,0); //主菜单。这些内容不必常常更新,只需在切换窗口的时分才更新显现
  728. display_lattice(3,0,Hz1616_cai,0,2,16,0);
  729. display_lattice(4,0,Hz1616_dan,0,2,16,0);
  730. }
  731. /* 注释四:
  732. * 留意!我前面讲数码管显现的时分有一句话讲错了,我那时说<部分更新应该写在整屏更新之前>,这是不对的。
  733. * 依照现在的显现程序结构<即整屏显现更新括号里包含了一切部分变量的激活>,应该是<整屏更新应该写在部分更新之前>
  734. * 这样才对。
  735. */
  736. if(ucWd1Part1Update==1) //窗口1的第1个部分更新显现变量,里边放一些常常需求改写显现的内容
  737. {
  738. ucWd1Part1Update=0; //及时清零,防止一向更新
  739. if(ucWd1Part==1) //被选中
  740. {
  741. ucCursorFlag=1; //反显 显现
  742. }
  743. else //没被选中
  744. {
  745. ucCursorFlag=0; //正常 显现
  746. }
  747. display_lattice(0,16,Hz1616_she,ucCursorFlag,2,16,0); //设置时刻规模
  748. display_lattice(1,16,Hz1616_zhi,ucCursorFlag,2,16,0);
  749. display_lattice(2,16,Hz1616_shi,ucCursorFlag,2,16,0);
  750. display_lattice(3,16,Hz1616_jian,ucCursorFlag,2,16,0);
  751. display_lattice(4,16,Hz1616_fan,ucCursorFlag,2,16,0);
  752. display_lattice(5,16,Hz1616_wei,ucCursorFlag,2,16,0);
  753. }
  754. if(ucWd1Part2Update==1) //窗口1的第2个部分更新显现变量,里边放一些常常需求改写显现的内容
  755. {
  756. ucWd1Part2Update=0; //及时清零,防止一向更新
  757. if(ucWd1Part==2) //被选中
  758. {
  759. ucCursorFlag=1; //反显 显现
  760. }
  761. else //没被选中
  762. {
  763. ucCursorFlag=0; //正常 显现
  764. }
  765. display_lattice(8,0,Hz1616_she,ucCursorFlag,2,16,0); //设置速度规模
  766. display_lattice(9,0,Hz1616_zhi,ucCursorFlag,2,16,0);
  767. display_lattice(10,0,Hz1616_su,ucCursorFlag,2,16,0);
  768. display_lattice(11,0,Hz1616_du,ucCursorFlag,2,16,0);
  769. display_lattice(12,0,Hz1616_fan,ucCursorFlag,2,16,0);
  770. display_lattice(13,0,Hz1616_wei,ucCursorFlag,2,16,0);
  771. }
  772. if(ucWd1Part3Update==1) //窗口1的第3行部分更新显现变量,里边放一些常常需求改写显现的内容
  773. {
  774. ucWd1Part3Update=0; //及时清零,防止一向更新
  775. if(ucWd1Part==3) //被选中
  776. {
  777. ucCursorFlag=1; //反显 显现
  778. }
  779. else //没被选中
  780. {
  781. ucCursorFlag=0; //正常 显现
  782. }
  783. display_lattice(8,16,Hz1616_she,ucCursorFlag,2,16,0); //设置频率规模
  784. display_lattice(9,16,Hz1616_zhi,ucCursorFlag,2,16,0);
  785. display_lattice(10,16,Hz1616_pin,ucCursorFlag,2,16,0);
  786. display_lattice(11,16,Hz1616_lv,ucCursorFlag,2,16,0);
  787. display_lattice(12,16,Hz1616_fan,ucCursorFlag,2,16,0);
  788. display_lattice(13,16,Hz1616_wei,ucCursorFlag,2,16,0);
  789. }
  790. }
  791. void wd2(void)//窗口2 设置时刻
  792. {
  793. unsigned char ucAnyNumber_1; //分化变量的个位
  794. unsigned char ucAnyNumber_10; //分化变量的十位
  795. unsigned char *p_ucAnyNumber_1; //经过数字转化成字模后,分化变量的个位字模首地址
  796. unsigned char *p_ucAnyNumber_10; //经过数字转化成字模后,分化变量的十位字模首地址
  797. unsigned char ucCursorFlag;//光标标志,也便是反显的标志,它是依据部分变量ucPart来定的
  798. if(ucWd2Update==1)//窗口2整屏更新,里边只放那些不必常常改写显现的内容
  799. {
  800. ucWd2Update=0;//及时清零,防止一向更新
  801. ucWd2Part1Update=1; //激活窗口2的第1个部分更新显现变量,这儿在前面数码管显现结构上有所改进
  802. ucWd2Part2Update=1; //激活窗口2的第2个部分更新显现变量,这儿在前面数码管显现结构上有所改进
  803. display_clear(0x00); // 清屏操作, 悉数显现空填充0x00,悉数显现点阵用0xff。
  804. clear_all_canvas();//把画布悉数清零
  805. insert_buffer_to_canvas(0,0,Zf816_mao_hao,0,1,16);//把冒号的字模刺进画布
  806. display_lattice(2,0,Hz1616_she,0,2,16,0); //设置时刻。这些内容不必常常更新,只需在切换窗口的时分才更新显现
  807. display_lattice(3,0,Hz1616_zhi,0,2,16,0);
  808. display_lattice(4,0,Hz1616_shi,0,2,16,0);
  809. display_lattice(5,0,Hz1616_jian,0,2,16,0);
  810. display_lattice(0,16,Hz1616_shi,0,2,16,0); //时刻上限
  811. display_lattice(1,16,Hz1616_jian,0,2,16,0);
  812. display_lattice(2,16,Hz1616_shang,0,2,16,0);
  813. display_lattice(3,16,Hz1616_xian,0,2,16,0);
  814. display_lattice(8,0,Hz1616_shi,0,2,16,0);//时刻下限
  815. display_lattice(9,0,Hz1616_jian,0,2,16,0);
  816. display_lattice(10,0,Hz1616_xia,0,2,16,0);
  817. display_lattice(11,0,Hz1616_xian,0,2,16,0);
  818. }
  819. if(ucWd2Part1Update==1) //窗口2的第1个部分更新显现变量,里边放一些常常需求改写显现的内容
  820. {
  821. ucWd2Part1Update=0; //及时清零,防止一向更新
  822. if(ucWd2Part==1) //被选中
  823. {
  824. ucCursorFlag=1; //反显 显现
  825. }
  826. else //没被选中
  827. {
  828. ucCursorFlag=0; //正常 显现
  829. }
  830. if(ucTimeH>=10) //有2位数以上
  831. {
  832. ucAnyNumber_10=ucTimeH/10;//十位
  833. }
  834. else //不然显现空
  835. {
  836. ucAnyNumber_10=10;//鄙人面的转化函数中,代码10表明空字模
  837. }
  838. ucAnyNumber_1=ucTimeH%10/1;//个位
  839. p_ucAnyNumber_10=number_to_matrix(ucAnyNumber_10); //把数字转化成字模首地址
  840. p_ucAnyNumber_1=number_to_matrix(ucAnyNumber_1); //把数字转化成字模首地址
  841. insert_buffer_to_canvas(2,0,p_ucAnyNumber_10,ucCursorFlag,1,16);//把十的字模刺进画布
  842. insert_buffer_to_canvas(3,0,p_ucAnyNumber_1,ucCursorFlag,1,16);//把个的字模刺进画布
  843. display_lattice(4,16,ucCanvasBuffer,0,4,16,0); //显现整屏的画布,最终的参数0是偏移量
  844. }
  845. if(ucWd2Part2Update==1) //窗口2的第2行部分更新显现变量,里边放一些常常需求改写显现的内容
  846. {
  847. ucWd2Part2Update=0; //及时清零,防止一向更新
  848. if(ucWd2Part==2) //被选中
  849. {
  850. ucCursorFlag=1; //反显 显现
  851. }
  852. else //没被选中
  853. {
  854. ucCursorFlag=0; //正常 显现
  855. }
  856. if(ucTimeL>=10) //有2位数以上
  857. {
  858. ucAnyNumber_10=ucTimeL/10;//十位
  859. }
  860. else //不然显现空
  861. {
  862. ucAnyNumber_10=10;//鄙人面的转化函数中,代码10表明空字模
  863. }
  864. ucAnyNumber_1=ucTimeL%10/1;//个位
  865. p_ucAnyNumber_10=number_to_matrix(ucAnyNumber_10); //把数字转化成字模首地址
  866. p_ucAnyNumber_1=number_to_matrix(ucAnyNumber_1); //把数字转化成字模首地址
  867. insert_buffer_to_canvas(2,0,p_ucAnyNumber_10,ucCursorFlag,1,16);//把十的字模刺进画布
  868. insert_buffer_to_canvas(3,0,p_ucAnyNumber_1,ucCursorFlag,1,16);//把个的字模刺进画布
  869. display_lattice(12,0,ucCanvasBuffer,0,4,16,0); //显现整屏的画布,最终的参数0是偏移量
  870. }
  871. }
  872. void wd3(void)//窗口3 设置速度
  873. {
  874. unsigned char ucAnyNumber_1; //分化变量的个位
  875. unsigned char ucAnyNumber_10; //分化变量的十位
  876. unsigned char *p_ucAnyNumber_1; //经过数字转化成字模后,分化变量的个位字模首地址
  877. unsigned char *p_ucAnyNumber_10; //经过数字转化成字模后,分化变量的十位字模首地址
  878. unsigned char ucCursorFlag;//光标标志,也便是反显的标志,它是依据部分变量ucPart来定的
  879. if(ucWd3Update==1)//窗口3整屏更新,里边只放那些不必常常改写显现的内容
  880. {
  881. ucWd3Update=0;//及时清零,防止一向更新
  882. ucWd3Part1Update=1; //激活窗口3的第1个部分更新显现变量,这儿在前面数码管显现结构上有所改进
  883. ucWd3Part2Update=1; //激活窗口3的第2个部分更新显现变量,这儿在前面数码管显现结构上有所改进
  884. display_clear(0x00); // 清屏操作, 悉数显现空填充0x00,悉数显现点阵用0xff。
  885. clear_all_canvas();//把画布悉数清零
  886. insert_buffer_to_canvas(0,0,Zf816_mao_hao,0,1,16);//把冒号的字模刺进画布
  887. display_lattice(2,0,Hz1616_she,0,2,16,0); //设置速度。这些内容不必常常更新,只需在切换窗口的时分才更新显现
  888. display_lattice(3,0,Hz1616_zhi,0,2,16,0);
  889. display_lattice(4,0,Hz1616_su,0,2,16,0);
  890. display_lattice(5,0,Hz1616_du,0,2,16,0);
  891. display_lattice(0,16,Hz1616_su,0,2,16,0); //速度上限
  892. display_lattice(1,16,Hz1616_du,0,2,16,0);
  893. display_lattice(2,16,Hz1616_shang,0,2,16,0);
  894. display_lattice(3,16,Hz1616_xian,0,2,16,0);
  895. display_lattice(8,0,Hz1616_su,0,2,16,0);//速度下限
  896. display_lattice(9,0,Hz1616_du,0,2,16,0);
  897. display_lattice(10,0,Hz1616_xia,0,2,16,0);
  898. display_lattice(11,0,Hz1616_xian,0,2,16,0);
  899. }
  900. if(ucWd3Part1Update==1) //窗口3的第1个部分更新显现变量,里边放一些常常需求改写显现的内容
  901. {
  902. ucWd3Part1Update=0; //及时清零,防止一向更新
  903. if(ucWd3Part==1) //被选中
  904. {
  905. ucCursorFlag=1; //反显 显现
  906. }
  907. else //没被选中
  908. {
  909. ucCursorFlag=0; //正常 显现
  910. }
  911. if(ucSpeedH>=10) //有2位数以上
  912. {
  913. ucAnyNumber_10=ucSpeedH/10;//十位
  914. }
  915. else //不然显现空
  916. {
  917. ucAnyNumber_10=10;//鄙人面的转化函数中,代码10表明空字模
  918. }
  919. ucAnyNumber_1=ucSpeedH%10/1;//个位
  920. p_ucAnyNumber_10=number_to_matrix(ucAnyNumber_10); //把数字转化成字模首地址
  921. p_ucAnyNumber_1=number_to_matrix(ucAnyNumber_1); //把数字转化成字模首地址
  922. insert_buffer_to_canvas(2,0,p_ucAnyNumber_10,ucCursorFlag,1,16);//把十的字模刺进画布
  923. insert_buffer_to_canvas(3,0,p_ucAnyNumber_1,ucCursorFlag,1,16);//把个的字模刺进画布
  924. display_lattice(4,16,ucCanvasBuffer,0,4,16,0); //显现整屏的画布,最终的参数0是偏移量
  925. }
  926. if(ucWd3Part2Update==1) //窗口3的第2行部分更新显现变量,里边放一些常常需求改写显现的内容
  927. {
  928. ucWd3Part2Update=0; //及时清零,防止一向更新
  929. if(ucWd3Part==2) //被选中
  930. {
  931. ucCursorFlag=1; //反显 显现
  932. }
  933. else //没被选中
  934. {
  935. ucCursorFlag=0; //正常 显现
  936. }
  937. if(ucSpeedL>=10) //有2位数以上
  938. {
  939. ucAnyNumber_10=ucSpeedL/10;//十位
  940. }
  941. else //不然显现空
  942. {
  943. ucAnyNumber_10=10;//鄙人面的转化函数中,代码10表明空字模
  944. }
  945. ucAnyNumber_1=ucSpeedL%10/1;//个位
  946. p_ucAnyNumber_10=number_to_matrix(ucAnyNumber_10); //把数字转化成字模首地址
  947. p_ucAnyNumber_1=number_to_matrix(ucAnyNumber_1); //把数字转化成字模首地址
  948. insert_buffer_to_canvas(2,0,p_ucAnyNumber_10,ucCursorFlag,1,16);//把十的字模刺进画布
  949. insert_buffer_to_canvas(3,0,p_ucAnyNumber_1,ucCursorFlag,1,16);//把个的字模刺进画布
  950. display_lattice(12,0,ucCanvasBuffer,0,4,16,0); //显现整屏的画布,最终的参数0是偏移量
  951. }
  952. }
  953. void wd4(void)//窗口4 设置频率
  954. {
  955. unsigned char ucAnyNumber_1; //分化变量的个位
  956. unsigned char ucAnyNumber_10; //分化变量的十位
  957. unsigned char *p_ucAnyNumber_1; //经过数字转化成字模后,分化变量的个位字模首地址
  958. unsigned char *p_ucAnyNumber_10; //经过数字转化成字模后,分化变量的十位字模首地址
  959. unsigned char ucCursorFlag;//光标标志,也便是反显的标志,它是依据部分变量ucPart来定的
  960. if(ucWd4Update==1)//窗口4整屏更新,里边只放那些不必常常改写显现的内容
  961. {
  962. ucWd4Update=0;//及时清零,防止一向更新
  963. ucWd4Part1Update=1; //激活窗口4的第1个部分更新显现变量,这儿在前面数码管显现结构上有所改进
  964. ucWd4Part2Update=1; //激活窗口4的第2个部分更新显现变量,这儿在前面数码管显现结构上有所改进
  965. display_clear(0x00); // 清屏操作, 悉数显现空填充0x00,悉数显现点阵用0xff。
  966. clear_all_canvas();//把画布悉数清零
  967. insert_buffer_to_canvas(0,0,Zf816_mao_hao,0,1,16);//把冒号的字模刺进画布
  968. display_lattice(2,0,Hz1616_she,0,2,16,0); //设置频率。这些内容不必常常更新,只需在切换窗口的时分才更新显现
  969. display_lattice(3,0,Hz1616_zhi,0,2,16,0);
  970. display_lattice(4,0,Hz1616_pin,0,2,16,0);
  971. display_lattice(5,0,Hz1616_lv,0,2,16,0);
  972. display_lattice(0,16,Hz1616_pin,0,2,16,0); //频率上限
  973. display_lattice(1,16,Hz1616_lv,0,2,16,0);
  974. display_lattice(2,16,Hz1616_shang,0,2,16,0);
  975. display_lattice(3,16,Hz1616_xian,0,2,16,0);
  976. display_lattice(8,0,Hz1616_pin,0,2,16,0);//频率下限
  977. display_lattice(9,0,Hz1616_lv,0,2,16,0);
  978. display_lattice(10,0,Hz1616_xia,0,2,16,0);
  979. display_lattice(11,0,Hz1616_xian,0,2,16,0);
  980. }
  981. if(ucWd4Part1Update==1) //窗口4的第1个部分更新显现变量,里边放一些常常需求改写显现的内容
  982. {
  983. ucWd4Part1Update=0; //及时清零,防止一向更新
  984. if(ucWd4Part==1) //被选中
  985. {
  986. ucCursorFlag=1; //反显 显现
  987. }
  988. else //没被选中
  989. {
  990. ucCursorFlag=0; //正常 显现
  991. }
  992. if(ucFreqH>=10) //有2位数以上
  993. {
  994. ucAnyNumber_10=ucFreqH/10;//十位
  995. }
  996. else //不然显现空
  997. {
  998. ucAnyNumber_10=10;//鄙人面的转化函数中,代码10表明空字模
  999. }
  1000. ucAnyNumber_1=ucFreqH%10/1;//个位
  1001. p_ucAnyNumber_10=number_to_matrix(ucAnyNumber_10); //把数字转化成字模首地址
  1002. p_ucAnyNumber_1=number_to_matrix(ucAnyNumber_1); //把数字转化成字模首地址
  1003. insert_buffer_to_canvas(2,0,p_ucAnyNumber_10,ucCursorFlag,1,16);//把十的字模刺进画布
  1004. insert_buffer_to_canvas(3,0,p_ucAnyNumber_1,ucCursorFlag,1,16);//把个的字模刺进画布
  1005. display_lattice(4,16,ucCanvasBuffer,0,4,16,0); //显现整屏的画布,最终的参数0是偏移量
  1006. }
  1007. if(ucWd4Part2Update==1) //窗口4的第2行部分更新显现变量,里边放一些常常需求改写显现的内容
  1008. {
  1009. ucWd4Part2Update=0; //及时清零,防止一向更新
  1010. if(ucWd4Part==2) //被选中
  1011. {
  1012. ucCursorFlag=1; //反显 显现
  1013. }
  1014. else //没被选中
  1015. {
  1016. ucCursorFlag=0; //正常 显现
  1017. }
  1018. if(ucFreqL>=10) //有2位数以上
  1019. {
  1020. ucAnyNumber_10=ucFreqL/10;//十位
  1021. }
  1022. else //不然显现空
  1023. {
  1024. ucAnyNumber_10=10;//鄙人面的转化函数中,代码10表明空字模
  1025. }
  1026. ucAnyNumber_1=ucFreqL%10/1;//个位
  1027. p_ucAnyNumber_10=number_to_matrix(ucAnyNumber_10); //把数字转化成字模首地址
  1028. p_ucAnyNumber_1=number_to_matrix(ucAnyNumber_1); //把数字转化成字模首地址
  1029. insert_buffer_to_canvas(2,0,p_ucAnyNumber_10,ucCursorFlag,1,16);//把十的字模刺进画布
  1030. insert_buffer_to_canvas(3,0,p_ucAnyNumber_1,ucCursorFlag,1,16);//把个的字模刺进画布
  1031. display_lattice(12,0,ucCanvasBuffer,0,4,16,0); //显现整屏的画布,最终的参数0是偏移量
  1032. }
  1033. }
  1034. void clear_all_canvas(void)//把画布悉数清零
  1035. {
  1036. unsigned int j=0;
  1037. unsigned int i=0;
  1038. for(j=0;j<16;j++)//这儿的16表明画布有16行
  1039. {
  1040. for(i=0;i<4;i++) //这儿的4表明画布每行有4个字节
  1041. {
  1042. ucCanvasBuffer[j*4+i]=0x00;
  1043. }
  1044. }
  1045. }
  1046. void display_clear(unsigned char ucFillDate) // 清屏悉数显现空填充0x00 悉数显现点阵用0xff
  1047. {
  1048. unsigned char x,y;
  1049. WriteCommand(0x34);//关显现缓冲指令
  1050. WriteCommand(0x34);//关显现缓冲指令成心写2次,怕1次关不了 这个是由于我参考到某厂家的驱动程序也是这样写的
  1051. y=0;
  1052. while(y<32)//y轴的规模0至31
  1053. {
  1054. WriteCommand(y+0x80); //笔直地址
  1055. WriteCommand(0x80); //水平地址
  1056. for(x=0;x<32;x++)//256个横向点,有32个字节
  1057. {
  1058. LCDWriteData(ucFillDate);
  1059. }
  1060. y++;
  1061. }
  1062. WriteCommand(0x36); //开显现缓冲指令
  1063. }
  1064. /* 注释五:
  1065. * 把字模刺进画布的函数.
  1066. * 这是本节的中心函数,读者尤其要搞懂x_amount和y_amount对应的显现联系。
  1067. * 第1,2个参数x,y是在画布中的坐标系统。
  1068. * x的规模是0至3,由于画布的横向只需4个字节。y的规模是0至15,由于画布的纵向只需16行。
  1069. * 第3个参数*ucArray是字模的数组。
  1070. * 第4个参数ucFbFlag是反白显现标志。0代表正常显现,1代表反白显现。
  1071. * 第5,6个参数x_amount,y_amount别离代表字模数组的横向有多少个字节,纵向有几横。
  1072. */
  1073. void insert_buffer_to_canvas(unsigned int x,unsigned int y,const unsigned char*ucArray,unsigned char ucFbFlag,unsigned int x_amount,unsigned int y_amount)
  1074. {
  1075. unsigned int j=0;
  1076. unsigned int i=0;
  1077. unsigned char ucTemp;
  1078. for(j=0;j
  1079. {
  1080. for(i=0;i
  1081. {
  1082. ucTemp=ucArray[j*x_amount+i];
  1083. if(ucFbFlag==0)
  1084. {
  1085. ucCanvasBuffer[(y+j)*4+x+i]=ucTemp; //这儿的4代表画布每一行只需4个字节
  1086. }
  1087. else
  1088. {
  1089. ucCanvasBuffer[(y+j)*4+x+i]=~ucTemp; //这儿的4代表画布每一行只需4个字节
  1090. }
  1091. }
  1092. }
  1093. }
  1094. /* 注释六:
  1095. * 显现恣意点阵函数.
  1096. * 留意,本函数在前几节的基础上多添加了第7个参数uiOffSetAddr,它是偏移地址。
  1097. * 关于这个函数,读者尤其要搞懂x_amount和y_amount对应的显现联系。
  1098. * 第1,2个参数x,y是坐标系统。x的规模是0至15,y的规模是0至31.
  1099. * 第3个参数*ucArray是字模的数组。
  1100. * 第4个参数ucFbFlag是反白显现标志。0代表正常显现,1代表反白显现。
  1101. * 第5,6个参数x_amount,y_amount别离代表字模数组的横向有多少个字节,纵向有几横。
  1102. * 第7个参数uiOffSetAddr是偏移地址,代表字模数组的从第几个数据开端显现。
  1103. */
  1104. void display_lattice(unsigned int x,unsigned int y,const unsigned char*ucArray,unsigned char ucFbFlag,unsigned int x_amount,unsigned int y_amount,unsigned int uiOffSetAddr)
  1105. {
  1106. unsigned int j=0;
  1107. unsigned int i=0;
  1108. unsigned char ucTemp;
  1109. //留意,要把以下两行指令屏蔽,不然屏幕在更新显现时会整屏闪烁
  1110. //WriteCommand(0x34);//关显现缓冲指令
  1111. //WriteCommand(0x34);//关显现缓冲指令成心写2次,怕1次关不了 这个是由于我参考到某厂家的驱动程序也是这样写的
  1112. for(j=0;j
  1113. {
  1114. WriteCommand(y+j+0x80); //笔直地址
  1115. WriteCommand(x+0x80); //水平地址
  1116. for(i=0;i
  1117. {
  1118. ucTemp=ucArray[j*x_amount+i+uiOffSetAddr]; //uiOffSetAddr是字模数组的偏移地址
  1119. if(ucFbFlag==1)//反白显现
  1120. {
  1121. ucTemp=~ucTemp;
  1122. }
  1123. LCDWriteData(ucTemp);
  1124. // delay_short(30000);//把上一节这个延时函数去掉,加速刷屏速度
  1125. }
  1126. }
  1127. WriteCommand(0x36); //开显现缓冲指令
  1128. }
  1129. void SendByteToLcd(unsigned char ucData)//发送一个字节数据到液晶模块
  1130. {
  1131. unsigned char i;
  1132. for ( i = 0; i < 8; i++ )
  1133. {
  1134. if ( (ucData << i) & 0x80 )
  1135. {
  1136. LCDSID_dr = 1;
  1137. }
  1138. else
  1139. {
  1140. LCDSID_dr = 0;
  1141. }
  1142. LCDCLK_dr = 0;
  1143. LCDCLK_dr = 1;
  1144. }
  1145. }
  1146. void SPIWrite(unsigned char ucWData, unsigned char ucWRS) //模仿SPI发送一个字节的指令或许数据给液晶模块的底层驱动
  1147. {
  1148. SendByteToLcd( 0xf8 + (ucWRS << 1) );
  1149. SendByteToLcd( ucWData & 0xf0 );
  1150. SendByteToLcd( (ucWData << 4) & 0xf0);
  1151. }
  1152. void WriteCommand(unsigned char ucCommand) //发送一个字节的指令给液晶模块
  1153. {
  1154. LCDCS_dr = 0;
  1155. LCDCS_dr = 1;
  1156. SPIWrite(ucCommand, 0);
  1157. delay_short(90);
  1158. }
  1159. void LCDWriteData(unsigned char ucData)//发送一个字节的数据给液晶模块
  1160. {
  1161. LCDCS_dr = 0;
  1162. LCDCS_dr = 1;
  1163. SPIWrite(ucData, 1);
  1164. }
  1165. void LCDInit(void) //初始化函数内部包含液晶模块的复位
  1166. {
  1167. LCDRST_dr = 1;//复位
  1168. LCDRST_dr = 0;
  1169. LCDRST_dr = 1;
  1170. }
  1171. void delay_short(unsigned int uiDelayShort) //延时函数
  1172. {
  1173. unsigned int i;
  1174. for(i=0;i
  1175. {
  1176. ;
  1177. }
  1178. }
  1179. void delay_long(unsigned int uiDelayLong)
  1180. {
  1181. unsigned int i;
  1182. unsigned int j;
  1183. for(i=0;i
  1184. {
  1185. for(j=0;j<500;j++)//内嵌循环的空指令数量
  1186. {
  1187. ; //一个分号相当于履行一条空句子
  1188. }
  1189. }
  1190. }

总结陈词:
我前面几节液晶屏程序的字模都是经过外围工具软件生成的,其实这款12864液晶模块自身便是自带字库,编程的时分只需在源代码里直接写入所需求的汉字或许字符,就能够主动调用相对应的字库了。可是仔细的网友一定会问,为什么在源代码上直接写入某个汉字就能够调用到这个汉字的字库?在这个过程中,C51编译器究竟还干了哪些不为人知的功德?欲知概况,请听下回分化—–液晶屏自带字库跟汉字机内码的联系。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/news/guandian/262021.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部