1. 前言

最近在准备16届的蓝桥杯嵌入式赛道的国赛,打算出一个系列的博客,记录STM32G431RBT6这块比赛用板上所有模块可能涉及到的所有考点,如果有错误或者遗漏欢迎各位大佬斧正。

本系列博客会分为以下两大类:

1.1. 单独模块的讲解

在这部分,我会分享自己总结的各个模块的相关配置、代码书写模板,涉及到的大致框架如下:

这个框架后续可能会不断更新,欢迎各位给出建议。

这一大类相关的文章链接如下(持续补充中):

【蓝桥杯嵌入式】【模块】一、系统初始化-CSDN博客

【蓝桥杯嵌入式】【模块】二、LED相关配置及代码模板-CSDN博客

【蓝桥杯嵌入式】【模块】三、LCD相关配置及代码模板-CSDN博客

【蓝桥杯嵌入式】【模块】四、按键相关配置及代码模板-CSDN博客

【蓝桥杯嵌入式】【模块】五、ADC相关配置及代码模板-CSDN博客

【蓝桥杯嵌入式】【模块】六、PWM相关配置及代码模板-CSDN博客

【蓝桥杯嵌入式】【模块】七、IIC相关配置及代码模板-CSDN博客

【蓝桥杯嵌入式】【模块】八、UART相关配置及代码模板-CSDN博客

1.2. 蓝桥杯各届的真题、模拟题复盘及个人答案

在这一部分,我会分享个人练过的所有题的复盘思路及代码。

这一大类相关的文章链接如下(持续补充中):

【蓝桥杯嵌入式】【复盘】第13届国赛真题-CSDN博客

【蓝桥杯嵌入式】【复盘】第14届国赛真题-CSDN博客

【蓝桥杯嵌入式】【复盘】第15届省赛真题-CSDN博客

【蓝桥杯嵌入式】【复盘】第15届国赛真题-CSDN博客


以下是本篇博客正文内容:

2. 在cubemx中配置lcd

实际上,cubemx中并不需要配置什么;因为使用cubemx的本质是为了配置与模块相关的gpio引脚,而在使用lcd时,我们会移植官方的lcd库文件,这个库文件里已经包含lcd相关引脚的初始化了,与这里同理,后续iic通信实际也是不用配置cubemx的。

所以,这个地方只讲库文件的移植,核心是移植资源数据包,LCD_HAL文件夹里的三个文件。

2.1. lcd相关库文件的移植

三个文件分别在Inc和Src文件夹里:

Inc里需要移植的是下图所示两个文件:

Src里需要移植的是图示两个文件中的lcd.c。之所以把main.c也圈起来,是因为main.c中包含lcd的使用模板,后续可以参考:

将上面说的三个文件复制后,粘贴进工程中之前新建的bsp文件夹

(如果对bsp文件夹没印象需要看之前的博客【蓝桥杯嵌入式】【模块】一、系统初始化-CSDN博客):

粘贴好后,还需要在keil里中添加对应的组,将文件放进去:

至此,lcd相关文件的移植结束。

3. lcd的初始化与显示

3.1. lcd的初始化

lcd初始化的代码如下:

    LCD_Init();
	HAL_Delay(100);

    LCD_SetBackColor(Black);
    LCD_SetTextColor(White);
	LCD_Clear(Black);

这一部分代码实际是直接从官方库的main.c文件里复制出来的。其作用就是初始化lcd相关的引脚,将显示设置为黑底白字。

3.2. lcd的显示

lcd显示的核心函数是:

LCD_DisplayStringLine(Line4, (unsigned char *)"    Hello,world.   ");

该函数有两个参数,第一个参数决定该行文字显示在lcd屏的第几行,第二个参数决定显示的字符串内容。

需要注意的是,lcd屏的行数从1开始计,但是库函数里的line却是从0开始计的,所以,如果待显示内容在lcd屏上是第一行,在写代码时则需要用line0。例如,如果要显示下图中第二行的"GOODS":

应该用的代码是:

LCD_DisplayStringLine(Line1, (unsigned char *)"       GOODS        ");

注意,空格一定要严格控制个数,图上面左右两边有几个空格,代码中也需要敲几个空格。

但是要显示上面图中的"R37:1.25V",其中的1.25实际是个变量值,又应该怎么做呢?这时,就需要用sprintf函数,代码示例如下:

    char lcd_text[20];
    float R37 = 1.25;
    sprintf(lcd_text, "     R37:%.2f      ", R37);
    LCD_DisplayStringLine(Line3, (unsigned char *)lcd_text);

定义一个char类型的数组,使用sprintf向里面填充内容,便可以实现像R37这样的变量的lcd显示。


4. 解决lcd与led的冲突问题

之前的博客(【蓝桥杯嵌入式】【模块】二、LED相关配置及代码模板-CSDN博客)中提到过,lcd与led会共用PC8-PC15引脚,所以可能会造成二者的引脚冲突,比如会发现lcd的显示会造成led乱亮,对于这种情况,做好以下几步措施应该可以解决:

第一点,在整体初始化时,要将led的初始化函数放在lcd的后面。

第二点,对lcd的库函数做部分修改,具体如下所示:

在lcd.c文件中,对图示三个函数添加上两句代码,其作用是保存之前的引脚赋值,即在lcd做显示时,先将之前的led状态存下来,显示完之后再还原。

经过以上两个调整,led和lcd冲突的问题基本得到解决。


5. lcd屏反转

参考:蓝桥杯嵌入式LCD翻转显示_lcd初始化代码翻转设置-CSDN博客

在第13届国赛的题目中,出现了这样一个需求:

要实现lcd的反转实际非常简单,在lcd.c文件里,有这样一个函数:

void REG_932X_Init(void)
{
    LCD_WriteReg(R227, 0x3008);   // Set internal timing
    LCD_WriteReg(R231, 0x0012); // Set internal timing
    LCD_WriteReg(R239, 0x1231);   // Set internal timing
    LCD_WriteReg(R1, 0x0000);   // set SS and SM bit		  //0x0100
    LCD_WriteReg(R2, 0x0700);   // set 1 line inversion
    LCD_WriteReg(R3, 0x1030);     // set GRAM write direction and BGR=1.
    LCD_WriteReg(R4, 0x0000);     // Resize register
    LCD_WriteReg(R8, 0x0207);     // set the back porch and front porch
    LCD_WriteReg(R9, 0x0000);     // set non-display area refresh cycle ISC[3:0]
    LCD_WriteReg(R10, 0x0000);    // FMARK function
    LCD_WriteReg(R12, 0x0000);  // RGB interface setting
    LCD_WriteReg(R13, 0x0000);    // Frame marker Position
    LCD_WriteReg(R15, 0x0000);  // RGB interface polarity
    /**************Power On sequence ****************/
    LCD_WriteReg(R16, 0x0000);    // SAP, BT[3:0], AP, DSTB, SLP, STB
    LCD_WriteReg(R17, 0x0007);    // DC1[2:0], DC0[2:0], VC[2:0]
    LCD_WriteReg(R18, 0x0000);  // VREG1OUT voltage
    LCD_WriteReg(R19, 0x0000);    // VDV[4:0] for VCOM amplitude
    //	Delay_Ms(200);                    // Delay 200 MS , Dis-charge capacitor power voltage
    HAL_Delay(200);
    LCD_WriteReg(R16, 0x1690);    // SAP, BT[3:0], AP, DSTB, SLP, STB
    LCD_WriteReg(R17, 0x0227);  // R11H=0x0221 at VCI=3.3V, DC1[2:0], DC0[2:0], VC[2:0]
    //	Delay_Ms(50);      // Delay 50ms
    HAL_Delay(50);
    LCD_WriteReg(R18, 0x001D);  // External reference voltage= Vci;
    //	Delay_Ms(50);      // Delay 50ms
    HAL_Delay(50);
    LCD_WriteReg(R19, 0x0800);  // R13H=1D00 when R12H=009D;VDV[4:0] for VCOM amplitude
    LCD_WriteReg(R41, 0x0014);  // R29H=0013 when R12H=009D;VCM[5:0] for VCOMH
    LCD_WriteReg(R43, 0x000B);    // Frame Rate = 96Hz
    //	Delay_Ms(50);      // Delay 50ms
    HAL_Delay(50);
    LCD_WriteReg(R32, 0x0000);  // GRAM horizontal Address
    LCD_WriteReg(R33, 0x0000);  // GRAM Vertical Address
    /* ----------- Adjust the Gamma Curve ---------- */
    LCD_WriteReg(R48, 0x0007);
    LCD_WriteReg(R49, 0x0707);
    LCD_WriteReg(R50, 0x0006);
    LCD_WriteReg(R53, 0x0704);
    LCD_WriteReg(R54, 0x1F04);
    LCD_WriteReg(R55, 0x0004);
    LCD_WriteReg(R56, 0x0000);
    LCD_WriteReg(R57, 0x0706);
    LCD_WriteReg(R60, 0x0701);
    LCD_WriteReg(R61, 0x000F);
    /* ------------------ Set GRAM area --------------- */
    LCD_WriteReg(R80, 0x0000);    // Horizontal GRAM Start Address
    LCD_WriteReg(R81, 0x00EF);    // Horizontal GRAM End Address
    LCD_WriteReg(R82, 0x0000);  // Vertical GRAM Start Address
    LCD_WriteReg(R83, 0x013F);  // Vertical GRAM Start Address
    LCD_WriteReg(R96, 0x2700);  // Gate Scan Line		  0xA700
    LCD_WriteReg(R97, 0x0001);  // NDL,VLE, REV
    LCD_WriteReg(R106, 0x0000); // set scrolling line
    /* -------------- Partial Display Control --------- */
    LCD_WriteReg(R128, 0x0000);
    LCD_WriteReg(R129, 0x0000);
    LCD_WriteReg(R130, 0x0000);
    LCD_WriteReg(R131, 0x0000);
    LCD_WriteReg(R132, 0x0000);
    LCD_WriteReg(R133, 0x0000);
    /* -------------- Panel Control ------------------- */
    LCD_WriteReg(R144, 0x0010);
    LCD_WriteReg(R146, 0x0000);
    LCD_WriteReg(R147, 0x0003);
    LCD_WriteReg(R149, 0x0110);
    LCD_WriteReg(R151, 0x0000);
    LCD_WriteReg(R152, 0x0000);
    /* Set GRAM write direction and BGR = 1 */
    /* I/D=01 (Horizontal : increment, Vertical : decrement) */
    /* AM=1 (address is updated in vertical writing direction) */
    LCD_WriteReg(R3, 0x01018);    //0x1018

    LCD_WriteReg(R7, 0x0173);   // 262K color and display ON
}

注意其中的两行代码:

可以发现,在两行代码的后面,官方都提供了其作用以及可能的取值:0x0100和0xA700。

第一行代码决定了lcd的扫描顺序,取值为0x0000时,为从上到下;为0x0100时,为从下到上。通俗点说,这一行代码的取值可以让lcd显示上下颠倒。

第二行代码决定其左右扫描顺序,取值为0x2700时,为从左到右扫描;为0xA700时,为从右到左扫描。通俗点说,这一行代码的取值可以让lcd显示左右颠倒。

要实现题目上的屏幕反转效果,实际就是上下翻转+左右翻转,因此,将上面的两行代码的取值更改一下即可:

LCD_WriteReg(R1, 0x0100);    // 上下翻转
LCD_WriteReg(R96, 0xA700);   // 左右翻转

6. lcd单行高亮

参考:STM32-蓝桥杯嵌入式LCD字符颜色、高亮显示_嵌入式lcd背景颜色怎么换-CSDN博客

实际上就是一句代码的事:

LCD_SetBackColor(Yellow);

需要哪行代码高亮,就将该行后面设定其颜色即可,不过需要注意的是,如果只需要单行高亮的话,在使用完改代码后,后续要记得将背景颜色改回来。


总结

本文主要介绍了lcd相关操作的模板代码,主要是lcd文件的移植、lcd的初始化与显示、解决lcd和led的冲突、lcd屏幕反转、lcd单行高亮。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐