【FRDM-MCXN947】TFT-LCD显示屏测试
[复制链接]
本帖最后由 TL-LED 于 2024-12-22 22:50 编辑
使用FLEXIO接口测试TFT-LCD显示屏,驱动芯片使用SSD1963。
一、硬件接口部分
1.1、使用板子上的LCD接口
1.2、SSD1963接口框图
1.3、SSD1963数据格式
SSD1963与显示屏之间数据接口的连接定义
1.4、显示屏接口
我的显示屏是18位总线,在配置SSD1963时,选择18位数据。
二、引脚配置
2.1、配置显示屏接口
2.2、配置外设
三、程序部分
3.1、mculcd.c
#include "main.h"
/*******************************************************************************
* Prototypes
******************************************************************************/
void BOARD_InitSmartDMA(void);
static void DEMO_InitFlexioMcuLcd(void);
static void DEMO_InitPanel(void);
static void DEMO_StartPanel(void);
static status_t DEMO_LcdWriteCommand(void *dbiXferHandle, uint32_t command);
static status_t DEMO_LcdWriteData(void *dbiXferHandle, void *data, uint32_t len_byte);
static status_t DEMO_LcdWriteMemory(void *dbiXferHandle, uint32_t command, const void *data, uint32_t len_byte);
/*******************************************************************************
* Variables
******************************************************************************/
/* The functions used to drive the panel. */
static dbi_xfer_ops_t s_flexioDbiOps = {
.writeCommand = DEMO_LcdWriteCommand,
.writeData = DEMO_LcdWriteData,
.writeMemory = DEMO_LcdWriteMemory,
.readMemory = NULL, /* Don't need read in this project. */
.setMemoryDoneCallback = NULL, /* This used for upper layer to register callback.
If the writeMemory is a non-blocking(or async)
function, when write finished, the registered
callback function will be called.
In this project, to be simple, DEMO_LcdWriteMemory
blocks to wait the write done, it is not async
implementation, so don't need to set callback.
*/
};
static ssd1963_handle_t lcdHandle;
static flexio_mculcd_smartdma_handle_t s_flexioLcdHandle;
static demo_pixel_t s_lcdBuffer[DEMO_BUFFER_HEIGHT][DEMO_BUFFER_WIDTH];
static volatile bool s_transferDone = false;
void FLEXIO_TransferCallback(FLEXIO_MCULCD_Type *,flexio_mculcd_smartdma_handle_t *,status_t ,void *)
{
s_transferDone = true;
}
void BOARD_SetResetPin(bool set)
{
GPIO_PinWrite(DEMO_SSD1963_RST_GPIO, DEMO_SSD1963_RST_PIN, (uint8_t)set);
}
void BOARD_InitSmartDMA(void)
{
RESET_ClearPeripheralReset(kMUX_RST_SHIFT_RSTn);
INPUTMUX_Init(INPUTMUX0);
INPUTMUX_AttachSignal(INPUTMUX0, 0, kINPUTMUX_FlexioToSmartDma);
/* Turnoff clock to inputmux to save power. Clock is only needed to make changes */
INPUTMUX_Deinit(INPUTMUX0);
SMARTDMA_InitWithoutFirmware();
NVIC_EnableIRQ(SMARTDMA_IRQn);
NVIC_SetPriority(SMARTDMA_IRQn, 3);
}
static status_t DEMO_LcdWriteCommand(void *dbiXferHandle, uint32_t command)
{
/* dbiXferHandle is actually s_flexioLcdHandle, set by SSD1963_Init 4th parameter. */
flexio_mculcd_smartdma_handle_t *flexioLcdHandle = (flexio_mculcd_smartdma_handle_t *)dbiXferHandle;
/* Here use blocking way to send command, because command is short. */
FLEXIO_MCULCD_Type *flexioLCD = flexioLcdHandle->base; /* flexioLcdDev */
FLEXIO_MCULCD_StartTransfer(flexioLCD);
FLEXIO_MCULCD_WriteCommandBlocking(flexioLCD, command);
FLEXIO_MCULCD_StopTransfer(flexioLCD);
return kStatus_Success;
}
static status_t DEMO_LcdWriteData(void *dbiXferHandle, void *data, uint32_t len_byte)
{
/* dbiXferHandle is actually s_flexioLcdHandle, set by SSD1963_Init 4th parameter. */
flexio_mculcd_smartdma_handle_t *flexioLcdHandle = (flexio_mculcd_smartdma_handle_t *)dbiXferHandle;
/*
* Here use blocking way to write data, this function is generally
* used to send command parameter, the data length is short.
*/
FLEXIO_MCULCD_Type *flexioLCD = flexioLcdHandle->base; /* flexioLcdDev */
FLEXIO_MCULCD_StartTransfer(flexioLCD);
FLEXIO_MCULCD_WriteDataArrayBlocking(flexioLCD, data, len_byte);
FLEXIO_MCULCD_StopTransfer(flexioLCD);
return kStatus_Success;
}
static status_t DEMO_LcdWriteMemory(void *dbiXferHandle, uint32_t command, const void *data, uint32_t len_byte)
{
status_t status;
/* dbiXferHandle is actually s_flexioLcdHandle, set by SSD1963_Init 4th parameter. */
flexio_mculcd_smartdma_handle_t *flexioLcdHandle = (flexio_mculcd_smartdma_handle_t *)dbiXferHandle;
FLEXIO_MCULCD_Type *flexioLCD = flexioLcdHandle->base; /* flexioLcdDev */
flexio_mculcd_transfer_t xfer = {
.command = command,
.mode = kFLEXIO_MCULCD_WriteArray,
.dataAddrOrSameValue = (uint32_t)data,
.dataSize = len_byte,
};
s_transferDone = false;
status = FLEXIO_MCULCD_TransferSMARTDMA(flexioLCD, flexioLcdHandle, &xfer);
if (kStatus_Success != status)
{
PRINTF("Write Memory Failed\r\n");
while (1)
{
}
}
else
{
/* Wait for transfer done. */
while (!s_transferDone)
{
}
}
return status;
}
static void DEMO_InitFlexioMcuLcd(void)
{
status_t status;
flexio_mculcd_config_t flexioMcuLcdConfig;
flexio_mculcd_smartdma_config_t flexioEzhConfig = {
.inputPixelFormat = kFLEXIO_MCULCD_RGB565,
.outputPixelFormat = kFLEXIO_MCULCD_RGB565,
};
/* Initialize the flexio MCU LCD. */
/*
* flexioMcuLcdConfig.enable = true;
* flexioMcuLcdConfig.enableInDoze = false;
* flexioMcuLcdConfig.enableInDebug = true;
* flexioMcuLcdConfig.enableFastAccess = true;
* flexioMcuLcdConfig.baudRate_Bps = 96000000U;
*/
// FLEXIO_MCULCD_GetDefaultConfig(&flexioMcuLcdConfig);
// flexioMcuLcdConfig.baudRate_Bps = DEMO_FLEXIO_BAUDRATE_BPS;
// status = FLEXIO_MCULCD_Init(&flexioLcdDev, &flexioMcuLcdConfig, DEMO_FLEXIO_CLOCK_FREQ);
// if (kStatus_Success != status)
// {
// PRINTF("FlexIO MCULCD init failed\r\n");
// while (1)
// ;
// }
/* Init SMARTDMA. */
// BOARD_InitSmartDMA();
// /* Create FLEXIO_MCULCD SMARTDMA handle. */
// status = FLEXIO_MCULCD_TransferCreateHandleSMARTDMA(&flexioLcdDev, &s_flexioLcdHandle, &flexioEzhConfig,
// DEMO_FLEXIO_TransferCallback, NULL);
// status = FLEXIO_MCULCD_TransferCreateHandleSMARTDMA(&FLEXIO0_peripheralConfig, &ss_flexioLcdHandle, &FLEXIO0_smartdma_config,
// FLEXIO_TransferCallback, NULL);
// if (kStatus_Success != status)
// {
// PRINTF("FlexIO MCULCD handle creation failed\r\n");
// while (1)
// ;
// }
}
static void DEMO_InitPanel(void)
{
status_t status;
const ssd1963_config_t ssd1963Config = {
.pclkFreq_Hz = DEMO_SSD1963_PCLK_FREQ,
#if SSD1963_DATA_WITDH == 16
.pixelInterface = kSSD1963_PixelInterface16Bit565,
#else
.pixelInterface = kSSD1963_PixelInterface8BitBGR888,
#endif
.panelDataWidth = kSSD1963_PanelData18Bit,
.polarityFlags = DEMO_SSD1963_POLARITY_FLAG,
.panelWidth = DEMO_PANEL_WIDTH,
.panelHeight = DEMO_PANEL_HEIGHT,
.hsw = DEMO_SSD1963_HSW,
.hfp = DEMO_SSD1963_HFP,
.hbp = DEMO_SSD1963_HBP,
.vsw = DEMO_SSD1963_VSW,
.vfp = DEMO_SSD1963_VFP,
.vbp = DEMO_SSD1963_VBP
};
/* Reset the SSD1963 LCD controller. */
BOARD_SetResetPin(false);
SDK_DelayAtLeastUs(1, SystemCoreClock); /* Delay 10ns. */
BOARD_SetResetPin(true);
SDK_DelayAtLeastUs(5000, SystemCoreClock); /* Delay 5ms. */
status = SSD1963_Init(&lcdHandle, &ssd1963Config, &s_flexioDbiOps, &ss_flexioLcdHandle, DEMO_SSD1963_XTAL_FREQ);
if (kStatus_Success != status)
{
PRINTF("Panel initialization failed\r\n");
while (1)
{
}
}
}
void DEMO_StartPanel(void)
{
SSD1963_StartDisplay(&lcdHandle);
SSD1963_SetBackLight(&lcdHandle, 255);
}
/*
* Draw one window with pixel array, and delay some time after draw done.
*/
void DEMO_DrawWindow(uint16_t startX,
uint16_t startY,
uint16_t endX,
uint16_t endY,
const uint8_t *data,
uint32_t dataLen,
uint32_t delayMsAfterDraw)
{
SSD1963_SelectArea(&lcdHandle, startX, startY, endX, endY);
SSD1963_WriteMemory(&lcdHandle, data, dataLen);
if (delayMsAfterDraw > 0)
{
SDK_DelayAtLeastUs(delayMsAfterDraw * 1000, SystemCoreClock);
}
}
/*
* Draw multiple windows with specified color, can delay some time each window draw finished.
* In this example, the whole screen is devided in to 4 windows, this function fills the
* windows one by one.
*/
void DEMO_DrawMultiWindows(demo_pixel_t color, uint32_t intervalMs)
{
/* Fill buffer with pixel. */
for (uint32_t y = 0; y < DEMO_BUFFER_HEIGHT; y++)
{
for (uint32_t x = 0; x < DEMO_BUFFER_WIDTH; x++)
{
s_lcdBuffer[y][x] = color;
}
}
/* Region 0. */
DEMO_DrawWindow(0, 0, DEMO_BUFFER_WIDTH - 1, DEMO_BUFFER_HEIGHT - 1, (const uint8_t *)s_lcdBuffer,
sizeof(s_lcdBuffer), intervalMs);
/* Region 1. */
DEMO_DrawWindow(DEMO_BUFFER_WIDTH, 0, 2 * DEMO_BUFFER_WIDTH - 1, DEMO_BUFFER_HEIGHT - 1,
(const uint8_t *)s_lcdBuffer, sizeof(s_lcdBuffer), intervalMs);
/* Region 2. */
DEMO_DrawWindow(0, DEMO_BUFFER_HEIGHT, DEMO_BUFFER_WIDTH - 1, 2 * DEMO_BUFFER_HEIGHT - 1,
(const uint8_t *)s_lcdBuffer, sizeof(s_lcdBuffer), intervalMs);
/* Region 3. */
DEMO_DrawWindow(DEMO_BUFFER_WIDTH, DEMO_BUFFER_HEIGHT, 2 * DEMO_BUFFER_WIDTH - 1, 2 * DEMO_BUFFER_HEIGHT - 1,
(const uint8_t *)s_lcdBuffer, sizeof(s_lcdBuffer), intervalMs);
}
void init_mculcd(void)
{
BOARD_InitBootPeripherals();
BOARD_InitSmartDMA();
DEMO_InitPanel();
DEMO_DrawMultiWindows(DEMO_COLOR_BLACK, 0);
DEMO_StartPanel();
}
3.2、mculcd.h
#ifndef __MCULCD_H
#define __MCULCD_H
#define DEMO_PANEL_WIDTH 640U
#define DEMO_PANEL_HEIGHT 480U
/* Macros for the LCD controller. */
#define DEMO_SSD1963_XTAL_FREQ 10000000U
#define DEMO_SSD1963_PCLK_FREQ 25000000U
#define DEMO_SSD1963_HSW 1U
#define DEMO_SSD1963_HFP 116U
#define DEMO_SSD1963_HBP 44U
#define DEMO_SSD1963_VSW 1U
#define DEMO_SSD1963_VFP 10U
#define DEMO_SSD1963_VBP 34U
#define DEMO_SSD1963_POLARITY_FLAG 0U
#define DEMO_SSD1963_RST_GPIO GPIO4
#define DEMO_SSD1963_RST_PIN 7
#define DEMO_SSD1963_CS_GPIO GPIO0
#define DEMO_SSD1963_CS_PIN 12
#define DEMO_SSD1963_RS_GPIO GPIO0
#define DEMO_SSD1963_RS_PIN 7
#define DEMO_FLEXIO FLEXIO0
#define DEMO_FLEXIO_CLOCK_FREQ CLOCK_GetFlexioClkFreq()
#define DEMO_FLEXIO_BAUDRATE_BPS 160000000U /* 16-bit data bus, baud rate on each pin is 1MHz. */
/* Macros for FlexIO shifter, timer, and pins. */
#define DEMO_FLEXIO_WR_PIN 1
#define DEMO_FLEXIO_RD_PIN 0
#define DEMO_FLEXIO_DATA_PIN_START 16
#define DEMO_FLEXIO_TX_START_SHIFTER 0
#define DEMO_FLEXIO_RX_START_SHIFTER 0
#define DEMO_FLEXIO_TX_END_SHIFTER 7
#define DEMO_FLEXIO_RX_END_SHIFTER 7
#define DEMO_FLEXIO_TIMER 0
/* Macros for DMA */
#define DEMO_EDMA DMA0
#define DEMO_FLEXIO_TX_DMA_CHANNEL 0
#define DEMO_FLEXIO_TX_DMA_REQUEST kDma0RequestMuxFlexIO0ShiftRegister0Request
/* Buffer of the LCD send data. */
#define DEMO_BUFFER_WIDTH (DEMO_PANEL_WIDTH / 2U)
#define DEMO_BUFFER_HEIGHT (DEMO_PANEL_HEIGHT / 2U)
/* Color for RGB565 */
typedef uint16_t demo_pixel_t;
#define DEMO_COLOR_RED 0xF800U
#define DEMO_COLOR_GREEN 0x07E0U
#define DEMO_COLOR_BLUE 0x001FU
#define DEMO_COLOR_WHITE 0xFFFFU
#define DEMO_COLOR_BLACK 0x0000U
void init_mculcd(void);
void DEMO_DrawWindow(uint16_t startX,
uint16_t startY,
uint16_t endX,
uint16_t endY,
const uint8_t *data,
uint32_t dataLen,
uint32_t delayMsAfterDraw);
void DEMO_DrawMultiWindows(demo_pixel_t color, uint32_t intervalMs);
#endif
3.3、main.c
#include "main.h"
int main(void)
{
uint8_t i;
uint8_t colorIdx = 0;
const demo_pixel_t colorTable[] = {
DEMO_COLOR_RED,
DEMO_COLOR_GREEN,
DEMO_COLOR_BLUE,
DEMO_COLOR_WHITE,
};
CLOCK_EnableClock(kCLOCK_Gpio0);
BOARD_InitDEBUG_UARTPins();
BOARD_PowerMode_OD();
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
SysTick_Init();
init_led();
init_key();
init_mculcd();
while (1)
{
DEMO_DrawMultiWindows(colorTable[colorIdx], 500);
colorIdx++;
if (colorIdx >= ARRAY_SIZE(colorTable))
{
colorIdx = 0U;
}
led_red_tog();
}
}
3.4、 源代码
四、运行结果
下载程序到开发板,显示屏显示如下
lvgl
|