使用 FRDM-MCXA153 开发板驱动SPI LCD屏幕
- 版本说明
- SDK版本:25_06_00
- Keil MDK版本:5.42.0
- Config Tool版本:25.6
硬件条件
这里使用的是一块驱动芯片为 ST7789 的 SPI 接口 1.3 寸小屏幕,分辨率为240*240,通过FRDM-MCXA153 开发板上面的Arduino接口和屏幕底板进行连接,对应引脚如下。
| 屏幕底板 | MCU引脚 |
|---|---|
| SCL | P2_12 |
| BL | P2_16 |
| SDA | P2_13 |
| CS | P2_6 |
| DC | P3_14 |
| RES | P3_15 |
软件开发
使用 MCUXpresso Config Tool 工具配置好对应的几个管脚,除了 SPI 的 MCLK、MOSI 外均为输出模式
然后根据 ST7789 的芯片手册,编写写命令和写内存的两个函数,代码如下
void LPSPI_WriteCommand(uint8_t command, const uint8_t *params, uint8_t param_len)
{
lpspi_transfer_t masterXfer;
uint32_t i;
/* Set up the transfer data */
for (i = 0U; i < TRANSFER_SIZE; i++)
{
masterTxData[i] = 0U;
}
masterTxData[0] = command;
/*Start master transfer*/
masterXfer.txData = masterTxData;
masterXfer.rxData = NULL;
masterXfer.dataSize = 1;
masterXfer.configFlags =
EXAMPLE_LPSPI_MASTER_PCS_FOR_TRANSFER | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap;
GPIO_PinWrite(BOARD_INITPINS_DC_GPIO, BOARD_INITPINS_DC_GPIO_PIN, 0); /* command */
GPIO_PinWrite(BOARD_INITPINS_CS_GPIO, BOARD_INITPINS_CS_GPIO_PIN, 0); /* command */
LPSPI_MasterTransferBlocking(EXAMPLE_LPSPI_MASTER_BASEADDR, &masterXfer);
for (i = 0U; i < param_len; i++)
{
masterTxData[i] = params[i];
}
masterXfer.dataSize = param_len;
GPIO_PinWrite(BOARD_INITPINS_DC_GPIO, BOARD_INITPINS_DC_GPIO_PIN, 1); /* command */
LPSPI_MasterTransferBlocking(EXAMPLE_LPSPI_MASTER_BASEADDR, &masterXfer);
GPIO_PinWrite(BOARD_INITPINS_CS_GPIO, BOARD_INITPINS_CS_GPIO_PIN, 1); /* command */
}
void LPSPI_WriteMemory(uint16_t *data, uint32_t len)
{
lpspi_transfer_t masterXfer;
uint32_t i;
masterXfer.txData = (uint8_t *)data;
masterXfer.rxData = NULL;
masterXfer.dataSize = len * 2;
masterXfer.configFlags =
EXAMPLE_LPSPI_MASTER_PCS_FOR_TRANSFER | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap;
GPIO_PinWrite(BOARD_INITPINS_DC_GPIO, BOARD_INITPINS_DC_GPIO_PIN, 1); /* command */
GPIO_PinWrite(BOARD_INITPINS_CS_GPIO, BOARD_INITPINS_CS_GPIO_PIN, 0); /* command */
LPSPI_MasterTransferBlocking(EXAMPLE_LPSPI_MASTER_BASEADDR, &masterXfer);
GPIO_PinWrite(BOARD_INITPINS_CS_GPIO, BOARD_INITPINS_CS_GPIO_PIN, 1); /* command */
}
然后从 NXP的另一款 MCU —— N947 的 SDK 中复制出来 ST7796S的驱动代码进行修改,将头文件中原有的句柄结构体改成如下
/*! @brief ST7789 driver handle structure */
typedef struct _st7789_handle
{
void (*writeCommand)(uint8_t, const uint8_t *, uint8_t);
void (*writeMemory)(uint16_t *, uint32_t);
st7789_orientation_mode_t orientationMode; /*!< Current orientation mode */
} st7789_handle_t;
然后按如下步骤操作:
- 修改ST7796S的初始化序列,改为ST7789的初始化序列
- 按照原本的驱动框架进行注册、初始化
- 绘制像素、填充整个屏幕
将原本的初始化序列修改,使用ST7789的序列
static const uint8_t s_st7789_driver_preset_pars035[] = {
0x01, 0x36, 0x00,
0x01, 0x3a, 0x55,
//--------------------------------ST7789S Frame rate setting----------------------------------//
0x05, 0xb2, 0x0c, 0x0c, 0x00, 0x33, 0x33,
0x01, 0xb7, 0x35,
//---------------------------------ST7789S Power setting--------------------------------------//
0x01, 0xbb, 0x28,
0x01, 0xc0, 0x2c,
0x01, 0xc2, 0x01,
0x01, 0xc3, 0x0b,
0x01, 0xc4, 0x20,
0x01, 0xc6, 0x0f,
0x02, 0xd0, 0xa4, 0xa1,
//--------------------------------ST7789S gamma setting---------------------------------------//
0x0e, 0xe0, 0xd0, 0x01, 0x08, 0x0f, 0x11, 0x2a, 0x36, 0x55, 0x44, 0x3a, 0x0b, 0x06, 0x11, 0x20,
0x0e, 0xe1, 0xd0, 0x02, 0x07, 0x0a, 0x0b, 0x18, 0x34, 0x43, 0x4a, 0x2b, 0x1b, 0x1c, 0x22, 0x1f,
0x00, 0x11,
0x01, 0x29,
};
然后在main函数中完成对于屏幕的初始化,代码如下,完成屏幕的上电复位、初始化、框选整个屏幕等操作
st7789_handle_t g_st7789_handle = {
.writeCommand = LPSPI_WriteCommand,
.writeMemory = LPSPI_WriteMemory,
};
st7789_config_t g_st7789_config = {
.pixelFormat = kST7789_PixelFormatRGB565,
.teConfig = kST7789_TEDisabled,
.driverPreset = kST7789_DriverPresetLCDPARS035,
.orientationMode = kST7789_Orientation0,
.invertDisplay = false,
.flipDisplay = false,
.bgrFilter = false,
};
/* reset lcd */
GPIO_PinWrite(BOARD_INITPINS_RES_GPIO, BOARD_INITPINS_RES_GPIO_PIN, 0);
SDK_DelayAtLeastUs(100000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
GPIO_PinWrite(BOARD_INITPINS_RES_GPIO, BOARD_INITPINS_RES_GPIO_PIN, 1);
ST7789_Init(&g_st7789_handle, &g_st7789_config);
ST7789_InvertDisplay(&g_st7789_handle, true);
ST7789_EnableDisplay(&g_st7789_handle, true);
ST7789_SelectArea(&g_st7789_handle, 0, 0, 239, 239);
ST7789_StartPaint(&g_st7789_handle);
此时已经框选了整个屏幕,可以直接对整个屏幕进行写 memory 的操作,也就是对整个屏幕全屏刷新,这里代码实现了每隔1s就会变换红、绿、蓝三种颜色
for (size_t i = 0; i < 240; i++) {
for (size_t j = 0; j < 480; j += 2) {
masterTxData[j] = 0xf800 >> 8;
masterTxData[j + 1] = 0xf800 & 0xff;
}
ST7789_WritePixels(&g_st7789_handle, (uint16_t *)masterTxData, 240);
}
SDK_DelayAtLeastUs(1000000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
for (size_t i = 0; i < 240; i++) {
for (size_t j = 0; j < 480; j += 2) {
masterTxData[j] = 0x07E0 >> 8;
masterTxData[j + 1] = 0x07E0 & 0xff;
}
ST7789_WritePixels(&g_st7789_handle, (uint16_t *)masterTxData, 240);
}
SDK_DelayAtLeastUs(1000000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
for (size_t i = 0; i < 240; i++) {
for (size_t j = 0; j < 480; j += 2) {
masterTxData[j] = 0x001f >> 8;
masterTxData[j + 1] = 0x001f & 0xff;
}
ST7789_WritePixels(&g_st7789_handle, (uint16_t *)masterTxData, 240);
}
SDK_DelayAtLeastUs(1000000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
实现的效果如下视频所示,几种颜色不断的变换,对这块的 SPI LCD 驱动 demo 就完成了


