前言
恩智浦“FRDM-MCXN947”評測活動由安富利和與非網(wǎng)協(xié)同舉辦。本篇內(nèi)容由與非網(wǎng)用戶發(fā)布,已獲轉載許可。原文可在與非網(wǎng)(eefocus)工程師社區(qū)查看。
TFT LCD模組介紹
模組名字為SPI_Module_MSP3323,驅動芯片為ILI9341,屏幕尺寸為240x320像素,自帶GRAM。通過4線SPI驅動,可以發(fā)送數(shù)據(jù)和命令也可以讀取屏幕的IC參數(shù)甚至像素點顏色。
模組背面

模組管腳

MCXN947的接口
當前只移植顯示接口,只需要關注顯示屏相關的引腳。
MCXN947驅動TFT LCD的方式為4線SPI,選擇FLEXIO_SPI_EDMA方式驅動。FLEXIO_SPI相關的管腳為如下的FLEXIO_Dxx。

FLEXIO介紹
MCXN947只有一個FLEXIO模塊,即FLEXIO0。FLEXIO是一個高度可配置的模塊,它提供了:
靈活的16位定時器,支持各種觸發(fā)、復位、使能和禁用條件;
可編程邏輯塊,允許實現(xiàn)片上的數(shù)字邏輯功能,并且可配置內(nèi)部和外部模塊的交互;
可編程狀態(tài)機,用于從CPU中卸載基本的系統(tǒng)控制功能;
FLEXIO框圖
下圖提供了FLEXIO計時器和移位寄存器配置的高層次總覽。
FLEXIO使用移位器、計時器和外部觸發(fā)器來講數(shù)據(jù)移入或移除FLEXIO。如方框圖所示,計時器控制這個數(shù)據(jù)移位的時間,您可以將計時器配置為使用通用計時器功能,外部觸發(fā)器或各種其他條件來決定控制邏輯。

FLEXIO特性
1.具有傳輸、接收、數(shù)據(jù)匹配、邏輯和狀態(tài)模式的32位移位寄存器陣列:
支持連續(xù)數(shù)據(jù)傳輸?shù)碾p緩沖移位操作;
支持大塊數(shù)據(jù)傳輸?shù)囊莆贿B接;
支持自動啟動和停止位生成;
1,2,4,8,16或者32為多移位寬度的并行接口支持;
中斷,DMA或者輪詢傳輸和接收操作;
2.高度靈活的16位定時器,支持各種內(nèi)部或者外部觸發(fā),重置,啟用和禁用條件:
可編程波特率獨立于總線時鐘頻率,并支持在停止模式器件的異步操作;
可編程邏輯模式,用于集成外部數(shù)字邏輯功能,或組合引腳,移位器,或定時器功能,以產(chǎn)生復雜的輸出;
可編程狀態(tài)機,用于從CPU卸載基本的系統(tǒng)控制功能,支持最多8個狀態(tài),8個輸出,每個狀態(tài)和3個可選輸入;
3.集成的通用I/O寄存器和引腳上升或下降的邊緣中斷,以簡化軟件支持;
4.支持廣泛的協(xié)議,包括但不限于:I2C,SPI,I2S,Camera IF,Motorola 68K或Intel 8080 bus,PWM波形發(fā)生器,輸入捕獲(脈沖邊緣間隔測量),如SENT
管腳配置
當前只需要點亮LCD,只需要配置顯示相關的管腳,如下圖所示:
在MCUXpress Config Tools中新建一個功能組,命名為TFT_LCD_Init,
設置管腳路由信息,并修改各個管腳的標志符;

其中LCD_RST,LCD_RS,LCD_LED都是GPIO Output,分別對應J3.1,J3.3,J3.5。
FLEXIO模擬的SPI管腳分別是J8.27,J8.28,J8.26,J8.25。
移植
01移植思路
SPI接口驅動TFT LCD主要設計到3個控制管腳的輸出,SPI發(fā)送、讀取8比特數(shù)據(jù)。
023個GPIO控制管腳
都初始化為GPIO OUTPUT。
其中LCD_LED是背光管腳,拉高即點亮屏幕,拉低熄屏。當前只需要初始化時輸出高電平即可;
其中LCD_RS是數(shù)據(jù)、命令選擇功能,需要提供管腳的電平設置功能,提供兩個宏定義即可;
其中LCD_RST是LCD復位管腳,輸出低電平表示復位,提供兩個宏定義即可;
03SPI管腳
初始化FLEXIO0的4個管腳,然后初始化FLEXIO_SPI,并關聯(lián)這4個管腳。
關鍵代碼
01GPIO控制管腳
下面的port_LCD_CtrlPin_Init()函數(shù)是我新增的,僅僅設置LCD_LED輸出高電平,因為這3個管腳的初始化已經(jīng)由MCUXpresso Config Tools配置好并生成了初始化代碼,見下方的TFT_LCD_Init()函數(shù)。
(滑動查看)
/**
*@briefLCD 控制管腳初始化
* LCD_RST --> J3.1 P2_0 復位管腳:低電平復位
* LCD_RS --> J3.3 P1_22 命令數(shù)據(jù)選擇管腳:高電平--數(shù)據(jù);低電平--命令
* LCD_LED --> J3.5 P2_3 背光管腳:高電平點亮,也可以 PWM 調節(jié)亮度
*
*@param
*/
voidport_LCD_CtrlPin_Init(void)
{
// 這3個管腳已經(jīng)在 BOARD_InitBootPins() 中初始化了
LCD_LED(1);
}
(滑動查看)
/* FUNCTION************************************************************************************************************ * * Function Name : TFT_LCD_Init * Description : Configures pin routing and optionally pin electrical features. * * END****************************************************************************************************************/ void TFT_LCD_Init(void) { /* Enables the clock for GPIO1: Enables clock*/ CLOCK_EnableClock(kCLOCK_Gpio1); /* Enables the clock for GPIO2: Enables clock*/ CLOCK_EnableClock(kCLOCK_Gpio2); /* Enables the clock for PORT1: Enables clock*/ CLOCK_EnableClock(kCLOCK_Port1); /* Enables the clock for PORT2: Enables clock*/ CLOCK_EnableClock(kCLOCK_Port2); /* Enables the clock for PORT4: Enables clock*/ CLOCK_EnableClock(kCLOCK_Port4); gpio_pin_config_t LCD_RS_config= { .pinDirection = kGPIO_DigitalOutput, .outputLogic = 0U }; /* Initialize GPIO functionality on pin PIO1_22 (pin L4) */ GPIO_PinInit(TFT_LCD_LCD_RS_GPIO, TFT_LCD_LCD_RS_PIN, &LCD_RS_config); gpio_pin_config_t LCD_RST_config= { .pinDirection = kGPIO_DigitalOutput, .outputLogic = 0U }; /* Initialize GPIO functionality on pin PIO2_0 (pin H2) */ GPIO_PinInit(TFT_LCD_LCD_RST_GPIO, TFT_LCD_LCD_RST_PIN, &LCD_RST_config); gpio_pin_config_t LCD_LED_config= { .pinDirection = kGPIO_DigitalOutput, .outputLogic = 0U }; /* Initialize GPIO functionality on pin PIO2_3 (pin J3) */ GPIO_PinInit(TFT_LCD_LCD_LED_GPIO, TFT_LCD_LCD_LED_PIN, &LCD_LED_config); /* PORT1_22 (pin L4) is configured as PIO1_22*/ PORT_SetPinMux(TFT_LCD_LCD_RS_PORT, TFT_LCD_LCD_RS_PIN, kPORT_MuxAlt0); PORT1->PCR[22] = ((PORT1->PCR[22] & /* Mask bits to zero which are setting*/ (~(PORT_PCR_DSE_MASK|PORT_PCR_IBE_MASK))) /* Drive Strength Enable: High.*/ |PORT_PCR_DSE(PCR_DSE_dse1) /* Input Buffer Enable: Enables.*/ |PORT_PCR_IBE(PCR_IBE_ibe1)); /* PORT2_0 (pin H2) is configured as PIO2_0*/ PORT_SetPinMux(TFT_LCD_LCD_RST_PORT, TFT_LCD_LCD_RST_PIN, kPORT_MuxAlt0); PORT2->PCR[0] = ((PORT2->PCR[0] & /* Mask bits to zero which are setting*/ (~(PORT_PCR_DSE_MASK|PORT_PCR_IBE_MASK))) /* Drive Strength Enable: High.*/ |PORT_PCR_DSE(PCR_DSE_dse1) /* Input Buffer Enable: Enables.*/ |PORT_PCR_IBE(PCR_IBE_ibe1)); /* PORT2_3 (pin J3) is configured as PIO2_3*/ PORT_SetPinMux(TFT_LCD_LCD_LED_PORT, TFT_LCD_LCD_LED_PIN, kPORT_MuxAlt0); PORT2->PCR[3] = ((PORT2->PCR[3] & /* Mask bits to zero which are setting*/ (~(PORT_PCR_DSE_MASK|PORT_PCR_IBE_MASK))) /* Drive Strength Enable: High.*/ |PORT_PCR_DSE(PCR_DSE_dse1) /* Input Buffer Enable: Enables.*/ |PORT_PCR_IBE(PCR_IBE_ibe1)); /* PORT4_20 (pin T10) is configured as FLEXIO0_D28*/ PORT_SetPinMux(TFT_LCD_LCD_MOSI_PORT, TFT_LCD_LCD_MOSI_PIN, kPORT_MuxAlt6); PORT4->PCR[20] = ((PORT4->PCR[20] & /* Mask bits to zero which are setting*/ (~(PORT_PCR_DSE_MASK|PORT_PCR_IBE_MASK))) /* Drive Strength Enable: High.*/ |PORT_PCR_DSE(PCR_DSE_dse1) /* Input Buffer Enable: Enables.*/ |PORT_PCR_IBE(PCR_IBE_ibe1)); /* PORT4_21 (pin T11) is configured as FLEXIO0_D29*/ PORT_SetPinMux(TFT_LCD_LCD_MISO_PORT, TFT_LCD_LCD_MISO_PIN, kPORT_MuxAlt6); PORT4->PCR[21] = ((PORT4->PCR[21] & /* Mask bits to zero which are setting*/ (~(PORT_PCR_DSE_MASK|PORT_PCR_IBE_MASK))) /* Drive Strength Enable: High.*/ |PORT_PCR_DSE(PCR_DSE_dse1) /* Input Buffer Enable: Enables.*/ |PORT_PCR_IBE(PCR_IBE_ibe1)); /* PORT4_22 (pin T12) is configured as FLEXIO0_D30*/ PORT_SetPinMux(TFT_LCD_LCD_SCK_PORT, TFT_LCD_LCD_SCK_PIN, kPORT_MuxAlt6); PORT4->PCR[22] = ((PORT4->PCR[22] & /* Mask bits to zero which are setting*/ (~(PORT_PCR_DSE_MASK|PORT_PCR_IBE_MASK))) /* Drive Strength Enable: High.*/ |PORT_PCR_DSE(PCR_DSE_dse1) /* Input Buffer Enable: Enables.*/ |PORT_PCR_IBE(PCR_IBE_ibe1)); /* PORT4_23 (pin U12) is configured as FLEXIO0_D31*/ PORT_SetPinMux(TFT_LCD_LCD_CS_PORT, TFT_LCD_LCD_CS_PIN, kPORT_MuxAlt6); PORT4->PCR[23] = ((PORT4->PCR[23] & /* Mask bits to zero which are setting*/ (~(PORT_PCR_DSE_MASK|PORT_PCR_IBE_MASK))) /* Drive Strength Enable: High.*/ |PORT_PCR_DSE(PCR_DSE_dse1) /* Input Buffer Enable: Enables.*/ |PORT_PCR_IBE(PCR_IBE_ibe1)); }
并提供宏定義實現(xiàn)GPIO管腳的輸出高低電平功能:
(滑動查看)
// 硬件 CS,此處忽略 #defineLCD_CS_SET #defineLCD_CS_CLR // 數(shù)據(jù)、命令選擇 #defineLCD_RS_SETGPIO_PinWrite(TFT_LCD_LCD_RS_GPIO, TFT_LCD_LCD_RS_GPIO_PIN, 1) #defineLCD_RS_CLRGPIO_PinWrite(TFT_LCD_LCD_RS_GPIO, TFT_LCD_LCD_RS_GPIO_PIN, 0) #defineLCD_RST_SETGPIO_PinWrite(TFT_LCD_LCD_RST_GPIO, TFT_LCD_LCD_RST_GPIO_PIN, 1) #defineLCD_RST_CLRGPIO_PinWrite(TFT_LCD_LCD_RST_GPIO, TFT_LCD_LCD_RST_GPIO_PIN, 0)
02FLEXIO_SPI初始化
對應的管腳路由已經(jīng)在TFT_LCD_Init()中配置好了,此處僅需要初始化FLEXIO_SPI并關聯(lián)對應的4個管腳。
03全局宏定義和變量
(滑動查看)
/******************************************************************************* * Definitions ******************************************************************************/ #define BOARD_FLEXIO_BASE (FLEXIO0) #define FLEXIO_SPI_MOSI_PIN 28U #define FLEXIO_SPI_MISO_PIN 29U #define FLEXIO_SPI_SCK_PIN 30U #define FLEXIO_SPI_CSn_PIN 31U #define FLEXIO_CLOCK_FREQUENCYCLOCK_GetFlexioClkFreq() #define EXAMPLE_FLEXIO_SPI_DMA_BASEADDRDMA0 #define FLEXIO_SPI_TX_DMA_CHANNEL (0U) #define FLEXIO_SPI_RX_DMA_CHANNEL (1U) #define FLEXIO_TX_SHIFTER_INDEX 0U #define FLEXIO_RX_SHIFTER_INDEX 2U #define EXAMPLE_TX_DMA_SOURCE kDma0RequestMuxFlexIO0ShiftRegister0Request #define EXAMPLE_RX_DMA_SOURCE kDma0RequestMuxFlexIO0ShiftRegister2Request #define FLEXIO_SPI_BAUD_HIGH (1000000*25) #define FLEXIO_SPI_BAUD_LOW (1000000*1) /******************************************************************************* * Variables ******************************************************************************/ static flexio_spi_master_edma_handle_t g_spiHandle; static edma_handle_t txHandle; static edma_handle_t rxHandle; FLEXIO_SPI_Type spiDev; flexio_spi_master_config_t userConfig; volatile bool completeFlag =false; static void spi_master_completionCallback(FLEXIO_SPI_Type*base, flexio_spi_master_edma_handle_t *handle, status_t status, void *userData) { if (status == kStatus_Success) { completeFlag =true; } }
04FLEXIO_SPI初始化函數(shù)
初始化FLEXIO_SPI并初始化EDMA。
(滑動查看)
/**
* @brief SPI 初始化
*
*/
voidport_LCD_SPI_Init(void)
{
uint8_ti =0;
uint8_terr =0;
dma_request_source_tdma_request_source_tx;
dma_request_source_tdma_request_source_rx;
edma_config_tconfig;
/* attach PLL0 to FLEXIO */
CLOCK_SetClkDiv(kCLOCK_DivFlexioClk,1u);
CLOCK_AttachClk(kPLL0_to_FLEXIO);
/* Init FlexIO SPI. */
/*
* userConfig.enableMaster = true;
* userConfig.enableInDoze = false;
* userConfig.enableInDebug = true;
* userConfig.enableFastAccess = false;
* userConfig.baudRate_Bps = 500000U;
* userConfig.phase = kFLEXIO_SPI_ClockPhaseFirstEdge;
* userConfig.dataMode = kFLEXIO_SPI_8BitMode;
*/
FLEXIO_SPI_MasterGetDefaultConfig(&userConfig);
//NOTE:此處修改 SPI 通信速率
userConfig.baudRate_Bps =FLEXIO_SPI_BAUD_HIGH;
spiDev.flexioBase =BOARD_FLEXIO_BASE;
spiDev.SDOPinIndex=FLEXIO_SPI_MOSI_PIN;
spiDev.SDIPinIndex=FLEXIO_SPI_MISO_PIN;
spiDev.SCKPinIndex=FLEXIO_SPI_SCK_PIN;
spiDev.CSnPinIndex=FLEXIO_SPI_CSn_PIN;
spiDev.shifterIndex[0] =FLEXIO_TX_SHIFTER_INDEX;
spiDev.shifterIndex[1] =FLEXIO_RX_SHIFTER_INDEX;
spiDev.timerIndex[0] =0U;
spiDev.timerIndex[1] =1U;
dma_request_source_tx = (dma_request_source_t)EXAMPLE_TX_DMA_SOURCE;
dma_request_source_rx = (dma_request_source_t)EXAMPLE_RX_DMA_SOURCE;
#ifdefined(FSL_FEATURE_SOC_DMAMUX_COUNT) &&FSL_FEATURE_SOC_DMAMUX_COUNT
/*Init EDMA for example.*/
DMAMUX_Init(EXAMPLE_FLEXIO_SPI_DMAMUX_BASEADDR);
/* Request DMA channels for TX & RX. */
DMAMUX_SetSource(EXAMPLE_FLEXIO_SPI_DMAMUX_BASEADDR, FLEXIO_SPI_TX_DMA_CHANNEL, dma_request_source_tx);
DMAMUX_SetSource(EXAMPLE_FLEXIO_SPI_DMAMUX_BASEADDR, FLEXIO_SPI_RX_DMA_CHANNEL, dma_request_source_rx);
DMAMUX_EnableChannel(EXAMPLE_FLEXIO_SPI_DMAMUX_BASEADDR, FLEXIO_SPI_TX_DMA_CHANNEL);
DMAMUX_EnableChannel(EXAMPLE_FLEXIO_SPI_DMAMUX_BASEADDR, FLEXIO_SPI_RX_DMA_CHANNEL);
#endif
EDMA_GetDefaultConfig(&config);
EDMA_Init(EXAMPLE_FLEXIO_SPI_DMA_BASEADDR, &config);
EDMA_CreateHandle(&txHandle, EXAMPLE_FLEXIO_SPI_DMA_BASEADDR, FLEXIO_SPI_TX_DMA_CHANNEL);
EDMA_CreateHandle(&rxHandle, EXAMPLE_FLEXIO_SPI_DMA_BASEADDR, FLEXIO_SPI_RX_DMA_CHANNEL);
#ifdefined(FSL_FEATURE_EDMA_HAS_CHANNEL_MUX) &&FSL_FEATURE_EDMA_HAS_CHANNEL_MUX
EDMA_SetChannelMux(EXAMPLE_FLEXIO_SPI_DMA_BASEADDR, FLEXIO_SPI_TX_DMA_CHANNEL, dma_request_source_tx);
EDMA_SetChannelMux(EXAMPLE_FLEXIO_SPI_DMA_BASEADDR, FLEXIO_SPI_RX_DMA_CHANNEL, dma_request_source_rx);
#endif
FLEXIO_SPI_MasterInit(&spiDev, &userConfig, FLEXIO_CLOCK_FREQUENCY);
}
05SPI傳輸函數(shù)
此處僅實現(xiàn)了單個字節(jié)的發(fā)送和接收函數(shù),通過eDMA中斷來判斷收發(fā)是否完成。
(滑動查看)
uint8_tport_LCD_SPI_TxByte(uint8_tdata)
{
flexio_spi_transfer_txfer = {0};
uint8_treadBack =0;
/* Send to slave. */
xfer.txData =&data;
xfer.rxData =&readBack;
xfer.dataSize =1;
xfer.flags = kFLEXIO_SPI_8bitMsb;
FLEXIO_SPI_MasterTransferCreateHandleEDMA(&spiDev, &g_spiHandle,
spi_master_completionCallback,NULL, &txHandle, &rxHandle);
FLEXIO_SPI_MasterTransferEDMA(&spiDev, &g_spiHandle, &xfer);
while(!completeFlag);
completeFlag =false;
returnreadBack;
}
06LCD讀寫寄存器、數(shù)據(jù)函數(shù)
下面是LCD抽象層的函數(shù),僅僅需要控制管腳輸出高低電平、SPI傳輸單個字節(jié)即可。
(滑動查看)
/*****************************************************************************
* @name :void LCD_WR_REG(uint8_t data)
* @date :2018-08-09
* @function :Write an 8-bit command to the LCD screen
* @parameters Command value to be written
* @retvalue :None
******************************************************************************/
void LCD_WR_REG(uint8_t data)
{
LCD_CS_CLR;
LCD_RS_CLR;
port_LCD_SPI_TxByte(data);
LCD_CS_SET;
}
/*****************************************************************************
* @name :void LCD_WR_DATA(uint8_t data)
* @date :2018-08-09
* @function :Write an 8-bit data to the LCD screen
* @parameters data value to be written
* @retvalue :None
******************************************************************************/
void LCD_WR_DATA(uint8_t data)
{
LCD_CS_CLR;
LCD_RS_SET;
port_LCD_SPI_TxByte(data);
LCD_CS_SET;
}
運行
屏幕成功點亮,也能顯示中英文字符,繪制圖片出了點差錯,但是刷屏速度好慢。嘗試提高了SPI速度,編譯器優(yōu)化等級debug/release都試過,刷屏的百葉窗效果還是很明顯。


-
lcd
+關注
關注
36文章
4615瀏覽量
177181 -
恩智浦
+關注
關注
14文章
6095瀏覽量
146964 -
TFT
+關注
關注
10文章
409瀏覽量
114607 -
驅動芯片
+關注
關注
14文章
1642瀏覽量
57949
原文標題:用戶測評(六):NXP FRDM-MCXN947 FLEXIO_SPI驅動TFT LCD
文章出處:【微信號:AvnetAsia,微信公眾號:安富利】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
恩智浦MCX N23的官方評估板FRDM-MCXN236詳解
在恩智浦FRDM-MCXN947開發(fā)板部署DeepSeek大語言模型
FRDM-MCXN947的純Linux命令行環(huán)境搭建
關于將Flash寫入FRDM-MCXN947的問題求解
FRDM-MCXN947在初始化lpI2C時, I2C無法正常工作怎么解決?
《電子發(fā)燒友電子設計周報》聚焦硬科技領域核心價值 第11期:2025.05.12--2025.05.16
富昌電子推薦兩款恩智浦的MCX A和MCX N系列微控制器
《恩智浦FRDM-MCXN947開發(fā)實踐指南》上線啦
基于Label CIFAR10 image on FRDM-MCXN947例程實現(xiàn)鞋和帽子的識別
使用NXP MCX-N板卡搭建環(huán)境及點燈
使用恩智浦FRDM-MCXN947開發(fā)板驅動TFT LCD模組
評論