相关说明:
开发板:CT117E-M4(STM32G431RB 蓝桥杯嵌入式比赛板)
开发环境: CubeMX+Keil5
第六届到第十二届省赛题中,高亮显示考察了四次,分别是第六、七、九、十届,第十一届和第十二届没有考察,今年考察几率仍然较大。
说明:
如何看这块LCD的坐标?将单片机顺时针旋转90°即可,如下图所示,右下角为原点,Y轴正方向为上,X轴正方向为左。
(有点啰嗦,不关心可以直接跳过这一部分……)
我是从代码分析的,如高亮显示的这行代码,实现的功能是在第0行显示空格字符串。
点F12进函数内部看一下,注意高亮显示的代码,继续F12。
继续F12。
到这里可以看到上图传递过来的第一个参数是Line(行),到下面就成了Xpos(X轴坐标),这就说明行改变时X坐标也改变,X坐标控制行显示。
X轴正方向是如何确定的呢,在函数调用时我们有用到Line0~Line9。
鼠标点到Line0,F12一下。可以看到从Line0到Line9,值是依次增大24的,这就说明X轴坐标正方向是向左的,且一个字符的高度为24。
还是这行代码,F12进去。
这里面有个变量refcolumn,根据上面几张图片可以知道这个变量作为参数传递,到最后会成为Ypos(Y轴坐标)。ptr是字符串指针,每次循环ptr都会自增1(指向下一个字符),所以行显示函数内部其实就是一个一个字符从左到右显示出来(LCD面向自己),并且可以确定Y坐标控制列显示。
Y轴正方向是如何确定的呢,看refcolumn值的变化,从左到右显示时,refcolumn每次自减16,所以可以得出Y轴正方向是向上的,并且每个字符宽度为16。
(下文中的纵向横向均为LCD面向自己的情况)
高亮显示的类型主要有两种:
1.横向选择高亮(数据在同一行,如时间)
2.纵向选择高亮(数据在不同行)
这两种高亮显示都是根据坐标来操作的,纵向选择高亮则改变X坐标,横向选择高亮则改变Y坐标,注意每个字符高度为24,宽度为16,从上到下X坐标递增(Line0~Line9),从左到右Y坐标递减(320 ~ 0)。
其中第六届和第九届考的是横向选择高亮。
第七届和第十届考的是纵向选择高亮。
从上面几张图可以看出,数据切换选中都是由按键控制的,所以首先会有一个按键扫描的函数检测按键按下,检测到按键按下后修改当前坐标值(纵向:更改X坐标;横向:更改Y坐标),再根据当前坐标值对选中数据高亮(选中高亮),上一数据恢复即可(恢复显示),选中高亮和恢复显示都是LCD更新操作。
其中LCD更新显示可以分为四个步骤:
假如原来的颜色配置为白底蓝字。
LCD_SetBackColor(White);//原色为白底蓝字
LCD_SetTextColor(Blue);
1.修改颜色
即修改LCD接下来显示内容的背景色和字体色,这里高亮的颜色只是进行了颜色反转,从白底蓝字变为蓝底白字。
/* 颜色高亮 */
LCD_SetBackColor(Blue);//颜色翻转(高亮)
LCD_SetTextColor(White);
2.重新显示选中数据
修改了颜色之后重新显示选中数据即可实现选中高亮。
3.恢复颜色
恢复颜色就是将LCD显示颜色更改回原本的背景色和字体色。
/* 颜色恢复 */
LCD_SetBackColor(White);//原色为白底蓝字
LCD_SetTextColor(Blue);
4.重新显示上一数据
选中数据改变后,上一数据要恢复颜色。
特殊情况:纵向选择高亮时,第一行高亮显示后,要恢复显示是最后一行;横向选择高亮时,第一个数据高亮显示后,要恢复显示是最后一个数据。
综合上述四点,再具体从代码分析一下,如纵向选中高亮代码(第七届):
const uint8_t line_step=24*2; //数据间的间隔为两行,line_now加line_step即为下一数据对应的坐标
const uint8_t line_beg=Line4; //起始行为第四行
const uint8_t line_end=Line8; //末尾行为第八行
uint8_t line_now=line_beg; //当前行对应坐标
void Line_change()//LCD更新显示
{
char str1[30];//用于存储当前行显示数据
char str2[30];//用于存储上一行显示数据
switch(line_now)//用switch判断当前是哪一行数据
{
case line_beg+0*line_step: //当前行坐标(X坐标)为第一数据坐标
sprintf(str1," Threshold 1:%dcm ",Threshold_1);//当前行
sprintf(str2," Threshold 3:%dcm ",Threshold_3);//上一行
break;
case line_beg+1*line_step: //当前行坐标为第二数据坐标
sprintf(str1," Threshold 2:%dcm ",Threshold_2);
sprintf(str2," Threshold 1:%dcm ",Threshold_1);
break;
case line_beg+2*line_step: //当前行坐标为第三数据坐标
sprintf(str1," Threshold 3:%dcm ",Threshold_3);
sprintf(str2," Threshold 2:%dcm ",Threshold_2);
break;
}
/*高亮显示*/
LCD_SetBackColor(White);//颜色反转
LCD_SetTextColor(Black);
LCD_DisplayStringLine(line_now,(unsigned char*)str1);//当前行高亮
/*恢复显示*/
LCD_SetBackColor(Black);//颜色换回来
LCD_SetTextColor(White);
if(line_now==line_beg)//第一行的上一行为最后一行
LCD_DisplayStringLine(line_end,(unsigned char*)str2);//上一行恢复
else
LCD_DisplayStringLine(line_now-line_step,(unsigned char*)str2);
}
横向选中高亮代码(第六届):
横向选中高亮要用到LCD_DisplayChar函数(只更新一行中的某几列显示),调用该函数后就会在传递进去的坐标上显示相应的字符。注意函数第一个参数为X坐标(行号),第二个参数为Y坐标,第三个参数为要显示字符的ASCII码,所以要显示数字的话就得在数字的基础上+48,即为该数字对应的ASCII码。
const uint16_t Ypos_end=8*16; //初始Y坐标 对应时间第一位数据
const uint16_t Ypos_beg=14*16; //末尾Y坐标 对应时间最后一位数据
const uint8_t Ypos_step=16; //每个字符间Y坐标差值
uint16_t Ypos_now=14*16; //当前Y坐标 初始为第一位数据
const uint8_t hour=Ypos_beg-0*Ypos_step;//小时十位对应Y坐标 数据间间隔三个单位长度 如10:20:00 数字1和数字2的Y坐标差值为16*3
const uint8_t min=Ypos_beg-3*Ypos_step; //分钟十位对应Y坐标 注意是减
const uint8_t sec=Ypos_beg-6*Ypos_step; //秒十位对应Y坐标
void Sel_change(uint16_t Ypos)//切换选择 参数为当前Y坐标
{
char dex1;//当前数据在数组中的下标 小时--0 分钟--1 秒--2
char dex2;//上一数据在数组中的下标
switch(Ypos)//用switch判断当前Y坐标值
{
case hour://当前Y坐标值为小时对应的Y坐标值
dex1=0; //当前数据下标为0 下同
dex2=2;//上一数据下标为2
break;
case min://当前Y坐标值为分钟对应的Y坐标值
dex1=1;
dex2=0;
break;
case sec://当前Y坐标值为秒对应的Y坐标值
dex1=2;
dex2=1;
break;
}
/*选中高亮*/
LCD_SetBackColor(Blue);//颜色反转
LCD_SetTextColor(White);
LCD_DisplayChar(Line6,Ypos-0*Ypos_step,T[dex1]/10+48);//这里要注意函数第一个参数为X坐标(行号),第二个参数为Y坐标,第三个参数为要显示字符的ASCII码,所以要显示数字的话就得在数字的基础上+48,即为该数字对应的ASCII码
LCD_DisplayChar(Line6,Ypos-1*Ypos_step,T[dex1]%10+48);//T[dex1]存储的是小时的数据,T[dex1]/10就是小时的十位,T[dex1]%10就是小时的个位,再将两个数字显示在相邻的列,下同。
/*恢复显示*/
LCD_SetBackColor(White);//颜色改回来
LCD_SetTextColor(Blue);
if(Ypos==Ypos_beg)//如果当前为小时 则上一个数据为秒
{
LCD_DisplayChar(Line6,Ypos-6*Ypos_step,T[dex2]/10+48);
LCD_DisplayChar(Line6,Ypos-7*Ypos_step,T[dex2]%10+48);
}
else
{
LCD_DisplayChar(Line6,Ypos+3*Ypos_step,T[dex2]/10+48);
LCD_DisplayChar(Line6,Ypos+2*Ypos_step,T[dex2]%10+48);
}
}
以上就是全部内容,如有错误请批评指正。