jianhong_wu:
第七十九節:通過主菜單移動光標來進入子菜單窗口的液晶屏程序。開場白:其實主菜單窗口與子菜單窗口本質都是多窗口菜單程序,只不過我在按鍵服務程序里面建立起來了一條主窗口與子窗口的關系鏈。這個關系鏈還是用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)源代碼講解如下:#include"REG52.H"/*注釋一:*本程序用到的變量比較多,所以在keil編譯模式里要設置一下編譯模式memorymodel,*否則編譯會出錯.右鍵單擊Target選擇“OptionsforTarget'Target1'”就會出來一個框*在memorymodel中選擇compact:variablesinpdata就可以了。*/#defineconst_voice_short40//蜂鳴器短叫的持續時間#defineconst_key_time120//按鍵去抖動延時的時間#defineconst_key_time220//按鍵去抖動延時的時間#defineconst_key_time320//按鍵去抖動延時的時間#defineconst_key_time420//按鍵去抖動延時的時間sbitkey_sr1=P0^0;//對應朱兆祺學習板的S1鍵sbitkey_sr2=P0^1;//對應朱兆祺學習板的S5鍵sbitkey_sr3=P0^2;//對應朱兆祺學習板的S9鍵sbitkey_sr4=P0^3;//對應朱兆祺學習板的S13鍵sbitkey_gnd_dr=P0^4;//模擬獨立按鍵的地GND,因此必須一直輸出低電平sbitbeep_dr=P2^7;//蜂鳴器的驅動IO口sbitLCDCS_dr=P1^6;//片選線sbitLCDSID_dr=P1^7;//串行數據線sbitLCDCLK_dr=P3^2;//串行時鐘線sbitLCDRST_dr=P3^4;//復位線voidSendByteToLcd(unsignedcharucData);//發送一個字節數據到液晶模塊voidSPIWrite(unsignedcharucWData,unsignedcharucWRS);//模擬SPI發送一個字節的命令或者數據給液晶模塊的底層驅動voidWriteCommand(unsignedcharucCommand);//發送一個字節的命令給液晶模塊voidLCDWriteData(unsignedcharucData);//發送一個字節的數據給液晶模塊voidLCDInit(void);//初始化函數內部包括液晶模塊的復位voiddisplay_clear(unsignedcharucFillDate);//清屏全部顯示空填充0x00全部顯示點陣用0xffvoidinsert_buffer_to_canvas(unsignedintx,unsignedinty,constunsignedchar*ucArray,unsignedcharucFbFlag,unsignedintx_amount,unsignedinty_amount);//把字模插入畫布.voiddisplay_lattice(unsignedintx,unsignedinty,constunsignedchar*ucArray,unsignedcharucFbFlag,unsignedintx_amount,unsignedinty_amount,unsignedintuiOffSetAddr);//顯示任意點陣函數unsignedchar*number_to_matrix(unsignedcharucBitNumber);//把一位數字轉換成字模首地址的函數voiddelay_short(unsignedintuiDelayshort);//延時voiddelay_long(unsignedintuiDelayLong);voidT0_time();//定時中斷函數voidkey_service(void);//按鍵服務的應用程序voidkey_scan(void);//按鍵掃描函數放在定時中斷里voidinitial_myself();voidinitial_peripheral();voidlcd_display_service(void);//應用層面的液晶屏顯示程序voidclear_all_canvas(void);//把畫布全部清零voidwd1(void);//窗口1主菜單voidwd2(void);//窗口2設置時間voidwd3(void);//窗口3設置速度voidwd4(void);//窗口4設置頻率codeunsignedcharZf816_0[]={/*--文字:0--*//*--宋體12;此字體下對應的點陣為:寬x高=8x16--*/0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00,};codeunsignedcharZf816_1[]={/*--文字:1--*//*--宋體12;此字體下對應的點陣為:寬x高=8x16--*/0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00,};codeunsignedcharZf816_2[]={/*--文字:2--*//*--宋體12;此字體下對應的點陣為:寬x高=8x16--*/0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x04,0x04,0x08,0x10,0x20,0x42,0x7E,0x00,0x00,};codeunsignedcharZf816_3[]={/*--文字:3--*//*--宋體12;此字體下對應的點陣為:寬x高=8x16--*/0x00,0x00,0x00,0x3C,0x42,0x42,0x04,0x18,0x04,0x02,0x02,0x42,0x44,0x38,0x00,0x00,};codeunsignedcharZf816_4[]={/*--文字:4--*//*--宋體12;此字體下對應的點陣為:寬x高=8x16--*/0x00,0x00,0x00,0x04,0x0C,0x14,0x24,0x24,0x44,0x44,0x7E,0x04,0x04,0x1E,0x00,0x00,};codeunsignedcharZf816_5[]={/*--文字:5--*//*--宋體12;此字體下對應的點陣為:寬x高=8x16--*/0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x58,0x64,0x02,0x02,0x42,0x44,0x38,0x00,0x00,};codeunsignedcharZf816_6[]={/*--文字:6--*//*--宋體12;此字體下對應的點陣為:寬x高=8x16--*/0x00,0x00,0x00,0x1C,0x24,0x40,0x40,0x58,0x64,0x42,0x42,0x42,0x24,0x18,0x00,0x00,};codeunsignedcharZf816_7[]={/*--文字:7--*//*--宋體12;此字體下對應的點陣為:寬x高=8x16--*/0x00,0x00,0x00,0x7E,0x44,0x44,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,};codeunsignedcharZf816_8[]={/*--文字:8--*//*--宋體12;此字體下對應的點陣為:寬x高=8x16--*/0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x42,0x3C,0x00,0x00,};codeunsignedcharZf816_9[]={/*--文字:9--*//*--宋體12;此字體下對應的點陣為:寬x高=8x16--*/0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x26,0x1A,0x02,0x02,0x24,0x38,0x00,0x00,};codeunsignedcharZf816_nc[]=//空字模{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};codeunsignedcharZf816_mao_hao[]=//冒號{/*--文字::--*//*--宋體12;此字體下對應的點陣為:寬x高=8x16--*/0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,};codeunsignedcharHz1616_zhu[]={/*--文字:主--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x02,0x00,0x01,0x80,0x01,0x00,0x00,0x08,0x3F,0xFC,0x01,0x00,0x01,0x00,0x01,0x08,0x3F,0xFC,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x04,0x7F,0xFE,0x00,0x00,0x00,0x00,};codeunsignedcharHz1616_cai[]={/*--文字:菜--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x04,0x40,0xFF,0xFE,0x04,0x40,0x04,0x40,0x3F,0xF8,0x22,0x08,0x11,0x10,0x08,0x20,0x01,0x00,0x7F,0xFE,0x03,0x80,0x05,0x40,0x09,0x30,0x11,0x1C,0x61,0x08,0x01,0x00,};codeunsignedcharHz1616_dan[]={/*--文字:單--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x08,0x20,0x06,0x30,0x04,0x40,0x3F,0xF8,0x21,0x08,0x3F,0xF8,0x21,0x08,0x21,0x08,0x3F,0xF8,0x21,0x08,0x01,0x00,0xFF,0xFE,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,};codeunsignedcharHz1616_she[]={/*--文字:設--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x40,0x00,0x21,0xF0,0x31,0x10,0x21,0x10,0x01,0x10,0x01,0x10,0xE2,0x0E,0x25,0xF8,0x21,0x08,0x21,0x08,0x20,0x90,0x20,0x90,0x28,0x60,0x30,0x90,0x23,0x0E,0x0C,0x04,};codeunsignedcharHz1616_zhi[]={/*--文字:置--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x3F,0xF8,0x24,0x48,0x24,0x48,0x3F,0xF8,0x01,0x00,0x7F,0xFC,0x02,0x00,0x1F,0xF0,0x10,0x10,0x1F,0xF0,0x10,0x10,0x1F,0xF0,0x10,0x10,0x1F,0xF0,0x10,0x10,0xFF,0xFE,};codeunsignedcharHz1616_su[]={/*--文字:速--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x00,0x80,0x40,0x80,0x2F,0xFC,0x20,0x80,0x00,0x80,0x07,0xF8,0xE4,0x88,0x24,0x88,0x27,0xF8,0x21,0xA0,0x22,0x98,0x2C,0x88,0x20,0x80,0x50,0x80,0x8F,0xFE,0x00,0x00,};codeunsignedcharHz1616_du[]={/*--文字:度--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x01,0x00,0x00,0x80,0x3F,0xFE,0x22,0x20,0x22,0x20,0x2F,0xFC,0x22,0x20,0x23,0xE0,0x20,0x00,0x27,0xF8,0x22,0x10,0x21,0x20,0x20,0xC0,0x41,0x30,0x46,0x0E,0x98,0x04,};codeunsignedcharHz1616_shi[]={/*--文字:時--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x00,0x10,0x00,0x10,0x7C,0x10,0x44,0x10,0x47,0xFE,0x44,0x10,0x7C,0x10,0x45,0x10,0x44,0x90,0x44,0x90,0x7C,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x50,0x00,0x20,};codeunsignedcharHz1616_jian[]={/*--文字:間--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x20,0x00,0x13,0xFC,0x10,0x04,0x40,0x04,0x47,0xE4,0x44,0x24,0x44,0x24,0x47,0xE4,0x44,0x24,0x44,0x24,0x47,0xE4,0x40,0x04,0x40,0x04,0x40,0x04,0x40,0x14,0x40,0x08,};codeunsignedcharHz1616_pin[]={/*--文字:頻--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x08,0x00,0x08,0xFE,0x4E,0x20,0x48,0x40,0x48,0xFC,0xFE,0x84,0x00,0xA4,0x08,0xA4,0x4A,0xA4,0x4A,0xA4,0x84,0xA4,0x08,0x50,0x10,0x48,0x20,0x86,0xC3,0x02,0x00,0x00,};codeunsignedcharHz1616_lv[]={/*--文字:率--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x02,0x00,0x01,0x00,0x7F,0xFE,0x41,0x00,0x22,0x28,0x17,0xD0,0x04,0x80,0x11,0x10,0x22,0x48,0x47,0xC4,0x01,0x20,0xFF,0xFE,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,};codeunsignedcharHz1616_fan[]={/*--文字:范--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x04,0x20,0x04,0x20,0xFF,0xFE,0x04,0x60,0x40,0x00,0x31,0xF8,0x91,0x08,0x61,0x08,0x49,0x08,0x09,0x38,0x11,0x10,0xE1,0x00,0x21,0x04,0x21,0x04,0x20,0xFC,0x20,0x00,};codeunsignedcharHz1616_wei[]={/*--文字:圍--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x7F,0xFC,0x42,0x04,0x42,0x04,0x5F,0xF4,0x42,0x04,0x4F,0xE4,0x42,0x04,0x5F,0xE4,0x42,0x24,0x42,0x24,0x42,0x24,0x42,0xA4,0x42,0x44,0x40,0x04,0x7F,0xFC,0x40,0x04,};codeunsignedcharHz1616_shang[]={/*--文字:上--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0xF8,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x04,0x7F,0xFE,0x00,0x00,};codeunsignedcharHz1616_xia[]={/*--文字:下--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x00,0x04,0x7F,0xFE,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0xC0,0x01,0x60,0x01,0x30,0x01,0x20,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,};codeunsignedcharHz1616_xian[]={/*--文字:限--*//*--宋體12;此字體下對應的點陣為:寬x高=16x16--*/0x00,0x00,0xFB,0xF8,0x92,0x08,0x93,0xF8,0xA2,0x08,0xA2,0x08,0x93,0xF8,0x8A,0x80,0x8A,0x48,0xAA,0x50,0x92,0x20,0x82,0x20,0x82,0x10,0x82,0x8E,0x83,0x04,0x82,0x00,};unsignedcharucCanvasBuffer[]=//畫布顯示數組。注意,這里沒有code關鍵字,是全局變量。初始化全部填充0x00{0x00,0x00,0x00,0x00,//上半屏0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//------------上半屏和下半屏的分割線-----------0x00,0x00,0x00,0x00,//下半屏0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};unsignedcharucKeySec=0;//被觸發的按鍵編號unsignedintuiVoiceCnt=0;//蜂鳴器鳴叫的持續時間計數器unsignedcharucWd=1;//窗口變量unsignedcharucWd1Part=1;//窗口1的局部變量,代表選中某一行。unsignedcharucWd1Update=1;//窗口1的整屏更新顯示變量1代表更新顯示,響應函數內部會清零unsignedcharucWd1Part1Update=0;//窗口1的第1個局部更新顯示變量1代表更新顯示,響應函數內部會清零unsignedcharucWd1Part2Update=0;//窗口1的第2個局部更新顯示變量1代表更新顯示,響應函數內部會清零unsignedcharucWd1Part3Update=0;//窗口1的第3個局部更新顯示變量1代表更新顯示,響應函數內部會清零unsignedcharucWd2Part=1;//窗口2的局部變量,代表選中某一行。unsignedcharucWd2Update=0;//窗口2的整屏更新顯示變量1代表更新顯示,響應函數內部會清零unsignedcharucWd2Part1Update=0;//窗口2的第1個局部更新顯示變量1代表更新顯示,響應函數內部會清零unsignedcharucWd2Part2Update=0;//窗口2的第2個局部更新顯示變量1代表更新顯示,響應函數內部會清零unsignedcharucWd3Part=1;//窗口3的局部變量,代表選中某一行。unsignedcharucWd3Update=0;//窗口3的整屏更新顯示變量1代表更新顯示,響應函數內部會清零unsignedcharucWd3Part1Update=0;//窗口3的第1個局部更新顯示變量1代表更新顯示,響應函數內部會清零unsignedcharucWd3Part2Update=0;//窗口3的第2個局部更新顯示變量1代表更新顯示,響應函數內部會清零unsignedcharucWd4Part=1;//窗口4的局部變量,代表選中某一行。unsignedcharucWd4Update=0;//窗口4的整屏更新顯示變量1代表更新顯示,響應函數內部會清零unsignedcharucWd4Part1Update=0;//窗口4的第1個局部更新顯示變量1代表更新顯示,響應函數內部會清零unsignedcharucWd4Part2Update=0;//窗口4的第2個局部更新顯示變量1代表更新顯示,響應函數內部會清零unsignedcharucTimeH=2;//設置時間的上限數據unsignedcharucTimeL=1;//設置時間的下限數據unsignedcharucSpeedH=4;//設置速度的上限數據unsignedcharucSpeedL=3;//設置速度的下限數據unsignedcharucFreqH=6;//設置頻率的上限數據unsignedcharucFreqL=5;//設置頻率的下限數據voidmain(){initial_myself();//第一區,上電后馬上初始化delay_long(100);//一線,延時線。延時一段時間initial_peripheral();//第二區,上電后延時一段時間再初始化while(1)//第三區{key_service();//按鍵服務的應用程序lcd_display_service();//應用層面的液晶屏顯示程序}}voidinitial_myself()//第一區上電后馬上初始化{/*注釋二:*矩陣鍵盤也可以做獨立按鍵,前提是把某一根公共輸出線輸出低電平,*模擬獨立按鍵的觸發地,本程序中,把key_gnd_dr輸出低電平。*朱兆祺51學習板的S1和S5兩個按鍵就是本程序中用到的兩個獨立按鍵。*/key_gnd_dr=0;//模擬獨立按鍵的地GND,因此必須一直輸出低電平beep_dr=1;//用PNP三極管控制蜂鳴器,輸出高電平時不叫。TMOD=0x01;//設置定時器0為工作方式1TH0=0xf8;//重裝初始值(65535-2000)=63535=0xf82fTL0=0x2f;}voidinitial_peripheral()//第二區上電后延時一段時間再初始化{LCDInit();//初始化12864內部包含液晶模塊的復位EA=1;//開總中斷ET0=1;//允許定時中斷TR0=1;//啟動定時中斷}voidT0_time()interrupt1{TF0=0;//清除中斷標志TR0=0;//關中斷key_scan();//按鍵掃描函數if(uiVoiceCnt!=0){uiVoiceCnt--;//每次進入定時中斷都自減1,直到等于零為止。才停止鳴叫beep_dr=0;//蜂鳴器是PNP三極管控制,低電平就開始鳴叫。}else{;//此處多加一個空指令,想維持跟if括號語句的數量對稱,都是兩條指令。不加也可以。beep_dr=1;//蜂鳴器是PNP三極管控制,高電平就停止鳴叫。}TH0=0xf8;//重裝初始值(65535-2000)=63535=0xf82fTL0=0x2f;TR0=1;//開中斷}voidkey_scan(void)//按鍵掃描函數放在定時中斷里{staticunsignedintuiKeyTimeCnt1=0;//按鍵去抖動延時計數器staticunsignedcharucKeyLock1=0;//按鍵觸發后自鎖的變量標志staticunsignedintuiKeyTimeCnt2=0;//按鍵去抖動延時計數器staticunsignedcharucKeyLock2=0;//按鍵觸發后自鎖的變量標志staticunsignedintuiKeyTimeCnt3=0;//按鍵去抖動延時計數器staticunsignedcharucKeyLock3=0;//按鍵觸發后自鎖的變量標志staticunsignedintuiKeyTimeCnt4=0;//按鍵去抖動延時計數器staticunsignedcharucKeyLock4=0;//按鍵觸發后自鎖的變量標志if(key_sr1==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標志位{ucKeyLock1=0;//按鍵自鎖標志清零uiKeyTimeCnt1=0;//按鍵去抖動延時計數器清零,此行非常巧妙,是我實戰中摸索出來的。}elseif(ucKeyLock1==0)//有按鍵按下,且是第一次被按下{uiKeyTimeCnt1++;//累加定時中斷次數if(uiKeyTimeCnt1>const_key_time1){uiKeyTimeCnt1=0;ucKeyLock1=1;//自鎖按鍵置位,避免一直觸發ucKeySec=1;//觸發1號鍵}}if(key_sr2==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標志位{ucKeyLock2=0;//按鍵自鎖標志清零uiKeyTimeCnt2=0;//按鍵去抖動延時計數器清零,此行非常巧妙,是我實戰中摸索出來的。}elseif(ucKeyLock2==0)//有按鍵按下,且是第一次被按下{uiKeyTimeCnt2++;//累加定時中斷次數if(uiKeyTimeCnt2>const_key_time2){uiKeyTimeCnt2=0;ucKeyLock2=1;//自鎖按鍵置位,避免一直觸發ucKeySec=2;//觸發2號鍵}}if(key_sr3==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標志位{ucKeyLock3=0;//按鍵自鎖標志清零uiKeyTimeCnt3=0;//按鍵去抖動延時計數器清零,此行非常巧妙,是我實戰中摸索出來的。}elseif(ucKeyLock3==0)//有按鍵按下,且是第一次被按下{uiKeyTimeCnt3++;//累加定時中斷次數if(uiKeyTimeCnt3>const_key_time3){uiKeyTimeCnt3=0;ucKeyLock3=1;//自鎖按鍵置位,避免一直觸發ucKeySec=3;//觸發3號鍵}}if(key_sr4==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標志位{ucKeyLock4=0;//按鍵自鎖標志清零uiKeyTimeCnt4=0;//按鍵去抖動延時計數器清零,此行非常巧妙,是我實戰中摸索出來的。}elseif(ucKeyLock4==0)//有按鍵按下,且是第一次被按下{uiKeyTimeCnt4++;//累加定時中斷次數if(uiKeyTimeCnt4>const_key_time4){uiKeyTimeCnt4=0;ucKeyLock4=1;//自鎖按鍵置位,避免一直觸發ucKeySec=4;//觸發4號鍵}}}voidkey_service(void)//按鍵服務的應用程序{switch(ucKeySec)//按鍵服務狀態切換{case1://加按鍵對應朱兆祺學習板的S1鍵switch(ucWd)//在不同的窗口下,設置不同的參數{case2://窗口2設置時間switch(ucWd2Part)//在窗口2下,根據不同的局部變量來設置不同的參數{case1://設置時間上限ucTimeH++;if(ucTimeH>99){ucTimeH=99;}ucWd2Part1Update=1;//1代表更新顯示,響應函數內部會清零break;case2://設置時間下限ucTimeL++;if(ucTimeL>99){ucTimeL=99;}ucWd2Part2Update=1;//1代表更新顯示,響應函數內部會清零break;}break;case3://窗口3設置速度switch(ucWd3Part)//在窗口3下,根據不同的局部變量來設置不同的參數{case1://設置速度上限ucSpeedH++;if(ucSpeedH>99){ucSpeedH=99;}ucWd3Part1Update=1;//1代表更新顯示,響應函數內部會清零break;case2://設置速度下限ucSpeedL++;if(ucSpeedL>99){ucSpeedL=99;}ucWd3Part2Update=1;//1代表更新顯示,響應函數內部會清零break;}break;case4://窗口4設置速度switch(ucWd4Part)//在窗口4下,根據不同的局部變量來設置不同的參數{case1://設置頻率上限ucFreqH++;if(ucFreqH>99){ucFreqH=99;}ucWd4Part1Update=1;//1代表更新顯示,響應函數內部會清零break;case2://設置頻率下限ucFreqL++;if(ucFreqL>99){ucFreqL=99;}ucWd4Part2Update=1;//1代表更新顯示,響應函數內部會清零break;}break;}uiVoiceCnt=const_voice_short;//按鍵聲音觸發,滴一聲就停。ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發break;case2://減按鍵對應朱兆祺學習板的S5鍵switch(ucWd)//在不同的窗口下,設置不同的參數{case2://窗口2設置時間switch(ucWd2Part)//在窗口2下,根據不同的局部變量來設置不同的參數{case1://設置時間上限ucTimeH--;if(ucTimeH>99)//一直減到最后,單片機C語言編譯器有一個特征,0減去1會溢出變成255(0xff){ucTimeH=0;}ucWd2Part1Update=1;//1代表更新顯示,響應函數內部會清零break;case2://設置時間下限ucTimeL--;if(ucTimeL>99)//一直減到最后,單片機C語言編譯器有一個特征,0減去1會溢出變成255(0xff){ucTimeL=0;}ucWd2Part2Update=1;//1代表更新顯示,響應函數內部會清零break;}break;case3://窗口3設置速度switch(ucWd3Part)//在窗口3下,根據不同的局部變量來設置不同的參數{case1://設置速度上限ucSpeedH--;if(ucSpeedH>99)//一直減到最后,單片機C語言編譯器有一個特征,0減去1會溢出變成255(0xff){ucSpeedH=0;}ucWd3Part1Update=1;//1代表更新顯示,響應函數內部會清零break;case2://設置速度下限ucSpeedL--;if(ucSpeedL>99)//一直減到最后,單片機C語言編譯器有一個特征,0減去1會溢出變成255(0xff){ucSpeedL=0;}ucWd3Part2Update=1;//1代表更新顯示,響應函數內部會清零break;}break;case4://窗口4設置頻率switch(ucWd4Part)//在窗口4下,根據不同的局部變量來設置不同的參數{case1://設置頻率上限ucFreqH--;if(ucFreqH>99)//一直減到最后,單片機C語言編譯器有一個特征,0減去1會溢出變成255(0xff){ucFreqH=0;}ucWd4Part1Update=1;//1代表更新顯示,響應函數內部會清零break;case2://設置頻率下限ucFreqL--;if(ucFreqL>99)//一直減到最后,單片機C語言編譯器有一個特征,0減去1會溢出變成255(0xff){ucFreqL=0;}ucWd4Part2Update=1;//1代表更新顯示,響應函數內部會清零break;}break;}uiVoiceCnt=const_voice_short;//按鍵聲音觸發,滴一聲就停。ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發break;case3://切換"光標"移動按鍵對應朱兆祺學習板的S9鍵switch(ucWd)//在不同的窗口下,設置不同的參數{case1://窗口1主菜單switch(ucWd1Part)//在窗口1下,根據不同的局部變量來設置不同的參數{case1://設置時間ucWd1Part=2;//光標切換到下一行ucWd1Part1Update=1;//更新顯示原來那一行,目的是更新反顯光標的狀態ucWd1Part2Update=1;//更新顯示下一行,目的是更新反顯光標的狀態break;case2://設置速度ucWd1Part=3;//光標切換到下一行ucWd1Part2Update=1;//更新顯示原來那一行,目的是更新反顯光標的狀態ucWd1Part3Update=1;//更新顯示下一行,目的是更新反顯光標的狀態break;case3://設置第3行參數ucWd1Part=1;//光標返回到第一行ucWd1Part3Update=1;//更新顯示原來那一行,目的是更新反顯光標的狀態ucWd1Part1Update=1;//更新顯示下一行,目的是更新反顯光標的狀態break;}break;case2://窗口2設置時間switch(ucWd2Part)//在窗口2下,根據不同的局部變量來設置不同的參數{case1://時間上限ucWd2Part=2;//光標切換到下一行ucWd2Part1Update=1;//更新顯示原來那一行,目的是更新反顯光標的狀態ucWd2Part2Update=1;//更新顯示下一行,目的是更新反顯光標的狀態break;case2://時間下限ucWd2Part=1;//光標返回到第一行ucWd2Part2Update=1;//更新顯示原來那一行,目的是更新反顯光標的狀態ucWd2Part1Update=1;//更新顯示下一行,目的是更新反顯光標的狀態break;}break;case3://窗口3設置速度switch(ucWd3Part)//在窗口3下,根據不同的局部變量來設置不同的參數{case1://速度上限ucWd3Part=2;//光標切換到下一行ucWd3Part1Update=1;//更新顯示原來那一行,目的是更新反顯光標的狀態ucWd3Part2Update=1;//更新顯示下一行,目的是更新反顯光標的狀態break;case2://速度下限ucWd3Part=1;//光標返回到第一行ucWd3Part2Update=1;//更新顯示原來那一行,目的是更新反顯光標的狀態ucWd3Part1Update=1;//更新顯示下一行,目的是更新反顯光標的狀態break;}break;case4://窗口4設置頻率switch(ucWd4Part)//在窗口4下,根據不同的局部變量來設置不同的參數{case1://頻率上限ucWd4Part=2;//光標切換到下一行ucWd4Part1Update=1;//更新顯示原來那一行,目的是更新反顯光標的狀態ucWd4Part2Update=1;//更新顯示下一行,目的是更新反顯光標的狀態break;case2://頻率下限ucWd4Part=1;//光標返回到第一行ucWd4Part2Update=1;//更新顯示原來那一行,目的是更新反顯光標的狀態ucWd4Part1Update=1;//更新顯示下一行,目的是更新反顯光標的狀態break;}break;}uiVoiceCnt=const_voice_short;//按鍵聲音觸發,滴一聲就停。ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發break;case4://進入和退出按鍵對應朱兆祺學習板的S13鍵,按一次進入選中的子菜單。再按一次退出子菜單。switch(ucWd)//在不同的窗口下,設置不同的參數{case1://窗口1switch(ucWd1Part)//在窗口1下,根據不同的局部變量來設置不同的參數{case1://設置時間ucWd=2;//進入設置時間的窗口2ucWd2Update=1;//窗口2整屏更新break;case2://設置速度ucWd=3;//進入設置速度的窗口3ucWd3Update=1;//窗口3整屏更新break;case3://設置頻率ucWd=4;//進入設置頻率的窗口4ucWd4Update=1;//窗口4整屏更新break;}break;case2://窗口2ucWd=1;//返回主菜單窗口1ucWd1Update=1;//窗口1整屏更新break;case3://窗口3ucWd=1;//返回主菜單窗口1ucWd1Update=1;//窗口1整屏更新break;case4://窗口4ucWd=1;//返回主菜單窗口1ucWd1Update=1;//窗口1整屏更新break;}uiVoiceCnt=const_voice_short;//按鍵聲音觸發,滴一聲就停。ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發break;}}unsignedchar*number_to_matrix(unsignedcharucBitNumber){unsignedchar*p_ucAnyNumber;//此指針根據ucBitNumber數值的大小,分別調用不同的字庫。switch(ucBitNumber)//根據ucBitNumber數值的大小,分別調用不同的字庫。{case0:p_ucAnyNumber=Zf816_0;break;case1:p_ucAnyNumber=Zf816_1;break;case2:p_ucAnyNumber=Zf816_2;break;case3:p_ucAnyNumber=Zf816_3;break;case4:p_ucAnyNumber=Zf816_4;break;case5:p_ucAnyNumber=Zf816_5;break;case6:p_ucAnyNumber=Zf816_6;break;case7:p_ucAnyNumber=Zf816_7;break;case8:p_ucAnyNumber=Zf816_8;break;case9:p_ucAnyNumber=Zf816_9;break;case10:p_ucAnyNumber=Zf816_nc;break;default://如果上面的條件都不符合,那么默認指向空字模p_ucAnyNumber=Zf816_nc;break;}returnp_ucAnyNumber;//返回轉換結束后的指針}voidlcd_display_service(void)//應用層面的液晶屏顯示程序{switch(ucWd)//本程序的核心變量,窗口顯示變量。類似于一級菜單的變量。代表顯示不同的窗口。{case1:wd1();//主菜單break;case2:wd2();//設置時間break;case3:wd3();//設置速度break;case4:wd4();//設置頻率break;//本程序只有4個窗口,所以只有4個case,如果要增加窗口,就直接增加case5,case6...}}voidwd1(void)//窗口1主菜單{unsignedcharucCursorFlag;//光標標志,也就是反顯的標志,它是根據局部變量ucPart來定的/*注釋三:*把每一個窗口的內容分為兩種類型,一種類型是那些不用經常刷新顯示的內容,只有在切換窗口的時候*才需要更新,這種內容放在整屏更新顯示的括號里,比如清屏操作等內容。另外一種是那些經常需要*刷新顯示的內容,這種內容放在局部更新顯示的括號里。*/if(ucWd1Update==1)//窗口1整屏更新,里面只放那些不用經常刷新顯示的內容{ucWd1Update=0;//及時清零,避免一直更新ucWd1Part1Update=1;//激活窗口1的第1個局部更新顯示變量ucWd1Part2Update=1;//激活窗口1的第2個局部更新顯示變量ucWd1Part3Update=1;//激活窗口1的第3個局部更新顯示變量display_clear(0x00);//清屏操作,全部顯示空填充0x00,全部顯示點陣用0xff。clear_all_canvas();//把畫布全部清零insert_buffer_to_canvas(0,0,Zf816_mao_hao,0,1,16);//把冒號的字模插入畫布display_lattice(2,0,Hz1616_zhu,0,2,16,0);//主菜單。這些內容不用經常更新,只有在切換窗口的時候才更新顯示display_lattice(3,0,Hz1616_cai,0,2,16,0);display_lattice(4,0,Hz1616_dan,0,2,16,0);}/*注釋四:*注意!我前面講數碼管顯示的時候有一句話講錯了,我那時說,這是不對的。*按照現在的顯示程序框架,應該是*這樣才對。*/if(ucWd1Part1Update==1)//窗口1的第1個局部更新顯示變量,里面放一些經常需要刷新顯示的內容{ucWd1Part1Update=0;//及時清零,避免一直更新if(ucWd1Part==1)//被選中{ucCursorFlag=1;//反顯顯示}else//沒被選中{ucCursorFlag=0;//正常顯示}display_lattice(0,16,Hz1616_she,ucCursorFlag,2,16,0);//設置時間范圍display_lattice(1,16,Hz1616_zhi,ucCursorFlag,2,16,0);display_lattice(2,16,Hz1616_shi,ucCursorFlag,2,16,0);display_lattice(3,16,Hz1616_jian,ucCursorFlag,2,16,0);display_lattice(4,16,Hz1616_fan,ucCursorFlag,2,16,0);display_lattice(5,16,Hz1616_wei,ucCursorFlag,2,16,0);}if(ucWd1Part2Update==1)//窗口1的第2個局部更新顯示變量,里面放一些經常需要刷新顯示的內容{ucWd1Part2Update=0;//及時清零,避免一直更新if(ucWd1Part==2)//被選中{ucCursorFlag=1;//反顯顯示}else//沒被選中{ucCursorFlag=0;//正常顯示}display_lattice(8,0,Hz1616_she,ucCursorFlag,2,16,0);//設置速度范圍display_lattice(9,0,Hz1616_zhi,ucCursorFlag,2,16,0);display_lattice(10,0,Hz1616_su,ucCursorFlag,2,16,0);display_lattice(11,0,Hz1616_du,ucCursorFlag,2,16,0);display_lattice(12,0,Hz1616_fan,ucCursorFlag,2,16,0);display_lattice(13,0,Hz1616_wei,ucCursorFlag,2,16,0);}if(ucWd1Part3Update==1)//窗口1的第3行局部更新顯示變量,里面放一些經常需要刷新顯示的內容{ucWd1Part3Update=0;//及時清零,避免一直更新if(ucWd1Part==3)//被選中{ucCursorFlag=1;//反顯顯示}else//沒被選中{ucCursorFlag=0;//正常顯示}display_lattice(8,16,Hz1616_she,ucCursorFlag,2,16,0);//設置頻率范圍display_lattice(9,16,Hz1616_zhi,ucCursorFlag,2,16,0);display_lattice(10,16,Hz1616_pin,ucCursorFlag,2,16,0);display_lattice(11,16,Hz1616_lv,ucCursorFlag,2,16,0);display_lattice(12,16,Hz1616_fan,ucCursorFlag,2,16,0);display_lattice(13,16,Hz1616_wei,ucCursorFlag,2,16,0);}}voidwd2(void)//窗口2設置時間{unsignedcharucAnyNumber_1;//分解變量的個位unsignedcharucAnyNumber_10;//分解變量的十位unsignedchar*p_ucAnyNumber_1;//經過數字轉換成字模后,分解變量的個位字模首地址unsignedchar*p_ucAnyNumber_10;//經過數字轉換成字模后,分解變量的十位字模首地址unsignedcharucCursorFlag;//光標標志,也就是反顯的標志,它是根據局部變量ucPart來定的if(ucWd2Update==1)//窗口2整屏更新,里面只放那些不用經常刷新顯示的內容{ucWd2Update=0;//及時清零,避免一直更新ucWd2Part1Update=1;//激活窗口2的第1個局部更新顯示變量,這里在前面數碼管顯示框架上有所改進ucWd2Part2Update=1;//激活窗口2的第2個局部更新顯示變量,這里在前面數碼管顯示框架上有所改進display_clear(0x00);//清屏操作,全部顯示空填充0x00,全部顯示點陣用0xff。clear_all_canvas();//把畫布全部清零insert_buffer_to_canvas(0,0,Zf816_mao_hao,0,1,16);//把冒號的字模插入畫布display_lattice(2,0,Hz1616_she,0,2,16,0);//設置時間。這些內容不用經常更新,只有在切換窗口的時候才更新顯示display_lattice(3,0,Hz1616_zhi,0,2,16,0);display_lattice(4,0,Hz1616_shi,0,2,16,0);display_lattice(5,0,Hz1616_jian,0,2,16,0);display_lattice(0,16,Hz1616_shi,0,2,16,0);//時間上限display_lattice(1,16,Hz1616_jian,0,2,16,0);display_lattice(2,16,Hz1616_shang,0,2,16,0);display_lattice(3,16,Hz1616_xian,0,2,16,0);display_lattice(8,0,Hz1616_shi,0,2,16,0);//時間下限display_lattice(9,0,Hz1616_jian,0,2,16,0);display_lattice(10,0,Hz1616_xia,0,2,16,0);display_lattice(11,0,Hz1616_xian,0,2,16,0);}if(ucWd2Part1Update==1)//窗口2的第1個局部更新顯示變量,里面放一些經常需要刷新顯示的內容{ucWd2Part1Update=0;//及時清零,避免一直更新if(ucWd2Part==1)//被選中{ucCursorFlag=1;//反顯顯示}else//沒被選中{ucCursorFlag=0;//正常顯示}if(ucTimeH>=10)//有2位數以上{ucAnyNumber_10=ucTimeH/10;//十位}else//否則顯示空{ucAnyNumber_10=10;//在下面的轉換函數中,代碼10表示空字模}ucAnyNumber_1=ucTimeH%10/1;//個位p_ucAnyNumber_10=number_to_matrix(ucAnyNumber_10);//把數字轉換成字模首地址p_ucAnyNumber_1=number_to_matrix(ucAnyNumber_1);//把數字轉換成字模首地址insert_buffer_to_canvas(2,0,p_ucAnyNumber_10,ucCursorFlag,1,16);//把十的字模插入畫布insert_buffer_to_canvas(3,0,p_ucAnyNumber_1,ucCursorFlag,1,16);//把個的字模插入畫布display_lattice(4,16,ucCanvasBuffer,0,4,16,0);//顯示整屏的畫布,最后的參數0是偏移量}if(ucWd2Part2Update==1)//窗口2的第2行局部更新顯示變量,里面放一些經常需要刷新顯示的內容{ucWd2Part2Update=0;//及時清零,避免一直更新if(ucWd2Part==2)//被選中{ucCursorFlag=1;//反顯顯示}else//沒被選中{ucCursorFlag=0;//正常顯示}if(ucTimeL>=10)//有2位數以上{ucAnyNumber_10=ucTimeL/10;//十位}else//否則顯示空{ucAnyNumber_10=10;//在下面的轉換函數中,代碼10表示空字模}ucAnyNumber_1=ucTimeL%10/1;//個位p_ucAnyNumber_10=number_to_matrix(ucAnyNumber_10);//把數字轉換成字模首地址p_ucAnyNumber_1=number_to_matrix(ucAnyNumber_1);//把數字轉換成字模首地址insert_buffer_to_canvas(2,0,p_ucAnyNumber_10,ucCursorFlag,1,16);//把十的字模插入畫布insert_buffer_to_canvas(3,0,p_ucAnyNumber_1,ucCursorFlag,1,16);//把個的字模插入畫布display_lattice(12,0,ucCanvasBuffer,0,4,16,0);//顯示整屏的畫布,最后的參數0是偏移量}}voidwd3(void)//窗口3設置速度{unsignedcharucAnyNumber_1;//分解變量的個位unsignedcharucAnyNumber_10;//分解變量的十位unsignedchar*p_ucAnyNumber_1;//經過數字轉換成字模后,分解變量的個位字模首地址unsignedchar*p_ucAnyNumber_10;//經過數字轉換成字模后,分解變量的十位字模首地址unsignedcharucCursorFlag;//光標標志,也就是反顯的標志,它是根據局部變量ucPart來定的if(ucWd3Update==1)//窗口3整屏更新,里面只放那些不用經常刷新顯示的內容{ucWd3Update=0;//及時清零,避免一直更新ucWd3Part1Update=1;//激活窗口3的第1個局部更新顯示變量,這里在前面數碼管顯示框架上有所改進ucWd3Part2Update=1;//激活窗口3的第2個局部更新顯示變量,這里在前面數碼管顯示框架上有所改進display_clear(0x00);//清屏操作,全部顯示空填充0x00,全部顯示點陣用0xff。clear_all_canvas();//把畫布全部清零insert_buffer_to_canvas(0,0,Zf816_mao_hao,0,1,16);//把冒號的字模插入畫布display_lattice(2,0,Hz1616_she,0,2,16,0);//設置速度。這些內容不用經常更新,只有在切換窗口的時候才更新顯示display_lattice(3,0,Hz1616_zhi,0,2,16,0);display_lattice(4,0,Hz1616_su,0,2,16,0);display_lattice(5,0,Hz1616_du,0,2,16,0);display_lattice(0,16,Hz1616_su,0,2,16,0);//速度上限display_lattice(1,16,Hz1616_du,0,2,16,0);display_lattice(2,16,Hz1616_shang,0,2,16,0);display_lattice(3,16,Hz1616_xian,0,2,16,0);display_lattice(8,0,Hz1616_su,0,2,16,0);//速度下限display_lattice(9,0,Hz1616_du,0,2,16,0);display_lattice(10,0,Hz1616_xia,0,2,16,0);display_lattice(11,0,Hz1616_xian,0,2,16,0);}if(ucWd3Part1Update==1)//窗口3的第1個局部更新顯示變量,里面放一些經常需要刷新顯示的內容{ucWd3Part1Update=0;//及時清零,避免一直更新if(ucWd3Part==1)//被選中{ucCursorFlag=1;//反顯顯示}else//沒被選中{ucCursorFlag=0;//正常顯示}if(ucSpeedH>=10)//有2位數以上{ucAnyNumber_10=ucSpeedH/10;//十位}else//否則顯示空{ucAnyNumber_10=10;//在下面的轉換函數中,代碼10表示空字模}ucAnyNumber_1=ucSpeedH%10/1;//個位p_ucAnyNumber_10=number_to_matrix(ucAnyNumber_10);//把數字轉換成字模首地址p_ucAnyNumber_1=number_to_matrix(ucAnyNumber_1);//把數字轉換成字模首地址insert_buffer_to_canvas(2,0,p_ucAnyNumber_10,ucCursorFlag,1,16);//把十的字模插入畫布insert_buffer_to_canvas(3,0,p_ucAnyNumber_1,ucCursorFlag,1,16);//把個的字模插入畫布display_lattice(4,16,ucCanvasBuffer,0,4,16,0);//顯示整屏的畫布,最后的參數0是偏移量}if(ucWd3Part2Update==1)//窗口3的第2行局部更新顯示變量,里面放一些經常需要刷新顯示的內容{ucWd3Part2Update=0;//及時清零,避免一直更新if(ucWd3Part==2)//被選中{ucCursorFlag=1;//反顯顯示}else//沒被選中{ucCursorFlag=0;//正常顯示}if(ucSpeedL>=10)//有2位數以上{ucAnyNumber_10=ucSpeedL/10;//十位}else//否則顯示空{ucAnyNumber_10=10;//在下面的轉換函數中,代碼10表示空字模}ucAnyNumber_1=ucSpeedL%10/1;//個位p_ucAnyNumber_10=number_to_matrix(ucAnyNumber_10);//把數字轉換成字模首地址p_ucAnyNumber_1=number_to_matrix(ucAnyNumber_1);//把數字轉換成字模首地址insert_buffer_to_canvas(2,0,p_ucAnyNumber_10,ucCursorFlag,1,16);//把十的字模插入畫布insert_buffer_to_canvas(3,0,p_ucAnyNumber_1,ucCursorFlag,1,16);//把個的字模插入畫布display_lattice(12,0,ucCanvasBuffer,0,4,16,0);//顯示整屏的畫布,最后的參數0是偏移量}}voidwd4(void)//窗口4設置頻率{unsignedcharucAnyNumber_1;//分解變量的個位unsignedcharucAnyNumber_10;//分解變量的十位unsignedchar*p_ucAnyNumber_1;//經過數字轉換成字模后,分解變量的個位字模首地址unsignedchar*p_ucAnyNumber_10;//經過數字轉換成字模后,分解變量的十位字模首地址unsignedcharucCursorFlag;//光標標志,也就是反顯的標志,它是根據局部變量ucPart來定的if(ucWd4Update==1)//窗口4整屏更新,里面只放那些不用經常刷新顯示的內容{ucWd4Update=0;//及時清零,避免一直更新ucWd4Part1Update=1;//激活窗口4的第1個局部更新顯示變量,這里在前面數碼管顯示框架上有所改進ucWd4Part2Update=1;//激活窗口4的第2個局部更新顯示變量,這里在前面數碼管顯示框架上有所改進display_clear(0x00);//清屏操作,全部顯示空填充0x00,全部顯示點陣用0xff。clear_all_canvas();//把畫布全部清零insert_buffer_to_canvas(0,0,Zf816_mao_hao,0,1,16);//把冒號的字模插入畫布display_lattice(2,0,Hz1616_she,0,2,16,0);//設置頻率。這些內容不用經常更新,只有在切換窗口的時候才更新顯示display_lattice(3,0,Hz1616_zhi,0,2,16,0);display_lattice(4,0,Hz1616_pin,0,2,16,0);display_lattice(5,0,Hz1616_lv,0,2,16,0);display_lattice(0,16,Hz1616_pin,0,2,16,0);//頻率上限display_lattice(1,16,Hz1616_lv,0,2,16,0);display_lattice(2,16,Hz1616_shang,0,2,16,0);display_lattice(3,16,Hz1616_xian,0,2,16,0);display_lattice(8,0,Hz1616_pin,0,2,16,0);//頻率下限display_lattice(9,0,Hz1616_lv,0,2,16,0);display_lattice(10,0,Hz1616_xia,0,2,16,0);display_lattice(11,0,Hz1616_xian,0,2,16,0);}if(ucWd4Part1Update==1)//窗口4的第1個局部更新顯示變量,里面放一些經常需要刷新顯示的內容{ucWd4Part1Update=0;//及時清零,避免一直更新if(ucWd4Part==1)//被選中{ucCursorFlag=1;//反顯顯示}else//沒被選中{ucCursorFlag=0;//正常顯示}if(ucFreqH>=10)//有2位數以上{ucAnyNumber_10=ucFreqH/10;//十位}else//否則顯示空{ucAnyNumber_10=10;//在下面的轉換函數中,代碼10表示空字模}ucAnyNumber_1=ucFreqH%10/1;//個位p_ucAnyNumber_10=number_to_matrix(ucAnyNumber_10);//把數字轉換成字模首地址p_ucAnyNumber_1=number_to_matrix(ucAnyNumber_1);//把數字轉換成字模首地址insert_buffer_to_canvas(2,0,p_ucAnyNumber_10,ucCursorFlag,1,16);//把十的字模插入畫布insert_buffer_to_canvas(3,0,p_ucAnyNumber_1,ucCursorFlag,1,16);//把個的字模插入畫布display_lattice(4,16,ucCanvasBuffer,0,4,16,0);//顯示整屏的畫布,最后的參數0是偏移量}if(ucWd4Part2Update==1)//窗口4的第2行局部更新顯示變量,里面放一些經常需要刷新顯示的內容{ucWd4Part2Update=0;//及時清零,避免一直更新if(ucWd4Part==2)//被選中{ucCursorFlag=1;//反顯顯示}else//沒被選中{ucCursorFlag=0;//正常顯示}if(ucFreqL>=10)//有2位數以上{ucAnyNumber_10=ucFreqL/10;//十位}else//否則顯示空{ucAnyNumber_10=10;//在下面的轉換函數中,代碼10表示空字模}ucAnyNumber_1=ucFreqL%10/1;//個位p_ucAnyNumber_10=number_to_matrix(ucAnyNumber_10);//把數字轉換成字模首地址p_ucAnyNumber_1=number_to_matrix(ucAnyNumber_1);//把數字轉換成字模首地址insert_buffer_to_canvas(2,0,p_ucAnyNumber_10,ucCursorFlag,1,16);//把十的字模插入畫布insert_buffer_to_canvas(3,0,p_ucAnyNumber_1,ucCursorFlag,1,16);//把個的字模插入畫布display_lattice(12,0,ucCanvasBuffer,0,4,16,0);//顯示整屏的畫布,最后的參數0是偏移量}}voidclear_all_canvas(void)//把畫布全部清零{unsignedintj=0;unsignedinti=0;for(j=0;j