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