目录
一个驱动.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 设置扫描方向 | 宽 高 写指令
void NT35510_Init(stc_lcd_controller_t *pstcLCD)
{/* NOP */NT35510_WriteRegData(pstcLCD, 0x0000U, 0x00U);/* Read ID */m_stcLcdDevice.u16ID = NT35510_ReadID(pstcLCD);/* Chip Init */if(m_stcLcdDevice.u16ID == 0x9341){LCD_9341_Config(pstcLCD);} else if(m_stcLcdDevice.u16ID == 0x7789){LCD_7789_Config(pstcLCD);} else {/* Unsupported LCD */}/* Set LCD cursor */NT35510_SetDisplayDir(pstcLCD, LCD_DISPLAY_VERTICAL);/* Set cursor */NT35510_SetCursor(pstcLCD, 0U, 0U);/* Prepare to write to LCD RAM */NT35510_PrepareWriteRAM(pstcLCD);
}/*** @brief Read LCD ID.* @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure.* @retval LCD Register Value.*/
uint16_t NT35510_ReadID(stc_lcd_controller_t *pstcLCD)
{uint16_t u16ID;/* Try to read ID: 0x9341 */NT35510_WriteReg(pstcLCD, 0xD3U);(void)NT35510_ReadData(pstcLCD); /* dummy read */(void)NT35510_ReadData(pstcLCD); /* read: 0x00 */u16ID = NT35510_ReadData(pstcLCD) << 8; /* read: 0x93 */u16ID |= NT35510_ReadData(pstcLCD); /* read: 0x41 */if (u16ID != 0x9341U) {/* Try to read ID: 0x8552 */NT35510_WriteReg(pstcLCD, 0x04U);(void)NT35510_ReadData(pstcLCD); /* dummy read */(void)NT35510_ReadData(pstcLCD); /* read: 0x85 */u16ID = NT35510_ReadData(pstcLCD) << 8; /* read: 0x85 */u16ID |= NT35510_ReadData(pstcLCD); /* read: 0x41 */if (u16ID == 0x8552U) {u16ID = 0x7789U; /* ID convert to: 0x7789 */}else {u16ID = 0U; /* Unsupported LCD */}}return u16ID;
}/*** @brief Set scan direction.* @param [in] pstcLCD: LCD controller* @param [in] u16Dir: Scan direction* This parameter can be one of the following values:* @arg LCD_SCAN_DIR_L2R_U2D: From left to right && from up to down* @arg LCD_SCAN_DIR_L2R_D2U: From left to right && from down to up* @arg LCD_SCAN_DIR_R2L_U2D: From right to left && from up to down* @arg LCD_SCAN_DIR_R2L_D2U: From right to left && from down to up* @arg LCD_SCAN_DIR_U2D_L2R: From up to down && from left to right* @arg LCD_SCAN_DIR_U2D_R2L: From up to down && from right to left* @arg LCD_SCAN_DIR_D2U_L2R: From down to up && from left to right* @arg LCD_SCAN_DIR_D2U_R2L: From down to up && from right to left* @retval None*/
void NT35510_SetScanDir(stc_lcd_controller_t *pstcLCD, uint16_t u16Dir)
{uint16_t u16Temp;uint16_t dirreg;uint16_t regval = 0U;/* when display dir is VERTICAL, 1963 IC change scan-direction, other IC don't changewhen display dir is HORIZONTAL, 1963 IC don't change scan-direction, other IC change */if (((0U == m_stcLcdDevice.u16Dir) && (m_stcLcdDevice.u16ID == 0x1963U)) || \((1U == m_stcLcdDevice.u16Dir) && (m_stcLcdDevice.u16ID != 0x1963U))) {if (0U == u16Dir) {u16Dir = 6U;} else if (1U == u16Dir) {u16Dir = 7U;} else if (2U == u16Dir) {u16Dir = 4U;} else if (3UL == u16Dir) {u16Dir = 5U;} else if (4U == u16Dir) {u16Dir = 1U;} else if (5U == u16Dir) {u16Dir = 0U;} else if (6U == u16Dir) {u16Dir = 3U;} else if (7U == u16Dir) {u16Dir = 2U;} else {u16Dir = 6U;}}switch (u16Dir) {case LCD_SCAN_DIR_L2R_U2D:regval |= ((0U << 7) | (0U << 6) | (0U << 5));break;case LCD_SCAN_DIR_L2R_D2U:regval |= ((1U << 7) | (0U << 6) | (0U << 5));break;case LCD_SCAN_DIR_R2L_U2D:regval |= ((0U << 7) | (1U << 6) | (0U << 5));break;case LCD_SCAN_DIR_R2L_D2U:regval |= ((1U << 7) | (1U << 6) | (0U << 5));break;case LCD_SCAN_DIR_U2D_L2R:regval |= ((0U << 7) | (0U << 6) | (1U << 5));break;case LCD_SCAN_DIR_U2D_R2L:regval |= ((0U << 7) | (1U << 6) | (1U << 5));break;case LCD_SCAN_DIR_D2U_L2R:regval |= ((1U << 7) | (0U << 6) | (1U << 5));break;case LCD_SCAN_DIR_D2U_R2L:regval |= ((1U << 7) | (1U << 6) | (1U << 5));break;default:break;}if (0x5510U == m_stcLcdDevice.u16ID) {dirreg = 0x3600U;} else {dirreg = 0x36U;}/* 0x9341 & 0x7789 set BGR bit */if ((0x9341U == m_stcLcdDevice.u16ID) || (0x7789U == m_stcLcdDevice.u16ID)) {regval |= 0x08U;}NT35510_WriteRegData(pstcLCD, dirreg, regval);/* 1963 don't handle coordinate */if (m_stcLcdDevice.u16ID != 0x1963U) {if ((regval & 0x20U) > 0U) {/* swap X,Y */if (m_stcLcdDevice.u16Width < m_stcLcdDevice.u16Height) {u16Temp = m_stcLcdDevice.u16Width;m_stcLcdDevice.u16Width = m_stcLcdDevice.u16Height;m_stcLcdDevice.u16Height = u16Temp;}} else {/* swap X,Y */if (m_stcLcdDevice.u16Width > m_stcLcdDevice.u16Height) {u16Temp = m_stcLcdDevice.u16Width;m_stcLcdDevice.u16Width = m_stcLcdDevice.u16Height;m_stcLcdDevice.u16Height = u16Temp;}}}/* Set display window size */NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetXCmd);NT35510_WriteData(pstcLCD, 0U);NT35510_WriteData(pstcLCD, 0U);NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Width - 1U) >> 8);NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Width - 1U) & 0xFFU);NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetYCmd);NT35510_WriteData(pstcLCD, 0U);NT35510_WriteData(pstcLCD, 0U);NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Height - 1U) >> 8);NT35510_WriteData(pstcLCD, (m_stcLcdDevice.u16Height - 1U) & 0xFFU);
}/*** @brief Set screen direction.* @param [in] pstcLCD: LCD controller* @param [in] u16Dir: Screen direction* This parameter can be one of the following values:* @arg LCD_DISPLAY_VERTICAL: LCD vertical display* @arg LCD_DISPLAY_HORIZONTAL: LCD horizontal display* @retval None*/
void NT35510_SetDisplayDir(stc_lcd_controller_t *pstcLCD, uint16_t u16Dir)
{/* NT35310 / 9341 / 5310 / 7789 etc */m_stcLcdDevice.u16WRamCmd = 0x2CU;m_stcLcdDevice.u16SetXCmd = 0x2AU;m_stcLcdDevice.u16SetYCmd = 0x2BU;m_stcLcdDevice.u16Width = 320U;m_stcLcdDevice.u16Height = 240U;m_stcLcdDevice.u16Dir = u16Dir;NT35510_SetScanDir(pstcLCD, LCD_SCAN_DIR);
}
底层通用函数:
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 清屏
/*** @brief Write data on LCD data register.* @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure.* @param [in] u16Data: Data to be written* @retval None*/
void NT35510_WriteData(stc_lcd_controller_t *pstcLCD, uint16_t u16Data)
{pstcLCD->u16RAM = u16Data;
}/*** @brief Write register on LCD register.* @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure.* @param [in] u16Reg: Address of the selected register.* @retval None*/
void NT35510_WriteReg(stc_lcd_controller_t *pstcLCD, uint16_t u16Reg)
{pstcLCD->u16REG = u16Reg;
}/*** @brief Read data from LCD data register.* @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure.* @retval Read data.*/
uint16_t NT35510_ReadData(stc_lcd_controller_t *pstcLCD)
{return pstcLCD->u16RAM;
}/*** @brief Write to the selected LCD register.* @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure.* @param [in] u16Reg: Address of the selected register.* @param [in] u16Data: Data to be written* @retval None*/
void NT35510_WriteRegData(stc_lcd_controller_t *pstcLCD, uint16_t u16Reg, uint16_t u16Data)
{/* Write 16-bit index */pstcLCD->u16REG = u16Reg;/* Write 16-bit Reg */pstcLCD->u16RAM = u16Data;
}/*** @brief Read the selected LCD register.* @param [in] pstcLCD: LCD controller @ref stc_lcd_controller_t structure.* @param [in] u16Reg: Address of the selected register.* @retval Register value*/
uint16_t NT35510_ReadRegData(stc_lcd_controller_t *pstcLCD, uint16_t u16Reg)
{/* Write 16-bit index*/pstcLCD->u16REG = u16Reg;return pstcLCD->u16RAM;
}/*** @brief Enable the Display.* @param [in] pstcLCD: LCD controller* @retval None*/
void NT35510_DisplayOn(stc_lcd_controller_t *pstcLCD)
{if (m_stcLcdDevice.u16ID == 0x5510U) {NT35510_WriteReg(pstcLCD, 0x2900U); /* 5510 */} else {NT35510_WriteReg(pstcLCD, 0x29U); /* 9341/5310/1963/7789 */}
}/*** @brief Disable the Display.* @param [in] pstcLCD: LCD controller* @retval None*/
void NT35510_DisplayOff(stc_lcd_controller_t *pstcLCD)
{if (m_stcLcdDevice.u16ID == 0x5510U) {NT35510_WriteReg(pstcLCD, 0x2800U); /* 5510 */} else {NT35510_WriteReg(pstcLCD, 0x28U); /* 9341/5310/1963/7789 */}
}/*** @brief Get LCD PIXEL WIDTH.* @param None* @retval LCD PIXEL WIDTH.*/
uint16_t NT35510_GetPixelWidth(void)
{return m_stcLcdDevice.u16Width;
}/*** @brief Get LCD PIXEL HEIGHT.* @param None* @retval LCD PIXEL HEIGHT.*/
uint16_t NT35510_GetPixelHeight(void)
{return m_stcLcdDevice.u16Height;
}/*** @brief Prepare to write LCD RAM.* @param [in] pstcLCD: LCD controller* @retval None*/
void NT35510_PrepareWriteRAM(stc_lcd_controller_t *pstcLCD)
{NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16WRamCmd);
}/*** @brief Set screen backlight.* @param [in] pstcLCD: LCD controller* @param [in] u8PWM: PWM levelThis parameter can be a value between Min_Data = 0 and Max_Data = 100* @retval None*/
void NT35510_SetBackLight(stc_lcd_controller_t *pstcLCD, uint8_t u8PWM)
{float32_t f32PWM = ((float32_t)u8PWM * 2.55F);NT35510_WriteReg(pstcLCD, 0xBEU);NT35510_WriteData(pstcLCD, 0x05U);NT35510_WriteData(pstcLCD, (uint16_t)f32PWM);NT35510_WriteData(pstcLCD, 0x01U);NT35510_WriteData(pstcLCD, 0xFFU);NT35510_WriteData(pstcLCD, 0x00U);NT35510_WriteData(pstcLCD, 0x00U);
}/*** @brief Set Cursor position.* @param [in] pstcLCD: LCD controller* @param u16Xpos: Specifies the X position.* @param u16Ypos: Specifies the Y position.* @retval None*/
void NT35510_SetCursor(stc_lcd_controller_t *pstcLCD, uint16_t u16Xpos, uint16_t u16Ypos)
{NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetXCmd);NT35510_WriteData(pstcLCD, (u16Xpos >> 8));NT35510_WriteData(pstcLCD, (u16Xpos & 0xFFU));NT35510_WriteReg(pstcLCD, m_stcLcdDevice.u16SetYCmd);NT35510_WriteData(pstcLCD, (u16Ypos >> 8));NT35510_WriteData(pstcLCD, (u16Ypos & 0xFFU));
}/*** @brief Write pixel.* @param [in] pstcLCD: LCD controller* @param u16Xpos: Specifies the X position.* @param u16Ypos: Specifies the Y position.* @param u16RGBCode: The RGB pixel color in RGB565 format* @retval None*/
void NT35510_WritePixel(stc_lcd_controller_t *pstcLCD, uint16_t u16Xpos, uint16_t u16Ypos, uint16_t u16RGBCode)
{/* Set cursor */NT35510_SetCursor(pstcLCD, u16Xpos, u16Ypos);/* Prepare to write to LCD RAM */NT35510_PrepareWriteRAM(pstcLCD);NT35510_WriteData(pstcLCD, u16RGBCode);
}/*** @brief Clear screen.* @param [in] pstcLCD: LCD controller* @param u16RGBCode: The RGB pixel color in RGB565 format* @retval None*/
void NT35510_Clear(stc_lcd_controller_t *pstcLCD, uint16_t u16RGBCode)
{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, u16RGBCode);}
}
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]);
}
}