• 单片机常见的屏幕驱动移植


    目录

    一个驱动.c文件的典型模块划分(5)

    1. Include files

    2. Local type definitions ('typedef')

    3. Local pre-processor symbols/macros ('#define')

    4. Local variable definitions ('static')

    5. Function implementation - global ('extern') and local ('static')

    5.1 驱动初始化

    5.2 底层函数


    一个驱动.c文件的典型模块划分(5)

    1. Include files

    /*******************************************************************************
     * Include files
     ******************************************************************************/

    在文件的顶部列出,.C文件所要包含的头文件

    2. Local type definitions ('typedef')

    /*******************************************************************************
     * Local type definitions ('typedef')
     ******************************************************************************/
     
    /**
     * @brief LCD Device Structure Definition
     */
    typedef struct {
        uint16_t u16Dir;        /*!< Direction: 0, Vertical; 1, Horizontal */
        uint16_t u16ID;         /*!< LCD ID */
        uint16_t u16Width;      /*!< LCD Width */
        uint16_t u16Height;     /*!< LCD Heigth */
        uint16_t u16WRamCmd;    /*!< Start to write GRAM */
        uint16_t u16SetXCmd;    /*!< Set X axis */
        uint16_t u16SetYCmd;    /*!< Set Y axis */
    } stc_lcd_device_t;

    这是基本通用的屏幕参数:

    屏幕方向:水平显示,垂直显示

    屏幕ID:通过不同方式读取屏幕ID,根据不同ID兼容不同型号的屏幕

    屏幕宽度和高度:屏幕真实像素点个数

    屏幕写指令:将像素点数据写入GRAM

    屏幕坐标设置指令:将指针设置到指定像素点位置

    对于屏幕宽高,指的是像素大小,如240*320屏幕,表示屏幕为240*320像素 即76800个像素点,而不是屏幕尺寸。

    对于用过的 NT35310 / 9341 / 5310 / 7789 ,其写指令、坐标设置指令都一样,分别是0X2C,0X2A,0X2B。

    /**
     * @brief LCD Device Controller Structure Definition
     */
    typedef struct {
        volatile uint16_t u16REG;
        volatile uint16_t u16RAM;
    } stc_lcd_controller_t;

    这是最常用的LCD通讯实现方式,EXMC或FSMC。

    EXMC接口一般用 D[0:18] 进行通讯,一般用RGB565即16根数据线进行通讯。

    有WR\RD\CS\RS\RST五根控制线,CS用于片选器件,RS用于控制发送数据还是命令,WR和RS分别是写使能和读使能(基本都是低电平有效)。

    用EXMC接口驱动LCD屏幕时,其实是把它当成SRAM来用,只不过这个SRAM有2个地址,一个是写寄存器地址,一个是写数据地址。具体可搜索“FSMC驱动LCD的原理”去理解。

    具体地址定义如下:

    /* Use EXMC A16 as the RS signal */
    #define BSP_NT35510_BASE                (0x70000000UL | ((1UL << 17U) - 2UL))

    对应到最终写寄存器、写数据,就是直接修改指定地址的数据。

    FSMC一般有普通IO模拟、SPI和I2C等方式替代,FMC速率最高,普通IO并行模拟次之。

    除此之外,高分辨率屏幕,一般用RGB LCD接口,RGB分别是8位以上的数据线,还有DE数据使能线、VS垂直同步线、HS水平同步线、和DCLK像素时钟线。STM32可以用LTDC接口直接驱动,还有DMA2D图形加速。

    3. Local pre-processor symbols/macros ('#define')

    /*******************************************************************************
     * Local pre-processor symbols/macros ('#define')
     ******************************************************************************/

    /* LCD Scan Direction */
    #define LCD_SCAN_DIR                (LCD_SCAN_DIR_L2R_U2D)

    定义屏幕扫描方向为从左到右,从上到下

    4. Local variable definitions ('static')

    /*******************************************************************************
     * Local variable definitions ('static')
     ******************************************************************************/


    static stc_lcd_device_t m_stcLcdDevice;

    5. Function implementation - global ('extern') and local ('static')

    5.1 驱动初始化

    static void LCD_XXXX_Config(stc_lcd_controller_t *pstcLCD)

    {

            NT35510_WriteReg(pstcLCD, 0xE0); //Set Gamma

            NT35510_WriteData(pstcLCD, 0x0F);

            ...

            NT35510_WriteData(pstcLCD, 0XE1); //Set Gamma

            NT35510_WriteData(pstcLCD, 0x00);

            ...

    }

    屏幕驱动初始化设置大同小异,也主要是屏幕的寄存器定义基本类似。

    基本流程:

    1.  复位

    2.  进入正常模式或设置模式

    3.  显示颜色和方向设置

    4.  帧率设置

    5.  电源设置

    6.  gama设置

    不同屏幕的指令可能相同也有可能不一样,

    相同驱动ID的屏幕,厂家不同,gama设置以及其它设置也有可能不一样。

    具体都需要厂家提高参考代码。

    5.2 底层函数

    必备的底层函数一览:

    void NT35510_Init(stc_lcd_controller_t *pstcLCD);
    void NT35510_WriteData(stc_lcd_controller_t *pstcLCD, uint16_t u16Data);
    void NT35510_WriteReg(stc_lcd_controller_t *pstcLCD, uint16_t u16Reg);
    uint16_t NT35510_ReadData(stc_lcd_controller_t *pstcLCD);
    void NT35510_WriteRegData(stc_lcd_controller_t *pstcLCD, uint16_t u16Reg, uint16_t u16Data);
    uint16_t NT35510_ReadRegData(stc_lcd_controller_t *pstcLCD, uint16_t u16Reg);
    uint16_t NT35510_ReadID(stc_lcd_controller_t *pstcLCD);
    void NT35510_DisplayOn(stc_lcd_controller_t *pstcLCD);
    void NT35510_DisplayOff(stc_lcd_controller_t *pstcLCD);
    uint16_t NT35510_GetPixelWidth(void);
    uint16_t NT35510_GetPixelHeight(void);
    void NT35510_SetScanDir(stc_lcd_controller_t *pstcLCD, uint16_t u16Dir);
    void NT35510_SetDisplayDir(stc_lcd_controller_t *pstcLCD, uint16_t u16Dir);
    void NT35510_PrepareWriteRAM(stc_lcd_controller_t *pstcLCD);
    void NT35510_SetBackLight(stc_lcd_controller_t *pstcLCD, uint8_t u8PWM);
    void NT35510_SetCursor(stc_lcd_controller_t *pstcLCD, uint16_t u16Xpos, uint16_t u16Ypos);
    void NT35510_WritePixel(stc_lcd_controller_t *pstcLCD, uint16_t u16Xpos, uint16_t u16Ypos, uint16_t u16RGBCode);
    void NT35510_Clear(stc_lcd_controller_t *pstcLCD, uint16_t u16RGBCode);

    具体实现:

    需要做兼容处理的部分:

    NT35510_Init                         驱动初始化

    NT35510_ReadID                 读取驱动芯片ID

    NT35510_SetScanDir           设置扫描方向 | 宽 高 写指令

    1. void NT35510_Init(stc_lcd_controller_t *pstcLCD)
    2. {
    3. /* NOP */
    4. NT35510_WriteRegData(pstcLCD, 0x0000U, 0x00U);
    5. /* Read ID */
    6. m_stcLcdDevice.u16ID = NT35510_ReadID(pstcLCD);
    7. /* Chip Init */
    8. if(m_stcLcdDevice.u16ID == 0x9341){
    9. LCD_9341_Config(pstcLCD);
    10. } else if(m_stcLcdDevice.u16ID == 0x7789){
    11. LCD_7789_Config(pstcLCD);
    12. } else {
    13. /* Unsupported LCD */
    14. }
    15. /* Set LCD cursor */
    16. NT35510_SetDisplayDir(pstcLCD, LCD_DISPLAY_VERTICAL);
    17. /* Set cursor */
    18. NT35510_SetCursor(pstcLCD, 0U, 0U);
    19. /* Prepare to write to LCD RAM */
    20. NT35510_PrepareWriteRAM(pstcLCD);
    21. }
    22. /**
    23. * @brief Read LCD ID.
    24. * @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure.
    25. * @retval LCD Register Value.
    26. */
    27. uint16_t NT35510_ReadID(stc_lcd_controller_t *pstcLCD)
    28. {
    29. uint16_t u16ID;
    30. /* Try to read ID: 0x9341 */
    31. NT35510_WriteReg(pstcLCD, 0xD3U);
    32. (void)NT35510_ReadData(pstcLCD); /* dummy read */
    33. (void)NT35510_ReadData(pstcLCD); /* read: 0x00 */
    34. u16ID = NT35510_ReadData(pstcLCD) << 8; /* read: 0x93 */
    35. u16ID |= NT35510_ReadData(pstcLCD); /* read: 0x41 */
    36. if (u16ID != 0x9341U) {
    37. /* Try to read ID: 0x8552 */
    38. NT35510_WriteReg(pstcLCD, 0x04U);
    39. (void)NT35510_ReadData(pstcLCD); /* dummy read */
    40. (void)NT35510_ReadData(pstcLCD); /* read: 0x85 */
    41. u16ID = NT35510_ReadData(pstcLCD) << 8; /* read: 0x85 */
    42. u16ID |= NT35510_ReadData(pstcLCD); /* read: 0x41 */
    43. if (u16ID == 0x8552U) {
    44. u16ID = 0x7789U; /* ID convert to: 0x7789 */
    45. }
    46. else {
    47. u16ID = 0U; /* Unsupported LCD */
    48. }
    49. }
    50. return u16ID;
    51. }
    52. /**
    53. * @brief Set scan direction.
    54. * @param [in] pstcLCD: LCD controller
    55. * @param [in] u16Dir: Scan direction
    56. * This parameter can be one of the following values:
    57. * @arg LCD_SCAN_DIR_L2R_U2D: From left to right && from up to down
    58. * @arg LCD_SCAN_DIR_L2R_D2U: From left to right && from down to up
    59. * @arg LCD_SCAN_DIR_R2L_U2D: From right to left && from up to down
    60. * @arg LCD_SCAN_DIR_R2L_D2U: From right to left && from down to up
    61. * @arg LCD_SCAN_DIR_U2D_L2R: From up to down && from left to right
    62. * @arg LCD_SCAN_DIR_U2D_R2L: From up to down && from right to left
    63. * @arg LCD_SCAN_DIR_D2U_L2R: From down to up && from left to right
    64. * @arg LCD_SCAN_DIR_D2U_R2L: From down to up && from right to left
    65. * @retval None
    66. */
    67. void NT35510_SetScanDir(stc_lcd_controller_t *pstcLCD, uint16_t u16Dir)
    68. {
    69. uint16_t u16Temp;
    70. uint16_t dirreg;
    71. uint16_t regval = 0U;
    72. /* when display dir is VERTICAL, 1963 IC change scan-direction, other IC don't change
    73. when display dir is HORIZONTAL, 1963 IC don't change scan-direction, other IC change */
    74. if (((0U == m_stcLcdDevice.u16Dir) && (m_stcLcdDevice.u16ID == 0x1963U)) || \
    75. ((1U == m_stcLcdDevice.u16Dir) && (m_stcLcdDevice.u16ID != 0x1963U))) {
    76. if (0U == u16Dir) {
    77. u16Dir = 6U;
    78. } else if (1U == u16Dir) {
    79. u16Dir = 7U;
    80. } else if (2U == u16Dir) {
    81. u16Dir = 4U;
    82. } else if (3UL == u16Dir) {
    83. u16Dir = 5U;
    84. } else if (4U == u16Dir) {
    85. u16Dir = 1U;
    86. } else if (5U == u16Dir) {
    87. u16Dir = 0U;
    88. } else if (6U == u16Dir) {
    89. u16Dir = 3U;
    90. } else if (7U == u16Dir) {
    91. u16Dir = 2U;
    92. } else {
    93. u16Dir = 6U;
    94. }
    95. }
    96. switch (u16Dir) {
    97. case LCD_SCAN_DIR_L2R_U2D:
    98. regval |= ((0U << 7) | (0U << 6) | (0U << 5));
    99. break;
    100. case LCD_SCAN_DIR_L2R_D2U:
    101. regval |= ((1U << 7) | (0U << 6) | (0U << 5));
    102. break;
    103. case LCD_SCAN_DIR_R2L_U2D:
    104. regval |= ((0U << 7) | (1U << 6) | (0U << 5));
    105. break;
    106. case LCD_SCAN_DIR_R2L_D2U:
    107. regval |= ((1U << 7) | (1U << 6) | (0U << 5));
    108. break;
    109. case LCD_SCAN_DIR_U2D_L2R:
    110. regval |= ((0U << 7) | (0U << 6) | (1U << 5));
    111. break;
    112. case LCD_SCAN_DIR_U2D_R2L:
    113. regval |= ((0U << 7) | (1U << 6) | (1U << 5));
    114. break;
    115. case LCD_SCAN_DIR_D2U_L2R:
    116. regval |= ((1U << 7) | (0U << 6) | (1U << 5));
    117. break;
    118. case LCD_SCAN_DIR_D2U_R2L:
    119. regval |= ((1U << 7) | (1U << 6) | (1U << 5));
    120. break;
    121. default:
    122. break;
    123. }
    124. if (0x5510U == m_stcLcdDevice.u16ID) {
    125. dirreg = 0x3600U;
    126. } else {
    127. dirreg = 0x36U;
    128. }
    129. /* 0x9341 & 0x7789 set BGR bit */
    130. if ((0x9341U == m_stcLcdDevice.u16ID) || (0x7789U == m_stcLcdDevice.u16ID)) {
    131. regval |= 0x08U;
    132. }
    133. NT35510_WriteRegData(pstcLCD, dirreg, regval);
    134. /* 1963 don't handle coordinate */
    135. if (m_stcLcdDevice.u16ID != 0x1963U) {
    136. if ((regval & 0x20U) > 0U) {
    137. /* swap X,Y */
    138. if (m_stcLcdDevice.u16Width < m_stcLcdDevice.u16Height) {
    139. u16Temp = m_stcLcdDevice.u16Width;
    140. m_stcLcdDevice.u16Width = m_stcLcdDevice.u16Height;
    141. m_stcLcdDevice.u16Height = u16Temp;
    142. }
    143. } else {
    144. /* swap X,Y */
    145. if (m_stcLcdDevice.u16Width > m_stcLcdDevice.u16Height) {
    146. u16Temp = m_stcLcdDevice.u16Width;
    147. m_stcLcdDevice.u16Width = m_stcLcdDevice.u16Height;
    148. m_stcLcdDevice.u16Height = u16Temp;
    149. }
    150. }
    151. }
    152. /* Set display window size */
    153. NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetXCmd);
    154. NT35510_WriteData(pstcLCD, 0U);
    155. NT35510_WriteData(pstcLCD, 0U);
    156. NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Width - 1U) >> 8);
    157. NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Width - 1U) & 0xFFU);
    158. NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetYCmd);
    159. NT35510_WriteData(pstcLCD, 0U);
    160. NT35510_WriteData(pstcLCD, 0U);
    161. NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Height - 1U) >> 8);
    162. NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Height - 1U) & 0xFFU);
    163. }
    164. /**
    165. * @brief Set screen direction.
    166. * @param [in] pstcLCD: LCD controller
    167. * @param [in] u16Dir: Screen direction
    168. * This parameter can be one of the following values:
    169. * @arg LCD_DISPLAY_VERTICAL: LCD vertical display
    170. * @arg LCD_DISPLAY_HORIZONTAL: LCD horizontal display
    171. * @retval None
    172. */
    173. void NT35510_SetDisplayDir(stc_lcd_controller_t *pstcLCD, uint16_t u16Dir)
    174. {
    175. /* NT35310 / 9341 / 5310 / 7789 etc */
    176. m_stcLcdDevice.u16WRamCmd = 0x2CU;
    177. m_stcLcdDevice.u16SetXCmd = 0x2AU;
    178. m_stcLcdDevice.u16SetYCmd = 0x2BU;
    179. m_stcLcdDevice.u16Width = 320U;
    180. m_stcLcdDevice.u16Height = 240U;
    181. m_stcLcdDevice.u16Dir = u16Dir;
    182. NT35510_SetScanDir(pstcLCD, LCD_SCAN_DIR);
    183. }

    底层通用函数:

    NT35510_WriteData               写数据

    NT35510_WriteReg                写寄存器

    NT35510_ReadData               读数据

    NT35510_WriteRegData         写寄存器数据

    NT35510_ReadRegData         读寄存器数据

    NT35510_DisplayOn                打开显示

    NT35510_DisplayOff                关闭显示

    NT35510_GetPixelWidth         获取像素宽度

    NT35510_GetPixelHeight        获取像素高度

    NT35510_PrepareWriteRAM   写RAM

    NT35510_SetCursor                设置坐标

    NT35510_WritePixel                写单个像素点颜色

    NT35510_Clear                        清屏

    1. /**
    2. * @brief Write data on LCD data register.
    3. * @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure.
    4. * @param [in] u16Data: Data to be written
    5. * @retval None
    6. */
    7. void NT35510_WriteData(stc_lcd_controller_t *pstcLCD, uint16_t u16Data)
    8. {
    9. pstcLCD->u16RAM = u16Data;
    10. }
    11. /**
    12. * @brief Write register on LCD register.
    13. * @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure.
    14. * @param [in] u16Reg: Address of the selected register.
    15. * @retval None
    16. */
    17. void NT35510_WriteReg(stc_lcd_controller_t *pstcLCD, uint16_t u16Reg)
    18. {
    19. pstcLCD->u16REG = u16Reg;
    20. }
    21. /**
    22. * @brief Read data from LCD data register.
    23. * @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure.
    24. * @retval Read data.
    25. */
    26. uint16_t NT35510_ReadData(stc_lcd_controller_t *pstcLCD)
    27. {
    28. return pstcLCD->u16RAM;
    29. }
    30. /**
    31. * @brief Write to the selected LCD register.
    32. * @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure.
    33. * @param [in] u16Reg: Address of the selected register.
    34. * @param [in] u16Data: Data to be written
    35. * @retval None
    36. */
    37. void NT35510_WriteRegData(stc_lcd_controller_t *pstcLCD, uint16_t u16Reg, uint16_t u16Data)
    38. {
    39. /* Write 16-bit index */
    40. pstcLCD->u16REG = u16Reg;
    41. /* Write 16-bit Reg */
    42. pstcLCD->u16RAM = u16Data;
    43. }
    44. /**
    45. * @brief Read the selected LCD register.
    46. * @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure.
    47. * @param [in] u16Reg: Address of the selected register.
    48. * @retval Register value
    49. */
    50. uint16_t NT35510_ReadRegData(stc_lcd_controller_t *pstcLCD, uint16_t u16Reg)
    51. {
    52. /* Write 16-bit index*/
    53. pstcLCD->u16REG = u16Reg;
    54. return pstcLCD->u16RAM;
    55. }
    56. /**
    57. * @brief Enable the Display.
    58. * @param [in] pstcLCD: LCD controller
    59. * @retval None
    60. */
    61. void NT35510_DisplayOn(stc_lcd_controller_t *pstcLCD)
    62. {
    63. if (m_stcLcdDevice.u16ID == 0x5510U) {
    64. NT35510_WriteReg(pstcLCD, 0x2900U); /* 5510 */
    65. } else {
    66. NT35510_WriteReg(pstcLCD, 0x29U); /* 9341/5310/1963/7789 */
    67. }
    68. }
    69. /**
    70. * @brief Disable the Display.
    71. * @param [in] pstcLCD: LCD controller
    72. * @retval None
    73. */
    74. void NT35510_DisplayOff(stc_lcd_controller_t *pstcLCD)
    75. {
    76. if (m_stcLcdDevice.u16ID == 0x5510U) {
    77. NT35510_WriteReg(pstcLCD, 0x2800U); /* 5510 */
    78. } else {
    79. NT35510_WriteReg(pstcLCD, 0x28U); /* 9341/5310/1963/7789 */
    80. }
    81. }
    82. /**
    83. * @brief Get LCD PIXEL WIDTH.
    84. * @param None
    85. * @retval LCD PIXEL WIDTH.
    86. */
    87. uint16_t NT35510_GetPixelWidth(void)
    88. {
    89. return m_stcLcdDevice.u16Width;
    90. }
    91. /**
    92. * @brief Get LCD PIXEL HEIGHT.
    93. * @param None
    94. * @retval LCD PIXEL HEIGHT.
    95. */
    96. uint16_t NT35510_GetPixelHeight(void)
    97. {
    98. return m_stcLcdDevice.u16Height;
    99. }
    100. /**
    101. * @brief Prepare to write LCD RAM.
    102. * @param [in] pstcLCD: LCD controller
    103. * @retval None
    104. */
    105. void NT35510_PrepareWriteRAM(stc_lcd_controller_t *pstcLCD)
    106. {
    107. NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16WRamCmd);
    108. }
    109. /**
    110. * @brief Set screen backlight.
    111. * @param [in] pstcLCD: LCD controller
    112. * @param [in] u8PWM: PWM level
    113. This parameter can be a value between Min_Data = 0 and Max_Data = 100
    114. * @retval None
    115. */
    116. void NT35510_SetBackLight(stc_lcd_controller_t *pstcLCD, uint8_t u8PWM)
    117. {
    118. float32_t f32PWM = ((float32_t)u8PWM * 2.55F);
    119. NT35510_WriteReg(pstcLCD, 0xBEU);
    120. NT35510_WriteData(pstcLCD, 0x05U);
    121. NT35510_WriteData(pstcLCD, (uint16_t)f32PWM);
    122. NT35510_WriteData(pstcLCD, 0x01U);
    123. NT35510_WriteData(pstcLCD, 0xFFU);
    124. NT35510_WriteData(pstcLCD, 0x00U);
    125. NT35510_WriteData(pstcLCD, 0x00U);
    126. }
    127. /**
    128. * @brief Set Cursor position.
    129. * @param [in] pstcLCD: LCD controller
    130. * @param u16Xpos: Specifies the X position.
    131. * @param u16Ypos: Specifies the Y position.
    132. * @retval None
    133. */
    134. void NT35510_SetCursor(stc_lcd_controller_t *pstcLCD, uint16_t u16Xpos, uint16_t u16Ypos)
    135. {
    136. NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetXCmd);
    137. NT35510_WriteData(pstcLCD, (u16Xpos >> 8));
    138. NT35510_WriteData(pstcLCD, (u16Xpos & 0xFFU));
    139. NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetYCmd);
    140. NT35510_WriteData(pstcLCD, (u16Ypos >> 8));
    141. NT35510_WriteData(pstcLCD, (u16Ypos & 0xFFU));
    142. }
    143. /**
    144. * @brief Write pixel.
    145. * @param [in] pstcLCD: LCD controller
    146. * @param u16Xpos: Specifies the X position.
    147. * @param u16Ypos: Specifies the Y position.
    148. * @param u16RGBCode: The RGB pixel color in RGB565 format
    149. * @retval None
    150. */
    151. void NT35510_WritePixel(stc_lcd_controller_t *pstcLCD, uint16_t u16Xpos, uint16_t u16Ypos, uint16_t u16RGBCode)
    152. {
    153. /* Set cursor */
    154. NT35510_SetCursor(pstcLCD, u16Xpos, u16Ypos);
    155. /* Prepare to write to LCD RAM */
    156. NT35510_PrepareWriteRAM(pstcLCD);
    157. NT35510_WriteData(pstcLCD, u16RGBCode);
    158. }
    159. /**
    160. * @brief Clear screen.
    161. * @param [in] pstcLCD: LCD controller
    162. * @param u16RGBCode: The RGB pixel color in RGB565 format
    163. * @retval None
    164. */
    165. void NT35510_Clear(stc_lcd_controller_t *pstcLCD, uint16_t u16RGBCode)
    166. {
    167. uint32_t i;
    168. uint32_t u32TotalPoint;
    169. /* Set cursor */
    170. NT35510_SetCursor(pstcLCD, 0U, 0U);
    171. /* Prepare to write to LCD RAM */
    172. NT35510_PrepareWriteRAM(pstcLCD);
    173. u32TotalPoint = (uint32_t)m_stcLcdDevice.u16Width * (uint32_t)m_stcLcdDevice.u16Height;
    174. for (i = 0UL; i < u32TotalPoint; i++) {
    175. NT35510_WriteData(pstcLCD, u16RGBCode);
    176. }
    177. }

    5.3 画线

    利用差值法画线。包括水平线、垂直线、斜线。

    画线是最基本的函数,基于画线函数可以衍生出画圆、画弧线、画矩形等多种图形。

    /**
     * @brief  Draw line.
     * @param  [in] pstcLCD:                LCD controller
     * @param  u16X1:                       Specifies the X position 1.
     * @param  u16X2:                       Specifies the X position 2.
     * @param  u16Y1:                       Specifies the Y position 1.
     * @param  u16Y2:                       Specifies the Y position 2.
     * @param  u16RGBCode:                  The RGB pixel color in RGB565 format
     * @retval None
     */
    void NT35510_DrawLine(stc_lcd_controller_t *pstcLCD, uint16_t u16X1, uint16_t u16Y1,
                          uint16_t u16X2, uint16_t u16Y2, uint16_t u16RGBCode)
    {
        int16_t t;
        int16_t xerr = 0;
        int16_t yerr = 0;
        int16_t delta_x;
        int16_t delta_y;
        int16_t distance;
        int16_t incx;
        int16_t incy;
        int16_t Row;
        int16_t Col;

        Row = (int16_t)u16X1;
        Col = (int16_t)u16Y1;
        delta_x = ((int16_t)u16X2 - (int16_t)u16X1);      /* calc delta X, Y*/
        delta_y = ((int16_t)u16Y2 - (int16_t)u16Y1);

        if (delta_x > 0) {
            incx = 1;           /* forward u8Direction */
        } else if (delta_x == 0) {
            incx = 0;           /* vertical line */
        } else {
            incx = -1;          /* reverse direction */
            delta_x = -delta_x;
        }

        if (delta_y > 0) {
            incy = 1;             /* downward direction */
        } else if (delta_y == 0) {
            incy = 0;             /* horizontal line */
        } else {
            incy = -1;            /* upward direction */
            delta_y = -delta_y;
        }

        if (delta_x > delta_y) {
            distance = delta_x; /* set axis */
        } else {
            distance = delta_y;
        }

        for (t = 0; t <= (distance + 1); t++) {
            NT35510_WritePixel(pstcLCD, (uint16_t)Row, (uint16_t)Col, u16RGBCode);   /* draw pixel */

            xerr += delta_x ;
            yerr += delta_y ;

            if (xerr > distance) {
                xerr -= distance;
                Row += incx;
            }

            if (yerr > distance) {
                yerr -= distance;
                Col += incy;
            }
        }
    }
     

    Bresenham算法画圆


    /**
     * @brief  Draw a circle.
     * @param  [in] pstcLCD:                LCD controller
     * @param  [in]                         u16Xpos: X position
     * @param  [in]                         u16Ypos: Y position
     * @param  [in]                         u16Radius: Circle radius
     * @param  u16RGBCode:                  The RGB pixel color in RGB565 format
     * @retval None
     */
    void NT35510_DrawCircle(stc_lcd_controller_t *pstcLCD, uint16_t u16Xpos, uint16_t u16Ypos,
                            uint16_t u16Radius, uint16_t u16RGBCode)
    {
        int32_t  decision;       /* Decision Variable */
        uint32_t current_x;      /* Current X Value */
        uint32_t current_y;      /* Current Y Value */

        decision = 3 - ((int32_t)u16Radius * 2);
        current_x = 0U;
        current_y = u16Radius;

        while (current_x <= current_y) {
            NT35510_WritePixel(pstcLCD, (u16Xpos + (uint16_t)current_x), (u16Ypos - (uint16_t)current_y), u16RGBCode);
            NT35510_WritePixel(pstcLCD, (u16Xpos + (uint16_t)current_y), (u16Ypos - (uint16_t)current_x), u16RGBCode);
            NT35510_WritePixel(pstcLCD, (u16Xpos + (uint16_t)current_y), (u16Ypos + (uint16_t)current_x), u16RGBCode);
            NT35510_WritePixel(pstcLCD, (u16Xpos + (uint16_t)current_x), (u16Ypos + (uint16_t)current_y), u16RGBCode);
            NT35510_WritePixel(pstcLCD, (u16Xpos - (uint16_t)current_x), (u16Ypos + (uint16_t)current_y), u16RGBCode);
            NT35510_WritePixel(pstcLCD, (u16Xpos - (uint16_t)current_y), (u16Ypos + (uint16_t)current_x), u16RGBCode);
            NT35510_WritePixel(pstcLCD, (u16Xpos - (uint16_t)current_x), (u16Ypos - (uint16_t)current_y), u16RGBCode);
            NT35510_WritePixel(pstcLCD, (u16Xpos - (uint16_t)current_y), (u16Ypos - (uint16_t)current_x), u16RGBCode);
            current_x++;
            /* Bresenham algorithm */
            if (decision < 0) {
                decision += ((4 * (int32_t)current_x) + 6);
            } else {
                decision += (10 + (4 * ((int32_t)current_x - (int32_t)current_y)));
                current_y--;
            }
        }
    }

    5.4 显示图片

    像素点其实就是:

    1)事先将要显示的图,转化成位图,确定每个像素点要显示的颜色

    2)依次显示这些点

    基于这种方法,可以衍生出显示文字符合、特殊图像等等。

    不过该方法对内存要求高,需要占用RAM或ROM 来存储这些像素点颜色数据。

    /**
     * @brief  Show Picture.
     * @param  [in] pstcLCD:                LCD controller
     * @param  u16RGBCode:                  The RGB pixel color in RGB565 format
     * @retval None
     */
    void NT35510_Picture(stc_lcd_controller_t *pstcLCD, uint16_t *pu16RGBData)
    {
        uint32_t i;
        uint32_t u32TotalPoint;

        /* Set cursor */
        NT35510_SetCursor(pstcLCD, 0U, 0U);

        /* Prepare to write to LCD RAM */
        NT35510_PrepareWriteRAM(pstcLCD);

        u32TotalPoint = (uint32_t)m_stcLcdDevice.u16Width * (uint32_t)m_stcLcdDevice.u16Height;

        for (i = 0UL; i < u32TotalPoint; i++) {
            NT35510_WriteData(pstcLCD, pu16RGBData[i]);
        }
    }

  • 相关阅读:
    使用Zadig从0到1搭建持续交付平台
    R Studio 安装stringi 报错download of package ‘stringi’ failed
    TorchDrug教程--知识图推理
    源码解析springbatch的job是如何运行的?
    仿牛客网项目---Elasticsearch分布式搜索引擎
    CyberController手机外挂番外篇:源代码的二次修改
    金融知识分析系列之:期货种类、T+0期货品种、期货IF、沪深300股指期货、IF交割月份
    算法题:给定一个数组和一个目标和,从数组中找到两个数字相加等于目标和,输出这两个数字的下标
    cmake-format使用教程
    vue源码分析-从new Vue开始
  • 原文地址:https://blog.csdn.net/weixin_38743772/article/details/133807499