新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 第83節(jié):矩陣鍵盤輸入任意數(shù)字或小數(shù)點(diǎn)的液晶屏顯示程序

第83節(jié):矩陣鍵盤輸入任意數(shù)字或小數(shù)點(diǎn)的液晶屏顯示程序

作者: 時(shí)間:2016-11-22 來源:網(wǎng)絡(luò) 收藏
開場(chǎng)白:
本來這節(jié)打算講調(diào)用液晶屏內(nèi)部字庫時(shí)讓某行內(nèi)容反顯的,但是在昨天調(diào)試過程中,發(fā)現(xiàn)一個(gè)很奇怪的問題,當(dāng)調(diào)用內(nèi)部字庫時(shí),按照數(shù)據(jù)手冊(cè),我執(zhí)行一條反顯指令時(shí),應(yīng)該是僅僅某一行反顯,但是卻同時(shí)出現(xiàn)兩行反顯。比如,當(dāng)我執(zhí)行
WriteCommand(0x34); //擴(kuò)充指令集
WriteCommand(0x04); //第1行反顯
指令時(shí),發(fā)現(xiàn)第一行和第三行反顯,后來想想,我猜測(cè)這種12864的屏應(yīng)該是25632折成左右半屏,左半屏在上面,右半屏在下面。經(jīng)過這次經(jīng)驗(yàn),我覺得大家以后盡量不要用液晶屏的內(nèi)部字庫模式,應(yīng)該用自構(gòu)字庫的模式(圖形模式)。因?yàn)槲矣X得用內(nèi)部字庫模式的時(shí)候,這個(gè)集成的反顯擴(kuò)展指令不好用。而用自構(gòu)字庫的模式(圖形模式),卻可以順心所欲的靈活運(yùn)用,適合做菜單程序。
既然發(fā)現(xiàn)內(nèi)部字庫不好用,所以不再講內(nèi)部字庫模式,這節(jié)僅僅接著前面第79節(jié)內(nèi)容,繼續(xù)講在自構(gòu)字庫的模式(圖形模式)下,如何通過矩陣鍵盤直接輸入數(shù)字和小數(shù)點(diǎn),就像普通的計(jì)算器一樣鍵盤輸入。這個(gè)功能表面簡(jiǎn)單,其實(shí)有以下四個(gè)地方值得注意:
第一:如何用數(shù)組接收按鍵輸入的BCD碼數(shù)據(jù)。
第二:如何限制輸入?yún)?shù)的小數(shù)點(diǎn)個(gè)數(shù)和數(shù)組的有效個(gè)數(shù)。
第三:如果第0個(gè)位置是0,那么繼續(xù)輸入的數(shù)據(jù)直接覆蓋0,否則就移位再輸入。
第四:如果第0個(gè)位置是0,那么繼續(xù)輸入的小數(shù)點(diǎn)要移位輸入。
要仔細(xì)了解以上提到的關(guān)鍵點(diǎn),必須好好研究本程序中的void set_data(…)函數(shù)。同時(shí)也要溫習(xí)一下之前講的自構(gòu)字庫模式的液晶屏顯示內(nèi)容,尤其是插入畫布顯示的內(nèi)容。

具體內(nèi)容,請(qǐng)看源代碼講解。
(1) 硬件平臺(tái):
基于朱兆祺51單片機(jī)學(xué)習(xí)板。數(shù)字1鍵對(duì)應(yīng)S1鍵,數(shù)字2鍵對(duì)應(yīng)S2鍵,數(shù)字3鍵對(duì)應(yīng)S3鍵…. 數(shù)字9鍵對(duì)應(yīng)S9鍵, 數(shù)字0鍵對(duì)應(yīng)S10鍵。小數(shù)鍵對(duì)應(yīng)S11,清零鍵對(duì)應(yīng)S16,其它按鍵不用。
(2) 實(shí)現(xiàn)功能:
用矩陣鍵盤輸入任意數(shù)字或小數(shù)點(diǎn)。小數(shù)點(diǎn)不能超過2位,一旦超過2位,再按其它按鍵則輸入無效。有效數(shù)字也不能超過6位(包括小數(shù)點(diǎn)),一旦超過6位,再按其它按鍵則輸入無效。
想重新輸入,必須按S16清零按鍵才能重新輸入。

(3)源代碼講解如下:
  1. #include "REG52.H"
  2. #define const_voice_short40 //蜂鳴器短叫的持續(xù)時(shí)間
  3. #define const_key_time10 //按鍵去抖動(dòng)延時(shí)的時(shí)間
  4. sbit key_sr1=P0^0; //第一行輸入
  5. sbit key_sr2=P0^1; //第二行輸入
  6. sbit key_sr3=P0^2; //第三行輸入
  7. sbit key_sr4=P0^3; //第四行輸入
  8. sbit key_dr1=P0^4; //第一列輸出
  9. sbit key_dr2=P0^5; //第二列輸出
  10. sbit key_dr3=P0^6; //第三列輸出
  11. sbit key_dr4=P0^7; //第四列輸出
  12. sbit beep_dr=P2^7; //蜂鳴器的驅(qū)動(dòng)IO口
  13. sbitLCDCS_dr= P1^6;//片選線
  14. sbitLCDSID_dr = P1^7;//串行數(shù)據(jù)線
  15. sbitLCDCLK_dr = P3^2;//串行時(shí)鐘線
  16. sbitLCDRST_dr = P3^4;//復(fù)位線
  17. void SendByteToLcd(unsigned char ucData);//發(fā)送一個(gè)字節(jié)數(shù)據(jù)到液晶模塊
  18. void SPIWrite(unsigned char ucWData, unsigned char ucWRS); //模擬SPI發(fā)送一個(gè)字節(jié)的命令或者數(shù)據(jù)給液晶模塊的底層驅(qū)動(dòng)
  19. void WriteCommand(unsigned char ucCommand); //發(fā)送一個(gè)字節(jié)的命令給液晶模塊
  20. void LCDWriteData(unsigned char ucData); //發(fā)送一個(gè)字節(jié)的數(shù)據(jù)給液晶模塊
  21. void LCDInit(void);//初始化函數(shù)內(nèi)部包括液晶模塊的復(fù)位
  22. void display_clear(unsigned char ucFillDate); // 清屏 全部顯示空填充0x00 全部顯示點(diǎn)陣用0xff
  23. 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);//把字模插入畫布.
  24. 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); //顯示任意點(diǎn)陣函數(shù)
  25. unsigned char *number_to_matrix(unsigned charucBitNumber); //把一位數(shù)字轉(zhuǎn)換成字模首地址的函數(shù)
  26. void delay_short(unsigned int uiDelayshort); //延時(shí)
  27. void delay_long(unsigned int uiDelayLong);
  28. void key_number_input(unsigned char ucKeyNumber); //輸入數(shù)字按鍵
  29. void set_data(unsigned char ucKeyNumberTemp,unsigned char ucDotBitMax,unsigned char ucDataCntMax,unsigned char *p_ucDotCnt,unsigned char *p_ucDotBitS,unsigned char *p_ucWdPartCnt,unsigned char *p_ucSetDataBuffer);
  30. void key_delete_input(void); //刪除按鍵
  31. void T0_time(); //定時(shí)中斷函數(shù)
  32. void key_service();
  33. void key_scan(); //按鍵掃描函數(shù) 放在定時(shí)中斷里
  34. void initial_myself();
  35. void initial_peripheral();
  36. void lcd_display_service(void); //應(yīng)用層面的液晶屏顯示程序
  37. void clear_all_canvas(void);//把畫布全部清零
  38. code unsigned char Zf816_0[]=
  39. {
  40. /*--文字:0--*/
  41. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=8x16 --*/
  42. 0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00,
  43. };
  44. code unsigned char Zf816_1[]=
  45. {
  46. /*--文字:1--*/
  47. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=8x16 --*/
  48. 0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00,
  49. };
  50. code unsigned char Zf816_2[]=
  51. {
  52. /*--文字:2--*/
  53. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=8x16 --*/
  54. 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x04,0x04,0x08,0x10,0x20,0x42,0x7E,0x00,0x00,
  55. };
  56. code unsigned char Zf816_3[]=
  57. {
  58. /*--文字:3--*/
  59. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=8x16 --*/
  60. 0x00,0x00,0x00,0x3C,0x42,0x42,0x04,0x18,0x04,0x02,0x02,0x42,0x44,0x38,0x00,0x00,
  61. };
  62. code unsigned char Zf816_4[]=
  63. {
  64. /*--文字:4--*/
  65. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=8x16 --*/
  66. 0x00,0x00,0x00,0x04,0x0C,0x14,0x24,0x24,0x44,0x44,0x7E,0x04,0x04,0x1E,0x00,0x00,
  67. };
  68. code unsigned char Zf816_5[]=
  69. {
  70. /*--文字:5--*/
  71. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=8x16 --*/
  72. 0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x58,0x64,0x02,0x02,0x42,0x44,0x38,0x00,0x00,
  73. };
  74. code unsigned char Zf816_6[]=
  75. {
  76. /*--文字:6--*/
  77. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=8x16 --*/
  78. 0x00,0x00,0x00,0x1C,0x24,0x40,0x40,0x58,0x64,0x42,0x42,0x42,0x24,0x18,0x00,0x00,
  79. };
  80. code unsigned char Zf816_7[]=
  81. {
  82. /*--文字:7--*/
  83. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=8x16 --*/
  84. 0x00,0x00,0x00,0x7E,0x44,0x44,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,
  85. };
  86. code unsigned char Zf816_8[]=
  87. {
  88. /*--文字:8--*/
  89. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=8x16 --*/
  90. 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x42,0x3C,0x00,0x00,
  91. };
  92. code unsigned char Zf816_9[]=
  93. {
  94. /*--文字:9--*/
  95. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=8x16 --*/
  96. 0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x26,0x1A,0x02,0x02,0x24,0x38,0x00,0x00,
  97. };
  98. code unsigned char Zf816_nc[]=//空字模
  99. {
  100. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  101. };
  102. code unsigned char Zf816_dot[]=//小數(shù)點(diǎn)
  103. {
  104. /*--文字:.--*/
  105. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=8x16 --*/
  106. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,
  107. };
  108. code unsigned char Zf816_mao_hao[]=//冒號(hào)
  109. {
  110. /*--文字::--*/
  111. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=8x16 --*/
  112. 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,
  113. };
  114. code unsigned char Hz1616_yi[]=
  115. {
  116. /*--文字:一--*/
  117. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=16x16 --*/
  118. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x7F,0xFE,
  119. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  120. };
  121. code unsigned char Hz1616_xiang[]=
  122. {
  123. /*--文字:項(xiàng)--*/
  124. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=16x16 --*/
  125. 0x00,0x00,0x03,0xFE,0xFC,0x20,0x10,0x40,0x11,0xFC,0x11,0x04,0x11,0x24,0x11,0x24,
  126. 0x11,0x24,0x11,0x24,0x1D,0x24,0xE1,0x34,0x00,0x48,0x01,0x86,0x06,0x02,0x00,0x00,
  127. };
  128. code unsigned char Hz1616_shu[]=
  129. {
  130. /*--文字:數(shù)--*/
  131. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=16x16 --*/
  132. 0x08,0x20,0x49,0x30,0x2A,0x20,0x1C,0x20,0xFF,0x7E,0x1C,0x44,0x2B,0x44,0x48,0xC4,
  133. 0x08,0x28,0xFF,0x28,0x12,0x10,0x34,0x10,0x0C,0x28,0x32,0x4E,0xC0,0x84,0x00,0x00,
  134. };
  135. code unsigned char Hz1616_zhu[]=
  136. {
  137. /*--文字:組--*/
  138. /*--宋體12;此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=16x16 --*/
  139. 0x10,0x00,0x19,0xF8,0x11,0x08,0x25,0x08,0x25,0x08,0x79,0xF8,0x09,0x08,0x11,0x08,
  140. 0x21,0x08,0x7D,0xF8,0x01,0x08,0x01,0x08,0x0D,0x08,0x73,0xFE,0x00,0x00,0x00,0x00,
  141. };
  142. /* 注釋一:
  143. * 以下是畫布顯示數(shù)組。橫向是6個(gè)字節(jié),縱向16行,可以顯示3個(gè)16x16的漢字.
  144. *注意,這節(jié)內(nèi)容的畫布跟前面章節(jié)的畫布大小不一樣,前面章節(jié)的橫向是4個(gè)字節(jié),這節(jié)的橫向是6個(gè)字節(jié)。
  145. */
  146. unsigned char ucCanvasBuffer[]=
  147. {
  148. 0x00,0x00,0x00,0x00,0x00,0x00,//上半屏
  149. 0x00,0x00,0x00,0x00,0x00,0x00,
  150. 0x00,0x00,0x00,0x00,0x00,0x00,
  151. 0x00,0x00,0x00,0x00,0x00,0x00,
  152. 0x00,0x00,0x00,0x00,0x00,0x00,
  153. 0x00,0x00,0x00,0x00,0x00,0x00,
  154. 0x00,0x00,0x00,0x00,0x00,0x00,
  155. 0x00,0x00,0x00,0x00,0x00,0x00,
  156. //------------上半屏和下半屏的分割線-----------
  157. 0x00,0x00,0x00,0x00,0x00,0x00,//下半屏
  158. 0x00,0x00,0x00,0x00,0x00,0x00,
  159. 0x00,0x00,0x00,0x00,0x00,0x00,
  160. 0x00,0x00,0x00,0x00,0x00,0x00,
  161. 0x00,0x00,0x00,0x00,0x00,0x00,
  162. 0x00,0x00,0x00,0x00,0x00,0x00,
  163. 0x00,0x00,0x00,0x00,0x00,0x00,
  164. 0x00,0x00,0x00,0x00,0x00,0x00,
  165. };
  166. /* 注釋二:
  167. * 以下4個(gè)變量記錄一個(gè)參數(shù)的4種信息,包括小數(shù)點(diǎn)的數(shù)量,個(gè)數(shù),數(shù)據(jù)的位置,數(shù)組具體值.
  168. */
  169. unsigned char ucDotCnt_1=0;//記錄當(dāng)前輸入的小數(shù)點(diǎn)數(shù)量,如果小數(shù)點(diǎn)的數(shù)量不為0,說明當(dāng)前數(shù)組已包含小數(shù)點(diǎn),此時(shí)再按小數(shù)點(diǎn)按鍵則無效
  170. unsigned char ucDotBitS_1=0; //記錄當(dāng)前輸入的小數(shù)點(diǎn)個(gè)數(shù),如果小數(shù)點(diǎn)的個(gè)量如果超過規(guī)定2位,此時(shí)再按任何輸入按鍵則無效
  171. unsigned char ucWdPartCnt_1=0; //記錄當(dāng)前輸入的數(shù)據(jù)在數(shù)組中的位置。
  172. unsigned char ucDataBuffer_1[6]={0,10,10,10,10,10}; //一項(xiàng)的BCD碼數(shù)組緩沖
  173. unsigned char ucKeyStep=1;//按鍵掃描步驟變量
  174. unsigned char ucKeySec=0; //被觸發(fā)的按鍵編號(hào)
  175. unsigned intuiKeyTimeCnt=0; //按鍵去抖動(dòng)延時(shí)計(jì)數(shù)器
  176. unsigned char ucKeyLock=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志
  177. unsigned char ucRowRecord=1; //記錄當(dāng)前掃描到第幾列了
  178. unsigned intuiVoiceCnt=0;//蜂鳴器鳴叫的持續(xù)時(shí)間計(jì)數(shù)器
  179. unsigned char ucWd=1; //窗口變量
  180. unsigned char ucPart=1; //局部變量 0代表沒有選中任何一行,其它數(shù)值1到4代表選中某一行
  181. unsigned char ucWd1Update=1; //窗口1的整屏更新顯示變量 1代表更新顯示,響應(yīng)函數(shù)內(nèi)部會(huì)清零
  182. unsigned char ucWd1Part1Update=0; //窗口1的第1行局部更新顯示變量1代表更新顯示,響應(yīng)函數(shù)內(nèi)部會(huì)清零
  183. void main()
  184. {
  185. initial_myself(); //第一區(qū),上電后馬上初始化
  186. delay_long(100); //一線,延時(shí)線。延時(shí)一段時(shí)間
  187. initial_peripheral();//第二區(qū),上電后延時(shí)一段時(shí)間再初始化
  188. while(1) //第三區(qū)
  189. {
  190. key_service(); //按鍵服務(wù)程序
  191. lcd_display_service(); //應(yīng)用層面的液晶屏顯示程序
  192. }
  193. }
  194. void initial_myself()//第一區(qū) 上電后馬上初始化
  195. {
  196. beep_dr=1; //用PNP三極管控制蜂鳴器,輸出高電平時(shí)不叫。
  197. TMOD=0x01;//設(shè)置定時(shí)器0為工作方式1
  198. TH0=0xf8; //重裝初始值(65535-2000)=63535=0xf82f
  199. TL0=0x2f;
  200. }
  201. void initial_peripheral() //第二區(qū) 上電后延時(shí)一段時(shí)間再初始化
  202. {
  203. LCDInit(); //初始化12864 內(nèi)部包含液晶模塊的復(fù)位
  204. EA=1; //開總中斷
  205. ET0=1; //允許定時(shí)中斷
  206. TR0=1; //啟動(dòng)定時(shí)中斷
  207. }
  208. void T0_time() interrupt 1
  209. {
  210. TF0=0;//清除中斷標(biāo)志
  211. TR0=0; //關(guān)中斷
  212. key_scan();//按鍵掃描函數(shù) 放在定時(shí)中斷里
  213. if(uiVoiceCnt!=0)
  214. {
  215. uiVoiceCnt--; //每次進(jìn)入定時(shí)中斷都自減1,直到等于零為止。才停止鳴叫
  216. beep_dr=0;//蜂鳴器是PNP三極管控制,低電平就開始鳴叫。
  217. }
  218. else
  219. {
  220. ; //此處多加一個(gè)空指令,想維持跟if括號(hào)語句的數(shù)量對(duì)稱,都是兩條指令。不加也可以。
  221. beep_dr=1;//蜂鳴器是PNP三極管控制,高電平就停止鳴叫。
  222. }
  223. TH0=0xf8; //重裝初始值(65535-2000)=63535=0xf82f
  224. TL0=0x2f;
  225. TR0=1;//開中斷
  226. }
  227. void key_scan()//按鍵掃描函數(shù) 放在定時(shí)中斷里
  228. {
  229. switch(ucKeyStep)
  230. {
  231. case 1: //按鍵掃描輸出第ucRowRecord列低電平
  232. if(ucRowRecord==1)//第一列輸出低電平
  233. {
  234. key_dr1=0;
  235. key_dr2=1;
  236. key_dr3=1;
  237. key_dr4=1;
  238. }
  239. else if(ucRowRecord==2)//第二列輸出低電平
  240. {
  241. key_dr1=1;
  242. key_dr2=0;
  243. key_dr3=1;
  244. key_dr4=1;
  245. }
  246. else if(ucRowRecord==3)//第三列輸出低電平
  247. {
  248. key_dr1=1;
  249. key_dr2=1;
  250. key_dr3=0;
  251. key_dr4=1;
  252. }
  253. else //第四列輸出低電平
  254. {
  255. key_dr1=1;
  256. key_dr2=1;
  257. key_dr3=1;
  258. key_dr4=0;
  259. }
  260. uiKeyTimeCnt=0;//延時(shí)計(jì)數(shù)器清零
  261. ucKeyStep++; //切換到下一個(gè)運(yùn)行步驟
  262. break;
  263. case 2: //此處的小延時(shí)用來等待剛才列輸出信號(hào)穩(wěn)定,再判斷輸入信號(hào)。不是去抖動(dòng)延時(shí)。
  264. uiKeyTimeCnt++;
  265. if(uiKeyTimeCnt>1)
  266. {
  267. uiKeyTimeCnt=0;
  268. ucKeyStep++; //切換到下一個(gè)運(yùn)行步驟
  269. }
  270. break;
  271. case 3:
  272. if(key_sr1==1&&key_sr2==1&&key_sr3==1&&key_sr4==1)
  273. {
  274. ucKeyStep=1;//如果沒有按鍵按下,返回到第一個(gè)運(yùn)行步驟重新開始掃描
  275. ucKeyLock=0;//按鍵自鎖標(biāo)志清零
  276. uiKeyTimeCnt=0; //按鍵去抖動(dòng)延時(shí)計(jì)數(shù)器清零,此行非常巧妙
  277. ucRowRecord++;//輸出下一列
  278. if(ucRowRecord>4)
  279. {
  280. ucRowRecord=1; //依次輸出完四列之后,繼續(xù)從第一列開始輸出低電平
  281. }
  282. }
  283. else if(ucKeyLock==0)//有按鍵按下,且是第一次觸發(fā)
  284. {
  285. if(key_sr1==0&&key_sr2==1&&key_sr3==1&&key_sr4==1)
  286. {
  287. uiKeyTimeCnt++;//去抖動(dòng)延時(shí)計(jì)數(shù)器
  288. if(uiKeyTimeCnt>const_key_time)
  289. {
  290. uiKeyTimeCnt=0;
  291. ucKeyLock=1;//自鎖按鍵置位,避免一直觸發(fā),只有松開按鍵,此標(biāo)志位才會(huì)被清零
  292. if(ucRowRecord==1)//第一列輸出低電平
  293. {
  294. ucKeySec=1;//觸發(fā)1號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S1鍵
  295. }
  296. else if(ucRowRecord==2)//第二列輸出低電平
  297. {
  298. ucKeySec=2;//觸發(fā)2號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S2鍵
  299. }
  300. else if(ucRowRecord==3)//第三列輸出低電平
  301. {
  302. ucKeySec=3;//觸發(fā)3號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S3鍵
  303. }
  304. else //第四列輸出低電平
  305. {
  306. ucKeySec=4;//觸發(fā)4號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S4鍵
  307. }
  308. }
  309. }
  310. else if(key_sr1==1&&key_sr2==0&&key_sr3==1&&key_sr4==1)
  311. {
  312. uiKeyTimeCnt++;//去抖動(dòng)延時(shí)計(jì)數(shù)器
  313. if(uiKeyTimeCnt>const_key_time)
  314. {
  315. uiKeyTimeCnt=0;
  316. ucKeyLock=1;//自鎖按鍵置位,避免一直觸發(fā),只有松開按鍵,此標(biāo)志位才會(huì)被清零
  317. if(ucRowRecord==1)//第一列輸出低電平
  318. {
  319. ucKeySec=5;//觸發(fā)5號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S5鍵
  320. }
  321. else if(ucRowRecord==2)//第二列輸出低電平
  322. {
  323. ucKeySec=6;//觸發(fā)6號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S6鍵
  324. }
  325. else if(ucRowRecord==3)//第三列輸出低電平
  326. {
  327. ucKeySec=7;//觸發(fā)7號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S7鍵
  328. }
  329. else //第四列輸出低電平
  330. {
  331. ucKeySec=8;//觸發(fā)8號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S8鍵
  332. }
  333. }
  334. }
  335. else if(key_sr1==1&&key_sr2==1&&key_sr3==0&&key_sr4==1)
  336. {
  337. uiKeyTimeCnt++;//去抖動(dòng)延時(shí)計(jì)數(shù)器
  338. if(uiKeyTimeCnt>const_key_time)
  339. {
  340. uiKeyTimeCnt=0;
  341. ucKeyLock=1;//自鎖按鍵置位,避免一直觸發(fā),只有松開按鍵,此標(biāo)志位才會(huì)被清零
  342. if(ucRowRecord==1)//第一列輸出低電平
  343. {
  344. ucKeySec=9;//觸發(fā)9號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S9鍵
  345. }
  346. else if(ucRowRecord==2)//第二列輸出低電平
  347. {
  348. ucKeySec=10;//觸發(fā)10號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S10鍵
  349. }
  350. else if(ucRowRecord==3)//第三列輸出低電平
  351. {
  352. ucKeySec=11;//觸發(fā)11號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S11鍵
  353. }
  354. else //第四列輸出低電平
  355. {
  356. ucKeySec=12;//觸發(fā)12號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S12鍵
  357. }
  358. }
  359. }
  360. else if(key_sr1==1&&key_sr2==1&&key_sr3==1&&key_sr4==0)
  361. {
  362. uiKeyTimeCnt++;//去抖動(dòng)延時(shí)計(jì)數(shù)器
  363. if(uiKeyTimeCnt>const_key_time)
  364. {
  365. uiKeyTimeCnt=0;
  366. ucKeyLock=1;//自鎖按鍵置位,避免一直觸發(fā),只有松開按鍵,此標(biāo)志位才會(huì)被清零
  367. if(ucRowRecord==1)//第一列輸出低電平
  368. {
  369. ucKeySec=13;//觸發(fā)13號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S13鍵
  370. }
  371. else if(ucRowRecord==2)//第二列輸出低電平
  372. {
  373. ucKeySec=14;//觸發(fā)14號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S14鍵
  374. }
  375. else if(ucRowRecord==3)//第三列輸出低電平
  376. {
  377. ucKeySec=15;//觸發(fā)15號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S15鍵
  378. }
  379. else //第四列輸出低電平
  380. {
  381. ucKeySec=16;//觸發(fā)16號(hào)鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S16鍵
  382. }
  383. }
  384. }
  385. }
  386. break;
  387. }
  388. }
  389. void key_service() //按鍵服務(wù)的應(yīng)用程序
  390. {
  391. switch(ucKeySec) //按鍵服務(wù)狀態(tài)切換
  392. {
  393. case 1:// 數(shù)字1 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S1鍵
  394. key_number_input(1); //輸入數(shù)字按鍵
  395. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  396. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  397. break;
  398. case 2:// 數(shù)字2 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S2鍵
  399. key_number_input(2); //輸入數(shù)字按鍵
  400. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  401. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  402. break;
  403. case 3:// 數(shù)字3 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S3鍵
  404. key_number_input(3); //輸入數(shù)字按鍵
  405. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  406. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  407. break;
  408. case 4:// 數(shù)字4 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S4鍵
  409. key_number_input(4); //輸入數(shù)字按鍵
  410. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  411. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  412. break;
  413. case 5:// 數(shù)字5 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S5鍵
  414. key_number_input(5); //輸入數(shù)字按鍵
  415. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  416. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  417. break;
  418. case 6:// 數(shù)字6 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S6鍵
  419. key_number_input(6); //輸入數(shù)字按鍵
  420. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  421. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  422. break;
  423. case 7:// 數(shù)字7 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S7鍵
  424. key_number_input(7); //輸入數(shù)字按鍵
  425. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  426. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  427. break;
  428. case 8: //數(shù)字8 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S8鍵
  429. key_number_input(8); //輸入數(shù)字按鍵
  430. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  431. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  432. break;
  433. case 9:// 數(shù)字9 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S9鍵
  434. key_number_input(9); //輸入數(shù)字按鍵
  435. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  436. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  437. break;
  438. case 10:// 數(shù)字0對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S10鍵
  439. key_number_input(0); //輸入數(shù)字按鍵
  440. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  441. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  442. break;
  443. case 11:// 小數(shù)點(diǎn)按鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S11鍵
  444. key_number_input(11); //輸入數(shù)字按鍵11代表小數(shù)點(diǎn)
  445. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  446. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  447. break;
  448. case 12:// 本節(jié)暫時(shí)不用 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S12鍵
  449. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  450. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  451. break;
  452. case 13:// 本節(jié)暫時(shí)不用 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S13鍵
  453. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  454. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  455. break;
  456. case 14:// 本節(jié)暫時(shí)不用對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S14鍵
  457. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  458. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  459. break;
  460. case 15:// 本節(jié)暫時(shí)不用 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S15鍵
  461. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  462. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  463. break;
  464. case 16:// 清除按鍵 對(duì)應(yīng)朱兆祺學(xué)習(xí)板的S16鍵
  465. key_delete_input(); //刪除按鍵
  466. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  467. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)清零,避免一致觸發(fā)
  468. break;
  469. }
  470. }
  471. void key_number_input(unsigned char ucKeyNumber) //輸入數(shù)字按鍵
  472. {
  473. switch(ucWd)
  474. {
  475. case 1: //第1窗口。本節(jié)程序只有1個(gè)窗口
  476. switch(ucPart)
  477. {
  478. case 1://1窗口第1項(xiàng)
  479. set_data(ucKeyNumber,2,6,&ucDotCnt_1,&ucDotBitS_1,&ucWdPartCnt_1,ucDataBuffer_1); //設(shè)置參數(shù),請(qǐng)看本函數(shù)具體內(nèi)容。本節(jié)的核心內(nèi)容,值得好好研究!
  480. ucWd1Part1Update=1;//更新顯示
  481. break;
  482. }
  483. break;
  484. }
  485. }
  486. /* 注釋三:
  487. * 本節(jié)的核心函數(shù),值得好好研究!
  488. * 涉及到參數(shù)的4種信息,包括小數(shù)點(diǎn)的數(shù)量,個(gè)數(shù),數(shù)據(jù)的位置,數(shù)組具體值。以及它們之間的相互作用關(guān)系。
  489. * 以下參數(shù),指針類型的參數(shù)是讓代入的全局變量在退出函數(shù)后維持它當(dāng)前最新更改的數(shù)值不變。
  490. * 第1個(gè)參數(shù)ucKeyNumberTemp是當(dāng)前按鍵輸入的數(shù)值。
  491. * 第2個(gè)參數(shù)ucDotBitMax是限定被設(shè)置參數(shù)的小數(shù)點(diǎn)最大位數(shù)。
  492. * 第3個(gè)參數(shù)ucDataCntMax是限定被設(shè)置參數(shù)的最大數(shù)組個(gè)數(shù)。
  493. * 第4個(gè)參數(shù)*p_ucDotCnt是記錄當(dāng)前輸入的小數(shù)點(diǎn)數(shù)量,如果小數(shù)點(diǎn)的數(shù)量不為0,說明當(dāng)前數(shù)組已包含小數(shù)點(diǎn),此時(shí)再按小數(shù)點(diǎn)按鍵則無效。
  494. * 第5個(gè)參數(shù)*p_ucDotBitS是記錄當(dāng)前輸入的小數(shù)點(diǎn)個(gè)數(shù),如果小數(shù)點(diǎn)的個(gè)量如果超過規(guī)定2位,此時(shí)再按任何輸入按鍵則無效
  495. * 第6個(gè)參數(shù)*p_ucWdPartCnt是記錄當(dāng)前輸入的數(shù)據(jù)在數(shù)組中的位置,方便鎖定每次按鍵輸入的數(shù)字顯示位置。
  496. * 第7個(gè)參數(shù)*p_ucSetDataBuffer是BCD碼數(shù)組緩沖的具體數(shù)字內(nèi)容。
  497. */
  498. void set_data(unsigned char ucKeyNumberTemp,unsigned char ucDotBitMax,unsigned char ucDataCntMax,unsigned char *p_ucDotCnt,unsigned char *p_ucDotBitS,unsigned char *p_ucWdPartCnt,unsigned char *p_ucSetDataBuffer)
  499. {
  500. unsigned int i;
  501. if(ucKeyNumberTemp==11) //等于小數(shù)點(diǎn)
  502. {
  503. if(ucDotBitMax==0) //如果限定的小數(shù)點(diǎn)最大數(shù)是0,就意味著此數(shù)據(jù)不允許帶小數(shù)點(diǎn),必須是整數(shù)。
  504. {
  505. return; //直接返回退出
  506. }
  507. else if(*p_ucDotCnt>0)//小數(shù)點(diǎn)個(gè)數(shù)大于0,意味著當(dāng)前數(shù)組已經(jīng)包含了小數(shù)點(diǎn),此時(shí)再輸入小數(shù)點(diǎn)則無效。
  508. {
  509. return; //直接返回退出
  510. }
  511. else//否則有效,記錄當(dāng)前已經(jīng)包含一個(gè)小數(shù)點(diǎn)的信息。
  512. {
  513. *p_ucDotCnt=1;//只能包含一個(gè)小數(shù)點(diǎn)
  514. }
  515. }
  516. else if(*p_ucDotCnt==1) //如果輸入的不是小數(shù)點(diǎn),并且之前已經(jīng)輸入了一個(gè)小數(shù)點(diǎn),那么此時(shí)輸入的數(shù)字就是小數(shù)點(diǎn)后的數(shù)據(jù)
  517. {
  518. if(*p_ucDotBitS
  519. {
  520. *p_ucDotBitS=(*p_ucDotBitS)+1;
  521. }
  522. else //如果小數(shù)點(diǎn)位數(shù)已經(jīng)超過允許的范圍,則輸入的按鍵無效,直接退出。
  523. {
  524. return; //直接返回退出
  525. }
  526. }
  527. if(*p_ucWdPartCnt<(ucDataCntMax-1))//當(dāng)輸入的有效BCD碼不超過最大數(shù)組緩沖時(shí)
  528. {
  529. if(*p_ucWdPartCnt==0&&p_ucSetDataBuffer[0]==0&&ucKeyNumberTemp!=11)//如果當(dāng)前默認(rèn)位置是第0個(gè)位置,并且默認(rèn)第0個(gè)數(shù)據(jù)是0,并且當(dāng)前的按鍵輸入不是小數(shù)點(diǎn),則不用移位
  530. {
  531. ;
  532. }
  533. else//否則,移位
  534. {
  535. for(i=0;i<(ucDataCntMax-1);i++)//移位
  536. {
  537. p_ucSetDataBuffer[ucDataCntMax-1-i]=p_ucSetDataBuffer[ucDataCntMax-2-i];
  538. }
  539. *p_ucWdPartCnt=(*p_ucWdPartCnt)+1;
  540. }
  541. p_ucSetDataBuffer[0]=ucKeyNumberTemp; //當(dāng)前輸入的數(shù)字或者小數(shù)點(diǎn)永遠(yuǎn)在第右邊第0個(gè)位置。
  542. }
  543. }
  544. void key_delete_input(void) //刪除按鍵
  545. {
  546. static unsigned int i;
  547. switch(ucWd)
  548. {
  549. case 1: //第1窗口。本節(jié)程序只有1個(gè)窗口
  550. switch(ucPart)
  551. {
  552. case 1://1窗口第1項(xiàng)
  553. //清零
  554. ucDotBitS_1=0;
  555. ucDotCnt_1=0;
  556. ucWdPartCnt_1=0;
  557. for(i=0;i<6;i++)
  558. {
  559. ucDataBuffer_1[i]=10;
  560. }
  561. ucDataBuffer_1[0]=0; //第0個(gè)位置填入0
  562. ucWd1Part1Update=1;//更新顯示
  563. break;
  564. }
  565. break;
  566. }
  567. }
  568. unsigned char *number_to_matrix(unsigned charucBitNumber)
  569. {
  570. unsigned char *p_ucAnyNumber;//此指針根據(jù)ucBitNumber數(shù)值的大小,分別調(diào)用不同的字庫。
  571. switch(ucBitNumber)//根據(jù)ucBitNumber數(shù)值的大小,分別調(diào)用不同的字庫。
  572. {
  573. case 0:
  574. p_ucAnyNumber=Zf816_0;
  575. break;
  576. case 1:
  577. p_ucAnyNumber=Zf816_1;
  578. break;
  579. case 2:
  580. p_ucAnyNumber=Zf816_2;
  581. break;
  582. case 3:
  583. p_ucAnyNumber=Zf816_3;
  584. break;
  585. case 4:
  586. p_ucAnyNumber=Zf816_4;
  587. break;
  588. case 5:
  589. p_ucAnyNumber=Zf816_5;
  590. break;
  591. case 6:
  592. p_ucAnyNumber=Zf816_6;
  593. break;
  594. case 7:
  595. p_ucAnyNumber=Zf816_7;
  596. break;
  597. case 8:
  598. p_ucAnyNumber=Zf816_8;
  599. break;
  600. case 9:
  601. p_ucAnyNumber=Zf816_9;
  602. break;
  603. case 10://空格
  604. p_ucAnyNumber=Zf816_nc;
  605. break;
  606. case 11: //小數(shù)點(diǎn)
  607. p_ucAnyNumber=Zf816_dot;
  608. break;
  609. default: //如果上面的條件都不符合,那么默認(rèn)指向空字模
  610. p_ucAnyNumber=Zf816_nc;
  611. break;
  612. }
  613. return p_ucAnyNumber;//返回轉(zhuǎn)換結(jié)束后的指針
  614. }
  615. void lcd_display_service(void) //應(yīng)用層面的液晶屏顯示程序
  616. {
  617. static unsigned char *p_ucAnyNumber; //經(jīng)過數(shù)字轉(zhuǎn)換成字模后,分解變量的某位字模首地址
  618. static unsigned char ucCursorFlag;//光標(biāo)標(biāo)志,也就是反顯的標(biāo)志,它是根據(jù)局部變量ucPart來定的
  619. static unsigned int i;
  620. switch(ucWd)//本程序的核心變量,窗口顯示變量。類似于一級(jí)菜單的變量。代表顯示不同的窗口。
  621. {
  622. case 1: //顯示窗口1的數(shù)據(jù)
  623. if(ucWd1Update==1)//窗口1整屏更新,里面只放那些不用經(jīng)常刷新顯示的內(nèi)容
  624. {
  625. ucWd1Update=0;//及時(shí)清零,避免一直更新
  626. ucWd1Part1Update=1; //激活窗口1的第1行局部更新顯示變量,這里在前面數(shù)碼管顯示框架上有所改進(jìn)
  627. display_clear(0x00); // 清屏操作, 全部顯示空填充0x00,全部顯示點(diǎn)陣用0xff。
  628. clear_all_canvas();//把畫布全部清零
  629. display_lattice(0,0,Hz1616_yi,0,2,16,0); //一窗口一行,這些內(nèi)容不用經(jīng)常更新,只有在切換窗口的時(shí)候才更新顯示
  630. display_lattice(1,0,Hz1616_xiang,0,2,16,0);
  631. display_lattice(2,0,Hz1616_shu,0,2,16,0);
  632. display_lattice(3,0,Hz1616_zhu,0,2,16,0);
  633. display_lattice(4,0,Zf816_mao_hao,0,1,16,0); //冒號(hào)
  634. }
  635. if(ucWd1Part1Update==1) //窗口1的第1行局部更新顯示變量,里面放一些經(jīng)常需要刷新顯示的內(nèi)容
  636. {
  637. ucWd1Part1Update=0; //及時(shí)清零,避免一直更新
  638. if(ucPart==1) //被選中
  639. {
  640. ucCursorFlag=1; //反顯 顯示
  641. }
  642. else //沒被選中
  643. {
  644. ucCursorFlag=0; //正常 顯示
  645. }
  646. for(i=0;i<6;i++) //把每個(gè)數(shù)組緩沖的字模依次插入畫布
  647. {
  648. p_ucAnyNumber=number_to_matrix(ucDataBuffer_1[5-i]);
  649. insert_buffer_to_canvas(i,0,p_ucAnyNumber,0,1,16);//這里的i是畫布的橫向地址,一共可以顯示6個(gè)字符,因此取值范圍是0到5
  650. }
  651. display_lattice(5,0,ucCanvasBuffer,ucCursorFlag,6,16,0); //顯示整屏的畫布,最后的參數(shù)0是偏移量
  652. }
  653. break;
  654. //本程序只有1個(gè)窗口,所以只有一個(gè)case 1,如果要增加窗口,就直接增加 case 2, case 3...
  655. }
  656. }
  657. void clear_all_canvas(void)//把畫布全部清零
  658. {
  659. unsigned int j=0;
  660. unsigned int i=0;
  661. for(j=0;j<16;j++)//這里的16表示畫布有16行
  662. {
  663. for(i=0;i<4;i++) //這里的4表示畫布每行有4個(gè)字節(jié)
  664. {
  665. ucCanvasBuffer[j*4+i]=0x00;
  666. }
  667. }
  668. }
  669. void display_clear(unsigned char ucFillDate) // 清屏全部顯示空填充0x00 全部顯示點(diǎn)陣用0xff
  670. {
  671. unsigned char x,y;
  672. WriteCommand(0x34);//關(guān)顯示緩沖指令
  673. WriteCommand(0x34);//關(guān)顯示緩沖指令故意寫2次,怕1次關(guān)不了 這個(gè)是因?yàn)槲覅⒖嫉侥硰S家的驅(qū)動(dòng)程序也是這樣寫的
  674. y=0;
  675. while(y<32)//y軸的范圍0至31
  676. {
  677. WriteCommand(y+0x80); //垂直地址
  678. WriteCommand(0x80); //水平地址
  679. for(x=0;x<32;x++)//256個(gè)橫向點(diǎn),有32個(gè)字節(jié)
  680. {
  681. LCDWriteData(ucFillDate);
  682. }
  683. y++;
  684. }
  685. WriteCommand(0x36); //開顯示緩沖指令
  686. }
  687. /* 注釋四:
  688. * 注意,這節(jié)內(nèi)容的畫布跟前面章節(jié)的畫布大小不一樣,前面章節(jié)的橫向是4個(gè)字節(jié),這節(jié)的橫向是6個(gè)字節(jié)。
  689. * 把字模插入畫布的函數(shù).
  690. * 這是本節(jié)的核心函數(shù),讀者尤其要搞懂x_amount和y_amount對(duì)應(yīng)的顯示關(guān)系。
  691. * 第1,2個(gè)參數(shù)x,y是在畫布中的坐標(biāo)體系。
  692. * x的范圍是0至5,因?yàn)楫嫴嫉臋M向只要6個(gè)字節(jié)。y的范圍是0至15,因?yàn)楫嫴嫉目v向只有16行。
  693. * 第3個(gè)參數(shù)*ucArray是字模的數(shù)組。
  694. * 第4個(gè)參數(shù)ucFbFlag是反白顯示標(biāo)志。0代表正常顯示,1代表反白顯示。
  695. * 第5,6個(gè)參數(shù)x_amount,y_amount分別代表字模數(shù)組的橫向有多少個(gè)字節(jié),縱向有幾橫。
  696. */
  697. 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)
  698. {
  699. unsigned int j=0;
  700. unsigned int i=0;
  701. unsigned char ucTemp;
  702. for(j=0;j
  703. {
  704. for(i=0;i
  705. {
  706. ucTemp=ucArray[j*x_amount+i];
  707. if(ucFbFlag==0)
  708. {
  709. ucCanvasBuffer[(y+j)*6+x+i]=ucTemp; //這里的6代表畫布每一行只有6個(gè)字節(jié)。前面章節(jié)的橫向是4個(gè)字節(jié),要稍微注意的。
  710. }
  711. else
  712. {
  713. ucCanvasBuffer[(y+j)*6+x+i]=~ucTemp; //這里的6代表畫布每一行只有6個(gè)字節(jié)。前面章節(jié)的橫向是4個(gè)字節(jié),要稍微注意的。
  714. }
  715. }
  716. }
  717. }
  718. /* 注釋五:
  719. * 顯示任意點(diǎn)陣函數(shù).
  720. * 注意,本函數(shù)在前幾節(jié)的基礎(chǔ)上多增加了第7個(gè)參數(shù)uiOffSetAddr,它是偏移地址。
  721. * 對(duì)于這個(gè)函數(shù),讀者尤其要搞懂x_amount和y_amount對(duì)應(yīng)的顯示關(guān)系。
  722. * 第1,2個(gè)參數(shù)x,y是坐標(biāo)體系。x的范圍是0至15,y的范圍是0至31.
  723. * 第3個(gè)參數(shù)*ucArray是字模的數(shù)組。
  724. * 第4個(gè)參數(shù)ucFbFlag是反白顯示標(biāo)志。0代表正常顯示,1代表反白顯示。
  725. * 第5,6個(gè)參數(shù)x_amount,y_amount分別代表字模數(shù)組的橫向有多少個(gè)字節(jié),縱向有幾橫。
  726. * 第7個(gè)參數(shù)uiOffSetAddr是偏移地址,代表字模數(shù)組的從第幾個(gè)數(shù)據(jù)開始顯示。
  727. */
  728. 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)
  729. {
  730. unsigned int j=0;
  731. unsigned int i=0;
  732. unsigned char ucTemp;
  733. //注意,要把以下兩行指令屏蔽,否則屏幕在更新顯示時(shí)會(huì)整屏閃動(dòng)
  734. //WriteCommand(0x34);//關(guān)顯示緩沖指令
  735. //WriteCommand(0x34);//關(guān)顯示緩沖指令故意寫2次,怕1次關(guān)不了 這個(gè)是因?yàn)槲覅⒖嫉侥硰S家的驅(qū)動(dòng)程序也是這樣寫的
  736. for(j=0;j
  737. {
  738. WriteCommand(y+j+0x80); //垂直地址
  739. WriteCommand(x+0x80); //水平地址
  740. for(i=0;i
  741. {
  742. ucTemp=ucArray[j*x_amount+i+uiOffSetAddr]; //uiOffSetAddr是字模數(shù)組的偏移地址
  743. if(ucFbFlag==1)//反白顯示
  744. {
  745. ucTemp=~ucTemp;
  746. }
  747. LCDWriteData(ucTemp);
  748. // delay_short(30000);//把上一節(jié)這個(gè)延時(shí)函數(shù)去掉,加快刷屏速度
  749. }
  750. }
  751. WriteCommand(0x36); //開顯示緩沖指令
  752. }
  753. void SendByteToLcd(unsigned char ucData)//發(fā)送一個(gè)字節(jié)數(shù)據(jù)到液晶模塊
  754. {
  755. unsigned char i;
  756. for ( i = 0; i < 8; i++ )
  757. {
  758. if ( (ucData << i) & 0x80 )
  759. {
  760. LCDSID_dr = 1;
  761. }
  762. else
  763. {
  764. LCDSID_dr = 0;
  765. }
  766. LCDCLK_dr = 0;
  767. LCDCLK_dr = 1;
  768. }
  769. }
  770. void SPIWrite(unsigned char ucWData, unsigned char ucWRS) //模擬SPI發(fā)送一個(gè)字節(jié)的命令或者數(shù)據(jù)給液晶模塊的底層驅(qū)動(dòng)
  771. {
  772. SendByteToLcd( 0xf8 + (ucWRS << 1) );
  773. SendByteToLcd( ucWData & 0xf0 );
  774. SendByteToLcd( (ucWData << 4) & 0xf0);
  775. }
  776. void WriteCommand(unsigned char ucCommand) //發(fā)送一個(gè)字節(jié)的命令給液晶模塊
  777. {
  778. LCDCS_dr = 0;
  779. LCDCS_dr = 1;
  780. SPIWrite(ucCommand, 0);
  781. delay_short(90);
  782. }
  783. void LCDWriteData(unsigned char ucData)//發(fā)送一個(gè)字節(jié)的數(shù)據(jù)給液晶模塊
  784. {
  785. LCDCS_dr = 0;
  786. LCDCS_dr = 1;
  787. SPIWrite(ucData, 1);
  788. }
  789. void LCDInit(void) //初始化函數(shù)內(nèi)部包括液晶模塊的復(fù)位
  790. {
  791. LCDRST_dr = 1;//復(fù)位
  792. LCDRST_dr = 0;
  793. LCDRST_dr = 1;
  794. }
  795. void delay_short(unsigned int uiDelayShort) //延時(shí)函數(shù)
  796. {
  797. unsigned int i;
  798. for(i=0;i
  799. {
  800. ;
  801. }
  802. }
  803. void delay_long(unsigned int uiDelayLong)
  804. {
  805. unsigned int i;
  806. unsigned int j;
  807. for(i=0;i
  808. {
  809. for(j=0;j<500;j++)//內(nèi)嵌循環(huán)的空指令數(shù)量
  810. {
  811. ; //一個(gè)分號(hào)相當(dāng)于執(zhí)行一條空語句
  812. }
  813. }
  814. }
總結(jié)陳詞:
這節(jié)講的是鍵盤輸入數(shù)字或者小數(shù)點(diǎn)的BCD碼用來顯示,實(shí)際項(xiàng)目中,我們經(jīng)常要知道所輸入的BCD碼數(shù)組到底有效數(shù)值是多少,這個(gè)該怎么辦?欲知詳情,請(qǐng)聽下回分解----
實(shí)時(shí)同步把鍵盤輸入的BCD碼數(shù)組轉(zhuǎn)換成數(shù)值的液晶屏顯示程序。


評(píng)論


技術(shù)專區(qū)

關(guān)閉