
为智能语音设备点亮“视界”:我在启英泰伦CI230X上成功驱动LCD屏
1. 芯片介绍
CI230X系列芯片是启英泰伦研发的新一代高性能神经网络智能语音芯片,集成了启英泰伦自研的脑神经网络处理器BNPU V3和CPU内核,以及Wi-Fi和BLE的Combo功能。系统主频可达220MHz,内置大容量SRAM,集成PMU电源管理单元、双通道高性能低功耗Audio Codec和多路UART、IIC、IIS、PWM、SPI等外围控制接口。
芯片支持2.4 GHz 802.11 b/g/n Wi-Fi及 BLE 5.1 无线通信协议,仅需少量电阻电容等外围器件就可以实现各类智能语音离在线产品硬件方案,性价比极高。
2. 准备工作
CI-E0XGT03S_MB开发板,参考文档:CI-E0XGT03S_MB开发板套件说明 - 启英泰伦文档中心
显示屏:2.4寸,SPI接口,分辨率320*240。链接:2.4寸触摸显示屏LCD液晶屏SPI接口MCU8080接口带电容TP触摸 LVGL-淘宝网
SDK:请从启英泰伦 语音AI开发平台 获取。链接:资料库
3. 硬件介绍
LCD屏幕介绍
本文采用的是一款4-SPI接口IPS屏,分辨率为320*240。规格定义如下:



开发板屏接口

开发板GPIO与 屏幕接口对应关系如下:
开发板GPIO |
屏接口 |
PF3 |
BLK |
PF4 |
DC |
PF5 |
MOSI |
PF6 |
SCLK |
PF7 |
CS |
PF8 |
RES |
GND |
GND |
3V3 |
3V3 |
PE1 |
TP_RES |
PE4 |
TP_INT |
PE6 |
TP_SCL |
PE7 |
TP_SDA |
4. 软件配置
GPIO及SPI配置
根据开发板GPIO与屏幕接口对应关系修改ln_drv_spi_lcd.c文件中的GPIO及SPI配置。如下:
/* 配置SPI CS引脚 */
#define LN_SPI_LCD_TEST_CS_PORT_BASE GPIOB_BASE
#define LN_SPI_LCD_TEST_CS_PIN GPIO_PIN_7
#define LN_SPI_LCD_CS_LOW hal_gpio_pin_reset(LN_SPI_LCD_TEST_CS_PORT_BASE, LN_SPI_LCD_TEST_CS_PIN)
#define LN_SPI_LCD_CS_HIGH hal_gpio_pin_set(LN_SPI_LCD_TEST_CS_PORT_BASE, LN_SPI_LCD_TEST_CS_PIN)
/* 配置 DC 引脚 */
#define LN_SPI_LCD_DC_LOW hal_gpio_pin_reset(GPIOB_BASE, GPIO_PIN_4)
#define LN_SPI_LCD_DC_HIGH hal_gpio_pin_set(GPIOB_BASE, GPIO_PIN_4)
/* 配置 RST 引脚 */
#define LN_SPI_LCD_RST_LOW hal_gpio_pin_reset(GPIOB_BASE, GPIO_PIN_8)
#define LN_SPI_LCD_RST_HIGH hal_gpio_pin_set(GPIOB_BASE, GPIO_PIN_8)
void spi_lcd_hardware_init()
{
/*SPI INIT*/
/* 1. 配置引脚*/
hal_gpio_pin_afio_select(GPIOB_BASE, GPIO_PIN_6, SPI0_CLK);
hal_gpio_pin_afio_select(GPIOB_BASE, GPIO_PIN_5, SPI0_MOSI);
hal_gpio_pin_afio_en(GPIOB_BASE, GPIO_PIN_5, HAL_ENABLE);
hal_gpio_pin_afio_en(GPIOB_BASE, GPIO_PIN_6, HAL_ENABLE);
//配置CS引脚
gpio_init_t\_def gpio_init;
memset(&gpio_init, 0, sizeof(gpio_init));
gpio_init.dir = GPIO_OUTPUT;
gpio_init.pin = LN_SPI_LCD_TEST_CS_PIN;
gpio_init.speed = GPIO_HIGH_SPEED;
hal_gpio_init(LN_SPI_LCD_TEST_CS_PORT_BASE, &gpio_init);
hal_gpio_pin_set(LN_SPI_LCD_TEST_CS_PORT_BASE, LN_SPI_LCD_TEST_CS_PIN);
//配置DC引脚
gpio_init.pin = GPIO_PIN_4;
hal_gpio_init(GPIOB_BASE, &gpio_init);
hal_gpio_pin_set(GPIOB_BASE, GPIO_PIN_4);
//配置RST引脚
gpio_init.pin = GPIO_PIN_8;
hal_gpio_init(GPIOB_BASE, &gpio_init);
hal_gpio_pin_set(GPIOB_BASE, GPIO_PIN_8);
/* 2. 配置SPI */
spi_init_type_def spi_init;
memset(&spi_init, 0, sizeof(spi_init));
spi_init.spi_baud_rate_prescaler = SPI_BAUDRATEPRESCALER_2; //设置波特率
spi_init.spi_mode = SPI_MODE_MASTER; //设置主从模式
spi_init.spi_data_size = SPI_DATASIZE_8B; //设置数据大小
spi_init.spi_first_bit = SPI_FIRST_BIT_MSB; //设置帧格式
spi_init.spi_cpol = SPI_CPOL_LOW; //设置时钟极性
spi_init.spi_cpha = SPI_CPHA_1EDGE; //设置时钟相位
hal_spi_init(SPI0_BASE, &spi_init); //初始化SPI
hal_spi_en(SPI0_BASE, HAL_ENABLE); //SPI使能
hal_spi_ssoe_en(SPI0_BASE, HAL_DISABLE); //关闭CS OUTPUT
/* init the spi rx dma */
dma_init_t\_def dma_init;
memset(&dma_init, 0, sizeof(dma_init));
dma_init.dma_mem_addr = (uint32_t)0; //设置DMA内存地址
dma_init.dma_data_num = 0; //设置DMA传输次数
dma_init.dma_dir = DMA_READ_FORM_P; //设置DMA方向
dma_init.dma_mem_inc_en = DMA_MEM_INC_EN; //设置DMA内存是否增长
dma_init.dma_p\_addr = SPI0_DATA_REG; //设置DMA外设地址
dma_init.dma_p\_size = DMA_P\_SIZE_16_BIT;
dma_init.dma_mem_size = DMA_MEM_SIZE_16_BIT;
hal_dma_init(DMA_CH_3, &dma_init); //初始化DMA
/* init the spi tx dma */
memset(&dma_init, 0, sizeof(dma_init));
dma_init.dma_mem_addr = (uint32_t)0; //设置DMA内存地址
dma_init.dma_data_num = 0; //设置DMA传输次数
dma_init.dma_dir = DMA_READ_FORM_MEM; //设置DMA方向
dma_init.dma_mem_inc_en = DMA_MEM_INC_EN; //设置DMA内存是否增长
dma_init.dma_p\_addr = SPI0_DATA_REG; //设置DMA外设地址
dma_init.dma_p\_size = DMA_P\_SIZE_16_BIT;
dma_init.dma_mem_size = DMA_MEM_SIZE_16_BIT;
hal_dma_init(DMA_CH_4, &dma_init); //初始化DMA
hal_dma_en(DMA_CH_4, HAL_DISABLE); //DMA使能
hal_dma_en(DMA_CH_3, HAL_DISABLE); //DMA使能
hal_spi_dma_en(SPI0_BASE, SPI_DMA_RX_EN, HAL_DISABLE); //SPI DMA RX 使能
hal_spi_dma_en(SPI0_BASE, SPI_DMA_TX_EN, HAL_DISABLE); //SPI DMA TX 使能
}
修改屏幕初始化代码
屏幕厂家一般会提供如下初始化代码:
RES=1;
Delayms(5);
RES=0;
Delayms(10);
RES=1;
Delayms(120);
/************* Start Initial Sequence **********/
Writecom(0x11);
Delayms(120); //ms
Writecom(0x36);
Writedat(0x00);
Writecom(0x3A);
Writedat(0x55);
Writecom(0xB2);
Writedat(0x0C);
Writedat(0x0C);
Writedat(0x00);
Writedat(0x33);
Writedat(0x33);
Writecom(0xB7);
Writedat(0x56);
Writecom(0xBB);
Writedat(0x20);
Writecom(0xC0);
Writedat(0x2C);
Writecom(0xC2);
Writedat(0x01);
Writecom(0xC3);
Writedat(0x0F);
Writecom(0xC4);
Writedat(0x20);
Writecom(0xC6);
Writedat(0x0F);
Writecom(0xD0);
Writedat(0xA4);
Writedat(0xA1);
Writecom(0xD6);
Writedat(0xA1);
Writecom(0xE0);
Writedat(0xF0);
Writedat(0x00);
Writedat(0x06);
Writedat(0x06);
Writedat(0x07);
Writedat(0x05);
Writedat(0x30);
Writedat(0x44);
Writedat(0x48);
Writedat(0x38);
Writedat(0x11);
Writedat(0x10);
Writedat(0x2E);
Writedat(0x34);
Writecom(0xE1);
Writedat(0xF0);
Writedat(0x0A);
Writedat(0x0E);
Writedat(0x0D);
Writedat(0x0B);
Writedat(0x27);
Writedat(0x2F);
Writedat(0x44);
Writedat(0x47);
Writedat(0x35);
Writedat(0x12);
Writedat(0x12);
Writedat(0x2C);
Writedat(0x32);
Writecom(0x21);
Writecom(0x29);
将此初始化代码放到ln_drv_spi_lcd.c中spi_lcd_init函数中,并修改RES、Delayms、Writecom、Writedat为SDK中相应接口,如下:
LN_SPI_LCD_RST_HIGH;
ln_delay_ms(5);
LN_SPI_LCD_RST_LOW;
ln_delay_ms(10);
LN_SPI_LCD_RST_HIGH;
ln_delay_ms(120);
/**************StartInitialSequence*************/
spi_lcd_write_cmd(0x11);
ln_delay_ms(120);//ms
spi_lcd_write_cmd(0x36);
// spi_lcd_write_u8_data(0x00);
spi_lcd_write_u8_data(0x60);
spi_lcd_write_cmd(0x3A);
spi_lcd_write_u8_data(0x55);
spi_lcd_write_cmd(0xB2);
spi_lcd_write_u8_data(0x0C);
spi_lcd_write_u8_data(0x0C);
spi_lcd_write_u8_data(0x00);
spi_lcd_write_u8_data(0x33);
spi_lcd_write_u8_data(0x33);
spi_lcd_write_cmd(0xB7);
spi_lcd_write_u8_data(0x56);
spi_lcd_write_cmd(0xBB);
spi_lcd_write_u8_data(0x20);
spi_lcd_write_cmd(0xC0);
spi_lcd_write_u8_data(0x2C);
spi_lcd_write_cmd(0xC2);
spi_lcd_write_u8_data(0x01);
spi_lcd_write_cmd(0xC3);
spi_lcd_write_u8_data(0x0F);
spi_lcd_write_cmd(0xC4);
spi_lcd_write_u8_data(0x20);
spi_lcd_write_cmd(0xC6);
spi_lcd_write_u8_data(0x0F);
spi_lcd_write_cmd(0xD0);
spi_lcd_write_u8_data(0xA4);
spi_lcd_write_u8_data(0xA1);
spi_lcd_write_cmd(0xD6);
spi_lcd_write_u8_data(0xA1);
spi_lcd_write_cmd(0xE0);
spi_lcd_write_u8_data(0xF0);
spi_lcd_write_u8_data(0x00);
spi_lcd_write_u8_data(0x06);
spi_lcd_write_u8_data(0x06);
spi_lcd_write_u8_data(0x07);
spi_lcd_write_u8_data(0x05);
spi_lcd_write_u8_data(0x30);
spi_lcd_write_u8_data(0x44);
spi_lcd_write_u8_data(0x48);
spi_lcd_write_u8_data(0x38);
spi_lcd_write_u8_data(0x11);
spi_lcd_write_u8_data(0x10);
spi_lcd_write_u8_data(0x2E);
spi_lcd_write_u8_data(0x34);
spi_lcd_write_cmd(0xE1);
spi_lcd_write_u8_data(0xF0);
spi_lcd_write_u8_data(0x0A);
spi_lcd_write_u8_data(0x0E);
spi_lcd_write_u8_data(0x0D);
spi_lcd_write_u8_data(0x0B);
spi_lcd_write_u8_data(0x27);
spi_lcd_write_u8_data(0x2F);
spi_lcd_write_u8_data(0x44);
spi_lcd_write_u8_data(0x47);
spi_lcd_write_u8_data(0x35);
spi_lcd_write_u8_data(0x12);
spi_lcd_write_u8_data(0x12);
spi_lcd_write_u8_data(0x2C);
spi_lcd_write_u8_data(0x32);
spi_lcd_write_cmd(0x21);
spi_lcd_write_cmd(0x29);
自此,屏幕的驱动移植完成。
图片取模
若需要验证在屏幕上显示图片,可以通过图片取模软件将图片转换为数组的方式。
本文使用的图片取模工具为 STC-ISP 软件中的图片取模组件,设置如下:
扫描顺序:水平扫描,从左到右,从上到下
存储顺序:高位在前
数据格式:C表格格式
宽度:320
高度:240
输出格式:16位彩色-565
配置好后,导入提前准备好的320*240的图片,点击 开始转换,如下:


点击 复制数据,并将数据粘贴至ln_spi_lcd_pic.h中,并删除
#define IMG_WIDTH 320
#define IMG_HEIGHT 240
#define IMG_DEPTH 16
然后将数组名改为:gImage_pic
最后在main.c中增加图片显示函数,如下:
spi_lcd_show_picture(0, 0, 320, 240, gImage_pic);
至此软件配置完毕。
固件的编译可参考启英泰伦文档中心:开发环境搭建与使用 - 启英泰伦文档中心
固件的烧录可参考启英泰伦文档中心:CI-E0XGT03S_MB开发板套件说明 - 启英泰伦文档中心
5. 显示效果

6. 结语
通过本次实践,我们成功为启英泰伦CI230X语音芯片开发板驱动了SPI接口的LCD显示屏,让原本专注于语音交互的设备具备了视觉展示能力。这个过程不仅验证了CI230X芯片丰富的外设控制能力,也展示了其作为边缘计算平台的扩展潜力。
从硬件连接到软件配置,从GPIO初始化到SPI通信建立,再到屏幕初始化和图片取模显示,每一个步骤都是嵌入式开发中典型的硬件驱动开发流程。这种将不同硬件模块有效整合的能力,正是开发现代智能硬件产品的核心技能。
值得一提的是,本文提供的驱动代码和配置方法具有很好的通用性,稍作修改即可适配其他SPI接口的显示设备,为开发者提供了有价值的参考。显示功能的加入,为智能语音设备开辟了更丰富的交互可能性——无论是显示语音识别结果、设备状态信息,还是简单的用户界面,都能显著提升产品的用户体验。
未来,我们可以在此基础上进一步探索LVGL等轻量级图形库的集成,开发更复杂的用户界面,或者结合CI230X的语音处理能力,打造真正的多模态交互设备。期待各位开发者能够以此为基础,创造出更多创新的应用!
让设备既能"听"又能"看",人机交互的边界正在我们手中不断拓展。