【GD32F303红枫派使用手册】第二十六节 EXMC-液晶驱动实验

26.1 实验内容

通过本实验主要学习以下内容:

  • LCD显示原理
  • EXMC NOR/SRAM模式时序和8080并口时序
  • LCD显示控制

26.2 实验原理

使用MCU的EXMC外设实现8080并口时序,和TFT-LCD控制器进行通信,控制LCD显示图片、字符、色块等。

26.2.1 TFT-LCD介绍

薄膜晶体管液晶显示器(英语:Thin film transistor liquid crystal display,常简称为TFT-LCD)是多数液晶显示器的一种,它使用薄膜晶体管技术改善影象品质。虽然TFT-LCD被统称为LCD,不过它是种主动式矩阵LCD,被应用在电视、平面显示器及投影机上。

简单说,TFT-LCD面板可视为两片玻璃基板中间夹着一层液晶,上层的玻璃基板是彩色滤光片、而下层的玻璃则有晶体管镶嵌于上。当电流通过晶体管产生电场变化,造成液晶分子偏转,藉以改变光线的偏极性,再利用偏光片决定像素的明暗状态。此外,上层玻璃因与彩色滤光片贴合,形成每个像素各包含红蓝绿三颜色,这些发出红蓝绿色彩的像素便构成了面板上的视频画面。

为了对TFT-LCD的显示进行控制,需要通过接口和液晶屏通信,但所谓与液晶屏通信,实际上还是与液晶屏驱动控制芯片在通信,而主控制器需要按控制芯片支持的通信进行交互,通常有UART、IIC、SPI、8080、MIPI等各类接口。另外需要注意的一点是:一般支持普通MCU接口的LCD驱动芯片,都需要内置GRAM(Graphics RAM), 至少能存储一个屏幕的数据。

这这里,我们使用了8080接口通过并行总线传输控制命令和数据,并通过往LCD液晶模组自带的GRAM更新数据实现屏幕的刷新。

GD32F3红枫派开发板TFT-LCD如下图所示,采用了ILI9488 LCD驱动器,分辨率320*480,支持多种通信接口,在GD32F303xx上,适合使用16-bit Parallel MCU Interface接口进行通信,开发板配套的LCD模块也采用了该接口设计和开发板进行连接。

26.2.2 LCD 8080并口时序介绍(16-bit Parallel MCU Interface)

8080接口是由英特尔设计,是一种并行、异步、半双工通信协议,作用是用于外扩RAM、ROM,后面也用于LCD接口。并行接口又分为 8位/16位/24位 三种, 顾名思义,就是数据总线的位宽。

  • 如下图所示是16-bit Parallel MCU Interface的接口和MCU的连接信号:

  • 如下图所示是LCD驱动器 16BIT 8080并口读写时序:
  • CS拉低后,并口DATA IO在WR的上升沿被采样;
  • 可以理解为16线的SPI,而WR是写“CLK”,RD是读“CLK”;
  • 但这里还多了D/C引脚用于选择传输命令或数据

  • 8080接口的RGB颜色数据编码
  • 像素信息用RGB三原色表示,所以向液晶屏传输的数据帧主要也就是传输的RGB颜色数据。
  • 像素的颜色数据并不总是用 8R8G8B的24位真彩色 表示,共有下面几种表示情况:
  • 12-bits/pixel (R 4-bit, G 4-bit, B 4-bit), 4,096 Colors, 简称444;
  • 16-bits/pixel (R 5-bit, G 6-bit, B 5-bit), 65,536 Colors, 简称565;
  • 18-bits/pixel (R 6-bit, G 6-bit, B 6-bit), 262,144 Colors, 简称666;
  • 24-bits/pixel (R 8-bit, G 8-bit, B 8-bit), 16,777,216 Colors, 简称888;
    不同颜色表示方法和不同的总线位宽相组合,就会组合成多种RGB颜色数据编码。
  • 综合显示效果、内存资源开销等,我们采取了RGB565像素格式,这样16BIT 8080每次传输就是一个像素点的像素值,传输数据就为像素颜色值。

26.2.3 EXMC外设和EXMC NOR/SRAM模式实现8080时序

  • 这里我们使用EXMC中时序和接口类似的NOR/SRAM模式,来实现8080接口驱动TFT-LCD显示,EXMC外设可参考上文介绍东方红开发板使用手册 ,EXMC NOR/SRAM模式可参考上文介绍东方红开发板使用手册 
  • 这里我们使用SRAM模式异步模式A(扩展模式),时序如下图:

我们对比上面的时序和16-bit Data Bus 8080 LCD时序,发现一些信号的时序是类似的,我们可以将这些信号进行对应:

EXMC_NEx -> CSx

EXMC_NOE->RDx

EXMC_NWE->WR

EXMC_D[15:0]->DB[15:0]

EXMC_Ax->D/C

这里巧妙的是使用EXMC_Ax引脚实现D/C的数据/命令切换功能,所以我们只需要选择一个方便布线的EXMC_Ax引脚,然后在软件中对该引脚对应的EXMC逻辑地址进行操作就可以实现程序读写不同地址时,D/C引脚的状态切换,从而实现访问一个EXMC地址时是数据或命令类似,访问该地址位反向的任意地址就是另外一个类型。对于程序中逻辑地址的影响,除了Ax引脚的选择外还有NEx引脚的选择。NE[0]-NE[3]对应如下图的NOR/SRAM BANK下的Region0-Region3。

26.3 硬件设计

在红枫派开发板设计中,我们使用EXMC_NE1引脚作为CS,EXMC_A12引脚作为D/C,同时LCD触摸接口使用SPI,LCD_BL为背光控制引脚,这里的引脚选用了带PWM的引脚,可以实现LCD的背光亮度调节。

LCD在显示过程电源电流会有变化,为了稳定电源我们在3.3V和5V接口上使用了1uf电容。

26.4 代码解析

26.4.1 CSx、D/C、BL相关功能定义和注册;

在EXMC LCD驱动代码中存在和电路设计匹配的变更点,往往让开发者头大,需要详细阅读用户手册来进行配置调整、读写地址调整;而在我们的驱动文件bsp_lcd.c中定义注册背光引脚、Ax、NEx引脚,当硬件设计变更时只需要在这里调整,驱动就可以在新的硬件中正常使用。

C
//定义背光引脚的PWM通道和GPIO
TIMER_CH_DEF(LCD_BL,TIMER12,0,TIMER_CH_PWM_HIGH,F,8,AF_PP,GPIO_TIMER12_REMAP);//定义使用的EXMC_Ax引脚
#define EXMC_Ax  12
GPIO_DEF(EXMC_Ax_GPIO,G,2,AF_PP,SET,NULL);//定义使用的EXMC_NEx引脚
#define EXMC_NEx 1
GPIO_DEF(EXMC_NEx_GPIO,D,7,AF_PP,SET,NULL);//LCD数据、命令地址转换
#define EXMC_LCD_D  REG16(((uint32_t)(EXMC_BANK0_NORSRAM_REGIONx_ADDR(EXMC_NEx)))|BIT(EXMC_Ax)*2)
#define EXMC_LCD_C  REG16(((uint32_t)(EXMC_BANK0_NORSRAM_REGIONx_ADDR(EXMC_NEx))))

26.4.2 gpio和exmc初始化:

exmc使用了扩展模式,这样读和写的时序可以单独配置,因为LCD对读和写的要求时间是不同的,读的时候速率不能太高,如果使用一种参数类型就会为了满足读的要求而降低写的速率,影响最终刷屏的性能。这里主要调整读和写时的地址建立、数据建立时间,通常和硬件设计也有较大关系,这里红枫派开发板和配套LCD的电路可以在120M主频下,设置读数据建立5个clk、地址建立1个clk,写数据建立2个clk,地址建立1个clk。

C
/*!
* 说明     emxc LCD模式通用gpio初始化
* 输入[1]  norsram_region: @EXMC_BANK0_NORSRAM_REGION0/EXMC_BANK0_NORSRAM_REGION1/EXMC_BANK0_NORSRAM_REGION2/EXMC_BANK0_NORSRAM_REGION3
* 返回值   无
*/
void driver_exmc_lcd_16bit_gpio_init(void)
{/* EXMC clock enable */rcu_periph_clock_enable(RCU_EXMC);/* GPIO clock enable */rcu_periph_clock_enable(RCU_GPIOD);rcu_periph_clock_enable(RCU_GPIOE);rcu_periph_clock_enable(RCU_GPIOG);rcu_periph_clock_enable(RCU_AF);    /* configure EXMC_D[0~15]*//* PD14(EXMC_D0), PD15(EXMC_D1),PD0(EXMC_D2), PD1(EXMC_D3), PD8(EXMC_D13), PD9(EXMC_D14), PD10(EXMC_D15) */gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0 | GPIO_PIN_1| GPIO_PIN_8 | GPIO_PIN_9 |GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);/* PE7(EXMC_D4), PE8(EXMC_D5), PE9(EXMC_D6), PE10(EXMC_D7), PE11(EXMC_D8), PE12(EXMC_D9), PE13(EXMC_D10), PE14(EXMC_D11), PE15(EXMC_D12) */gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);//    /* configure PE2(EXMC_Ax) */ 
//    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2);/* configure NOE and NWE */gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_4 | GPIO_PIN_5);//    /* configure EXMC NEx */
//    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_7);gpio_compensation_config(GPIO_COMPENSATION_ENABLE);while(gpio_compensation_flag_get()==RESET);
}/*!
* 说明     emxc LCD模式初始化
* 输入[1]  norsram_region: @EXMC_BANK0_NORSRAM_REGION0/EXMC_BANK0_NORSRAM_REGION1/EXMC_BANK0_NORSRAM_REGION2/EXMC_BANK0_NORSRAM_REGION3
* 返回值   无
*/
void driver_exmc_lcd_init(uint32_t norsram_region)
{exmc_norsram_parameter_struct nor_init_struct;exmc_norsram_timing_parameter_struct nor_timing_read_init_struct;exmc_norsram_timing_parameter_struct nor_timing_write_init_struct;/* EXMC clock enable */rcu_periph_clock_enable(RCU_EXMC);nor_init_struct.read_write_timing = &nor_timing_read_init_struct;nor_init_struct.write_timing = &nor_timing_write_init_struct;    exmc_norsram_struct_para_init(&nor_init_struct);/* config timing parameter */nor_timing_read_init_struct.asyn_access_mode = EXMC_ACCESS_MODE_A;nor_timing_read_init_struct.syn_data_latency = EXMC_DATALAT_2_CLK;nor_timing_read_init_struct.syn_clk_division = EXMC_SYN_CLOCK_RATIO_2_CLK;nor_timing_read_init_struct.bus_latency = 1;nor_timing_read_init_struct.asyn_data_setuptime = 5;nor_timing_read_init_struct.asyn_address_holdtime = 1;nor_timing_read_init_struct.asyn_address_setuptime = 1;/* config timing parameter */nor_timing_write_init_struct.asyn_access_mode = EXMC_ACCESS_MODE_A;nor_timing_write_init_struct.syn_data_latency = EXMC_DATALAT_2_CLK;nor_timing_write_init_struct.syn_clk_division = EXMC_SYN_CLOCK_RATIO_2_CLK;nor_timing_write_init_struct.bus_latency = 1;nor_timing_write_init_struct.asyn_data_setuptime = 2;nor_timing_write_init_struct.asyn_address_holdtime = 1;nor_timing_write_init_struct.asyn_address_setuptime = 1;    /* config EXMC bus parameters */nor_init_struct.norsram_region = norsram_region;nor_init_struct.write_mode = EXMC_ASYN_WRITE;nor_init_struct.extended_mode = ENABLE;nor_init_struct.asyn_wait = DISABLE;nor_init_struct.nwait_signal = DISABLE;nor_init_struct.memory_write = ENABLE;nor_init_struct.nwait_config = EXMC_NWAIT_CONFIG_BEFORE;nor_init_struct.wrap_burst_mode = DISABLE;nor_init_struct.nwait_polarity = EXMC_NWAIT_POLARITY_LOW;nor_init_struct.burst_mode = DISABLE;nor_init_struct.databus_width = EXMC_NOR_DATABUS_WIDTH_16B;nor_init_struct.memory_type = EXMC_MEMORY_TYPE_SRAM;nor_init_struct.address_data_mux = DISABLE;exmc_norsram_init(&nor_init_struct);/* enable the EXMC bank0 NORSRAM */exmc_norsram_enable(norsram_region);  
}

 26.4.3 LCD数据、命令读写:

LCD的命令、数据的读写都通过EXMC来实现,在读写EXMC的逻辑地址时对应的波形会发送到LCD上,命令/数据目前通过地址引脚控制,所以我们需要定义两个地址分别对应命令、数据地址,对这两个地址读和写就可以实现LCD读写数据、写命令功能。

C
/*** 说明       LCD写数据* 输入       data: 要写入的数据* 返回值      无*/
void bsp_lcd_wr_data(__IO uint16_t data)
{//delay_sysclk(1);            EXMC_LCD_D = data;
}/*** 说明       LCD写寄存器编号/地址函数* 输入       regno: 寄存器编号/地址* 返回值      无*/
void bsp_lcd_wr_regno(__IO uint16_t regno)
{//delay_sysclk(1);        EXMC_LCD_C = regno;   /* 写入要写的寄存器序号 */
}/*** 说明       LCD写寄存器* 输入       regno:寄存器编号/地址* 输入       data:要写入的数据* 返回值      无*/
void bsp_lcd_write_reg(__IO uint16_t regno,__IO uint16_t data)
{//delay_sysclk(1);     EXMC_LCD_C = regno;   /* 写入要写的寄存器序号 *///delay_sysclk(1);     EXMC_LCD_D = data;    /* 写入数据 */
}/*** 说明       LCD读数据* 输入       无* 返回值      读取到的数据*/
static uint16_t bsp_lcd_read_data(void)
{//delay_sysclk(1);return EXMC_LCD_D;
}

26.4.4 LCD初始化

LCD初始化序列通常LCD驱动器厂家会提供相关寄存器配置,为了兼容不同的LCD,可以读取LCD ID后执行不同的驱动芯片初始化,初始化过程的寄存器配置就通过25.4.3章节实现的命令、数据读写接口实现:

C
/*** 说明       初始化LCD*   @note      该初始化函数可以初始化各种型号的LCD(详见本.c文件最前面的描述)** 输入       无* 返回值      无*/
uint32_t bsp_lcd_init(void)
{bsp_lcd_port_init();bsp_lcd_backlight_duty_set(BACK_LIGHT_DUTY);bsp_lcd_backlight_on();          /* 点亮背光 */    /* LCD的画笔颜色和背景色 */bsp_lcd_parameter.g_point_color = WHITE;    /* 画笔颜色 */bsp_lcd_parameter.g_back_color  = BLACK;    /* 背景色 */    delay_ms(1);     /* 初始化FSMC后,必须等待一定时间才能开始初始化 *//* 尝试9341 ID的读取 */bsp_lcd_wr_regno(0XD3);bsp_lcd_parameter.id = bsp_lcd_read_data();  /* dummy read */bsp_lcd_parameter.id = bsp_lcd_read_data();  /* 读到0X00 */bsp_lcd_parameter.id = bsp_lcd_read_data();  /* 读取0X93 */bsp_lcd_parameter.id <<= 8;bsp_lcd_parameter.id |= bsp_lcd_read_data(); /* 读取0X41 */if (bsp_lcd_parameter.id == 0X9488){lcd_ex_ili9488_reginit();   /* 执行ILI9388初始化 */}     else if (bsp_lcd_parameter.id == 0X9341){lcd_ex_ili9341_reginit();   /* 执行ILI9341初始化 */}else{return DRV_ERROR;}bsp_lcd_display_dir(0); /* 默认为竖屏 */bsp_lcd_clear(WHITE);return DRV_SUCCESS;
}/*** @brief       ILI9488寄存器初始化代码* @param       无* @retval      无*/
void lcd_ex_ili9488_reginit(void)
{//************* Start Initial Sequence **********//bsp_lcd_wr_regno(0XF7);            bsp_lcd_wr_data(0xA9);         bsp_lcd_wr_data(0x51);         bsp_lcd_wr_data(0x2C);         bsp_lcd_wr_data(0x82);bsp_lcd_wr_regno(0XEC);            bsp_lcd_wr_data(0x00);         bsp_lcd_wr_data(0x02);         bsp_lcd_wr_data(0x03);         bsp_lcd_wr_data(0x7A);bsp_lcd_wr_regno(0xC0);         bsp_lcd_wr_data(0x13);         bsp_lcd_wr_data(0x13);         bsp_lcd_wr_regno(0xC1);         bsp_lcd_wr_data(0x41);         bsp_lcd_wr_regno(0xC5);         bsp_lcd_wr_data(0x00);         bsp_lcd_wr_data(0x28);         bsp_lcd_wr_data(0x80);bsp_lcd_wr_regno(0xB1);   //Frame rate 70HZ          bsp_lcd_wr_data(0xB0);bsp_lcd_wr_data(0x11);        bsp_lcd_wr_regno(0xB4);         bsp_lcd_wr_data(0x02);           bsp_lcd_wr_regno(0xB6); //RGB/MCU Interface Control        bsp_lcd_wr_data(0x02);   //MCU        bsp_lcd_wr_data(0x22); bsp_lcd_wr_regno(0xB7);         bsp_lcd_wr_data(0xc6); bsp_lcd_wr_regno(0xBE);         bsp_lcd_wr_data(0x00); bsp_lcd_wr_data(0x04);        bsp_lcd_wr_regno(0xE9);         bsp_lcd_wr_data(0x00);bsp_lcd_wr_regno(0xF4);         bsp_lcd_wr_data(0x00); bsp_lcd_wr_data(0x00);bsp_lcd_wr_data(0x0f);        bsp_lcd_wr_regno(0xE0);         bsp_lcd_wr_data(0x00);         bsp_lcd_wr_data(0x04);         bsp_lcd_wr_data(0x0E);         bsp_lcd_wr_data(0x08);         bsp_lcd_wr_data(0x17);         bsp_lcd_wr_data(0x0A);         bsp_lcd_wr_data(0x40);         bsp_lcd_wr_data(0x79);         bsp_lcd_wr_data(0x4D);         bsp_lcd_wr_data(0x07);         bsp_lcd_wr_data(0x0E);         bsp_lcd_wr_data(0x0A);         bsp_lcd_wr_data(0x1A);         bsp_lcd_wr_data(0x1D);         bsp_lcd_wr_data(0x0F);          bsp_lcd_wr_regno(0xE1);         bsp_lcd_wr_data(0x00);         bsp_lcd_wr_data(0x1B);         bsp_lcd_wr_data(0x1F);         bsp_lcd_wr_data(0x02);         bsp_lcd_wr_data(0x10);         bsp_lcd_wr_data(0x05);         bsp_lcd_wr_data(0x32);         bsp_lcd_wr_data(0x34);         bsp_lcd_wr_data(0x43);         bsp_lcd_wr_data(0x02);         bsp_lcd_wr_data(0x0A);         bsp_lcd_wr_data(0x09);         bsp_lcd_wr_data(0x33);         bsp_lcd_wr_data(0x37);         bsp_lcd_wr_data(0x0F); bsp_lcd_wr_regno(0xF4);      bsp_lcd_wr_data(0x00);bsp_lcd_wr_data(0x00);bsp_lcd_wr_data(0x0f);        bsp_lcd_wr_regno(0x36);         bsp_lcd_wr_data(0x08);         bsp_lcd_wr_regno(0x3A);  //Interface Mode Control        bsp_lcd_wr_data(0x55);  //0x66 18bit; 0x55 16bit                        bsp_lcd_wr_regno(0x20);         bsp_lcd_wr_regno(0x11);         delay_ms(120);         bsp_lcd_wr_regno(0x29);         delay_ms(50); } 

26.4.5 LCD画点函数实现

LCD在任意点显示想要的颜色值,需要设置显示光标到目标位置,然后就可以从该光标进行颜色数据写入,颜色信息将显示到LCD的指定坐标上。

C
/*** 说明       画点* 输入       x,y: 坐标* 输入       color: 点的颜色(32位颜色,方便兼容LTDC)* 返回值      无*/
void bsp_lcd_draw_point(uint16_t x, uint16_t y, uint32_t color)
{bsp_lcd_set_cursor(x, y);       /* 设置光标位置 */EXMC_LCD_C = bsp_lcd_parameter.wramcmd;    /* 开始写入GRAM */EXMC_LCD_D = color;
}

26.4.6 窗口设置和色块填充

LCD可以设置需显示的窗口,设置窗口后可以连续的写数据,像素信息会从窗口起始坐标开始自动递增和换行显示颜色。通过图块设置函数可以显示图片,移植到GUI等;这里我们通过DMA的MEM TO MEM模式可以降低色块填充过程的CPU占用率,同时提升刷屏速率。

C
/*** 说明       在指定区域内填充指定颜色块* 输入       (sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex - sx + 1) * (ey - sy + 1)* 输入       color: 要填充的颜色数组首地址* 返回值      无*/
void bsp_lcd_color_fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color)
{uint16_t height, width;
//    uint32_t i;width = ex - sx + 1;            /* 得到填充的宽度 */height = ey - sy + 1;           /* 高度 */bsp_lcd_set_window(sx,sy,width,height);EXMC_LCD_C = bsp_lcd_parameter.wramcmd;driver_dma_mem_to_exmclcd_start((void*)&EXMC_LCD_D,&color[0],DMA_Width_16BIT,height*width);     
//    for(uin32_t i = 0; i < height*width; i++)
//    {
//        EXMC_LCD_D = color[i];     
//    }
}

26.4.7 字符显示和LCD Printf

实现上述功能后,通过字库信息结合打点函数就可以实现字符的显示,我们同时实现了在lcd上打印信息,以printf的形式更轻易便捷的输出信息到LCD上。

C
/*** 说明       LCD打印* 输入       ...和printf相同用法,自动换行* 返回值      无*/
void bsp_lcd_printf(const char * sFormat, ...) 
{char printf_buffer[64];char* p=printf_buffer;uint16_t len=0,count=0;va_list ParamList;va_start(ParamList, sFormat);    vsprintf(printf_buffer,sFormat, ParamList);     va_end(ParamList); len=strlen(printf_buffer);    while( ( ((*p <= '~') && (*p >= ' ')) || (*p =='\r') || (*p =='\n') ) && (count<len) )   /* 判断是不是非法字符! */{if((*p =='\r')){bsp_lcd_pritnf_parameter.x_now = bsp_lcd_pritnf_parameter.x_start;}        else if((*p =='\n')){bsp_lcd_pritnf_parameter.y_now += bsp_lcd_pritnf_parameter.size; bsp_lcd_fill(bsp_lcd_pritnf_parameter.x_now,bsp_lcd_pritnf_parameter.y_now,bsp_lcd_pritnf_parameter.x_end,bsp_lcd_pritnf_parameter.y_now+bsp_lcd_pritnf_parameter.size,bsp_lcd_pritnf_parameter.back_color);            }else if( (bsp_lcd_pritnf_parameter.x_now + bsp_lcd_pritnf_parameter.size/2) > bsp_lcd_pritnf_parameter.x_end){bsp_lcd_pritnf_parameter.x_now = bsp_lcd_pritnf_parameter.x_start;bsp_lcd_pritnf_parameter.y_now += bsp_lcd_pritnf_parameter.size;bsp_lcd_fill(bsp_lcd_pritnf_parameter.x_now,bsp_lcd_pritnf_parameter.y_now,bsp_lcd_pritnf_parameter.x_end,bsp_lcd_pritnf_parameter.y_now+bsp_lcd_pritnf_parameter.size,bsp_lcd_pritnf_parameter.back_color);                        }else if ( (bsp_lcd_pritnf_parameter.y_now+bsp_lcd_pritnf_parameter.size) > bsp_lcd_pritnf_parameter.y_end){bsp_lcd_pritnf_parameter.x_now = bsp_lcd_pritnf_parameter.x_start;bsp_lcd_pritnf_parameter.y_now = bsp_lcd_pritnf_parameter.y_start;            bsp_lcd_fill(bsp_lcd_pritnf_parameter.x_start,bsp_lcd_pritnf_parameter.y_start,bsp_lcd_pritnf_parameter.x_end,bsp_lcd_pritnf_parameter.y_end,bsp_lcd_pritnf_parameter.back_color);}if((*p !='\r')&&(*p !='\n')){bsp_lcd_show_char(bsp_lcd_pritnf_parameter.x_now, bsp_lcd_pritnf_parameter.y_now, *p, bsp_lcd_pritnf_parameter.size, 0, bsp_lcd_pritnf_parameter.point_color,bsp_lcd_pritnf_parameter.back_color);bsp_lcd_pritnf_parameter.x_now += bsp_lcd_pritnf_parameter.size / 2;            }p++;count++;}}

26.5 实验结果

复位后显示聚沃和GD LOG图片,大字显示LCD ID,刷屏时间、聚沃相关链接地址等。在下方设置了一个printf区窗口,循环打印亮度信息和系统tic信息。左右波动摇杆可以调节LCD亮度。

由聚沃科技原创,来源于

 【红枫派开发板】第二十六讲 EXMC-液晶驱动实验 - 苏州聚沃电子科技有限公司 (gd32bbs.com)

  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/35397.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图像超分辨率重建

一、什么是图像超分辨 图像超分辨是一种技术&#xff0c;旨在通过硬件或软件的方法提高原有图像的分辨率。这一过程涉及从一系列低分辨率的图像中获取一幅高分辨率的图像&#xff0c;实现了时间分辨率向空间分辨率的转换。超分辨率重建的核心思想是利用多帧图像序列的时间带宽来…

计算机毕业设计Thinkphp/Laravel学生考勤管理系统zyoqy

管理员登录学生考勤管理系统后&#xff0c;可以对首页、个人中心、公告信息管理、年级管理、专业管理、班级管理、学生管理、教师管理、课程信息管理、学生选课管理、课程签到管理、请假申请管理、销假申请管理等功能进行相应操作&#xff0c;如图5-2所示。学生登录进入学生考勤…

【Spine学习16】之 人物面部绑定

1、创建头部骨骼 一根头骨 以头骨为父结点创建一个面部控制器face-holder 2、创建头发和face面部控制结点的变换约束 左右头发的约束指向为face结点 3、设定后发的变换约束&#xff0c;约束指向为face结点&#xff0c;反方向移动 设置参数为-100 同理&#xff0c;耳朵也依…

【Python时序预测系列】基于CNN+Bi-LSTM实现单变量时间序列预测(案例+源码)

这是我的第309篇原创文章。 一、引言 基于CNN&#xff08;卷积神经网络&#xff09;和Bi-LSTM&#xff08;双向长短期记忆网络&#xff09;的单变量时间序列预测是一种结合空间特征提取和时间依赖建模的方法。以下是一个基于Python和TensorFlow/Keras实现的示例&#xff0c;展…

YOLOv8改进 | 主干网络| 可变形卷积网络C2f_DCN【CVPR2017】

&#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录&#xff1a;《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有40篇内容&#xff0c;内含各种Head检测头、损失函数Loss、B…

SiLM585x系列SiLM5851NHCG-DG一款具有分离的管脚输出 单通道隔离驱动器 拥有强劲的驱动能力

SiLM585x系列SiLM5851NHCG-DG是一款单通道隔离驱动器&#xff0c;具有分离的管脚输出&#xff0c;提供3.0A源电流和6.0A灌电流。主动保护功能包括退饱和过流检测、UVLO、隔离故障报警和 2.5A 米勒钳位。输入侧电源的工作电压为3V至5.5V&#xff0c;输出侧电源的工作电压范围为1…

小柴冲刺嵌入式系统设计师系列总目录

工作两年 逐渐意识到基础知识的重要性✌️ 意识到掌握了这个证书好像就已经掌握了80%工作中用到的知识了。剩下的就在工作的实战中学习 来和小柴一起冲刺软考吧&#xff01;加油&#x1f61c; 【小柴冲刺软考中级嵌入式系统设计师系列】总目录 前言 专栏目标&#xff1a;冲刺…

涵盖多项功能的文件外发系统,了解一下

伴随着业务范围的不断扩大&#xff0c;信息化的迅速发展&#xff0c;企业与客户、供应商等合作伙伴之间的文件交换也愈加频繁&#xff0c;尤其涉及到核心数据&#xff0c;像核心技术、设计图纸等敏感数据&#xff0c;对其的保护也是越发重视。文件外发系统&#xff0c;应运而生…

Linux基础 - RAID 与 LVM 磁盘阵列技术

目录 零. 简介 一. RAID 二. LVM 三. 总结 零. 简介 在 Linux 中&#xff0c;RAID&#xff08;Redundant Array of Independent Disks&#xff0c;独立磁盘冗余阵列&#xff09;和 LVM&#xff08;Logical Volume Manager&#xff0c;逻辑卷管理器&#xff09;是两种常用的…

机械继电器、固态继电器和模拟开关对比分析

1 结构 2 长期可靠性 与机械继电器相比&#xff0c;光继电器明显提高了可靠性&#xff0c;因为没有活动器件。 光继电器通过 LED 进行光学控制。通常情况下&#xff0c;此 LED 会随着时间的推移比开关本身更快地降级&#xff0c;具体取决于温度、正向电流、开关速度等。随着 LE…

群辉NAS使用Kodi影视墙

目录 一、KODI安装 二、修改UI语言 1、修改显示字体 2、修改语言为中文 四、添加媒体库 五、观看电影 五、高级设置 1、视图类型 2、修改点击播动作 五、补充 1、文件组织结构及命名 2、电影信息的刮削 (1)添加影片 (2)演员管理 (3)影片管理 (4)说明 K…

基于opencv的图像拼接

利用Python的OpenCV库实现了简单的图像拼接&#xff0c;示例 1. 图像拼接的基本原理 图像拼接主要包括以下几个步骤&#xff1a; 特征检测与匹配&#xff1a;首先&#xff0c;需要在待拼接的图像之间找到匹配的关键点或特征。OpenCV提供了如SIFT、SURF、ORB等特征提取器以及…

嵌入式EMC之TVS管

整理一些网上摘抄的笔记&#xff1a; TVS管认识&#xff1a; TVS的Vc要比&#xff0c;DCDC的最大承受电压要小

web前端大作业--美团外卖1

文章目录 概述代码截图代码链接 概述 web美团 登录和注册功能、页面展示。 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><link rel"stylesheet" href&quo…

Vue组件生命周期深度剖析:从创建到销毁的八大钩子实战指南

系列文章目录 Vue核心指令解析&#xff1a;探索MVVM与数据操作之美 文章目录 系列文章目录前言一、Vue生命周期是什么&#xff1f;二、钩子函数讲解1. beforeCreate( 创建前 )2. created ( 创建后 &#xff09;3. beforeMount&#xff08;挂载前&#xff09;4. mounted&#xf…

Redis-数据类型-Geospatial(地理空间索引)

文章目录 1、查看redis是否启动2、通过客户端连接redis3、切换到db5数据库4、将地理位置信息&#xff08;经度和纬度&#xff09;添加到 Redis 的键&#xff08;key&#xff09;中4.1、添加大江商厦4.2、添加西部硅谷 5、升序返回有序集key&#xff0c;让分数一起和值返回的结果…

简约的服务器监控工具Ward

什么是 Ward &#xff1f; Ward 是一个简单简约的服务器监控工具。 Ward 支持自适应设计系统。此外&#xff0c;它还支持深色主题。它仅显示主要信息&#xff0c;如果您想查看漂亮的仪表板而不是查看一堆数字和图表&#xff0c;则可以使用它。 Ward 在所有流行的操作系统上都能…

Redis缓存机制详解(数据淘汰策略、缓存击穿、缓存穿透、缓存雪崩)

Redis缓存机制详解 Redis 作为一个高效的内存数据库&#xff0c;常用于缓存系统。 其缓存机制有助于提高数据访问速度、减轻后端数据库压力。 由于 Redis 是基于内存的数据库&#xff0c;内存资源有限&#xff0c;因此需要有合理的数据淘汰策略以管理内存使用。 1. 内存数据淘…

解决chrome浏览器总是将对站点的http访问改为https的问题

问题&#xff1a;vue项目本地运行出来的地址是http开头的&#xff0c;但在chrome浏览器中无法访问&#xff0c;在Edge浏览器就可以&#xff0c;发现是chrome总是自动将http协议升级为https。 已试过的有效的方法&#xff1a; 一、无痕模式下访问 无痕模式下访问不会将http自…

java基于ssm+jsp 超市进销存管理系统

1前台首页功能模块 宜佰丰超市进销存管理系统&#xff0c;在系统首页可以查看首页、商品信息、新闻资讯、留言反馈、我的、跳转到后台、购物车等内容&#xff0c;如图1所示。 图1前台首页功能界面图 用户注册&#xff0c;在用户注册页面可以填写用户名、密码、姓名、联系电话、…