前言
恩智浦“FRDM-MCXN947”評測活動由安富利和與非網協同舉辦。本篇內容由與非網用戶發布,已獲轉載許可。原文可在與非網(eefocus)工程師社區查看。
TFT LCD模組介紹
模組名字為SPI_Module_MSP3323,驅動芯片為ILI9341,屏幕尺寸為240x320像素,自帶GRAM。通過4線SPI驅動,可以發送數據和命令也可以讀取屏幕的IC參數甚至像素點顏色。
模組背面
模組管腳
MCXN947的接口
當前只移植顯示接口,只需要關注顯示屏相關的引腳。
MCXN947驅動TFT LCD的方式為4線SPI,選擇FLEXIO_SPI_EDMA方式驅動。FLEXIO_SPI相關的管腳為如下的FLEXIO_Dxx。
FLEXIO介紹
MCXN947只有一個FLEXIO模塊,即FLEXIO0。FLEXIO是一個高度可配置的模塊,它提供了:
靈活的16位定時器,支持各種觸發、復位、使能和禁用條件;
可編程邏輯塊,允許實現片上的數字邏輯功能,并且可配置內部和外部模塊的交互;
可編程狀態機,用于從CPU中卸載基本的系統控制功能;
FLEXIO框圖
下圖提供了FLEXIO計時器和移位寄存器配置的高層次總覽。
FLEXIO使用移位器、計時器和外部觸發器來講數據移入或移除FLEXIO。如方框圖所示,計時器控制這個數據移位的時間,您可以將計時器配置為使用通用計時器功能,外部觸發器或各種其他條件來決定控制邏輯。
FLEXIO特性
1.具有傳輸、接收、數據匹配、邏輯和狀態模式的32位移位寄存器陣列:
支持連續數據傳輸的雙緩沖移位操作;
支持大塊數據傳輸的移位連接;
支持自動啟動和停止位生成;
1,2,4,8,16或者32為多移位寬度的并行接口支持;
中斷,DMA或者輪詢傳輸和接收操作;
2.高度靈活的16位定時器,支持各種內部或者外部觸發,重置,啟用和禁用條件:
可編程波特率獨立于總線時鐘頻率,并支持在停止模式器件的異步操作;
可編程邏輯模式,用于集成外部數字邏輯功能,或組合引腳,移位器,或定時器功能,以產生復雜的輸出;
可編程狀態機,用于從CPU卸載基本的系統控制功能,支持最多8個狀態,8個輸出,每個狀態和3個可選輸入;
3.集成的通用I/O寄存器和引腳上升或下降的邊緣中斷,以簡化軟件支持;
4.支持廣泛的協議,包括但不限于:I2C,SPI,I2S,Camera IF,Motorola 68K或Intel 8080 bus,PWM波形發生器,輸入捕獲(脈沖邊緣間隔測量),如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發送、讀取8比特數據。
023個GPIO控制管腳
都初始化為GPIO OUTPUT。
其中LCD_LED是背光管腳,拉高即點亮屏幕,拉低熄屏。當前只需要初始化時輸出高電平即可;
其中LCD_RS是數據、命令選擇功能,需要提供管腳的電平設置功能,提供兩個宏定義即可;
其中LCD_RST是LCD復位管腳,輸出低電平表示復位,提供兩個宏定義即可;
03SPI管腳
初始化FLEXIO0的4個管腳,然后初始化FLEXIO_SPI,并關聯這4個管腳。
關鍵代碼
01GPIO控制管腳
下面的port_LCD_CtrlPin_Init()函數是我新增的,僅僅設置LCD_LED輸出高電平,因為這3個管腳的初始化已經由MCUXpresso Config Tools配置好并生成了初始化代碼,見下方的TFT_LCD_Init()函數。
(滑動查看)
/** *@briefLCD 控制管腳初始化 * LCD_RST --> J3.1 P2_0 復位管腳:低電平復位 * LCD_RS --> J3.3 P1_22 命令數據選擇管腳:高電平--數據;低電平--命令 * LCD_LED --> J3.5 P2_3 背光管腳:高電平點亮,也可以 PWM 調節亮度 * *@param */ voidport_LCD_CtrlPin_Init(void) { // 這3個管腳已經在 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)); }
并提供宏定義實現GPIO管腳的輸出高低電平功能:
(滑動查看)
// 硬件 CS,此處忽略 #defineLCD_CS_SET #defineLCD_CS_CLR // 數據、命令選擇 #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初始化
對應的管腳路由已經在TFT_LCD_Init()中配置好了,此處僅需要初始化FLEXIO_SPI并關聯對應的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初始化函數
初始化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傳輸函數
此處僅實現了單個字節的發送和接收函數,通過eDMA中斷來判斷收發是否完成。
(滑動查看)
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讀寫寄存器、數據函數
下面是LCD抽象層的函數,僅僅需要控制管腳輸出高低電平、SPI傳輸單個字節即可。
(滑動查看)
/***************************************************************************** * @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速度,編譯器優化等級debug/release都試過,刷屏的百葉窗效果還是很明顯。
-
lcd
+關注
關注
34文章
4515瀏覽量
171276 -
恩智浦
+關注
關注
14文章
5974瀏覽量
115384 -
TFT
+關注
關注
10文章
396瀏覽量
112452 -
驅動芯片
+關注
關注
13文章
1403瀏覽量
56304
原文標題:用戶測評(六):NXP FRDM-MCXN947 FLEXIO_SPI驅動TFT LCD
文章出處:【微信號:AvnetAsia,微信公眾號:安富利】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
恩智浦MCX N23的官方評估板FRDM-MCXN236詳解

在恩智浦FRDM-MCXN947開發板部署DeepSeek大語言模型

FRDM-MCXN947的純Linux命令行環境搭建
關于將Flash寫入FRDM-MCXN947的問題求解
FRDM-MCXN947在初始化lpI2C時, I2C無法正常工作怎么解決?
《電子發燒友電子設計周報》聚焦硬科技領域核心價值 第11期:2025.05.12--2025.05.16
富昌電子推薦兩款恩智浦的MCX A和MCX N系列微控制器
恩智浦新品MCX N系列線下培訓來啦!LVGL、AI等超多精彩Demo演示,快來報名吧!

基于Label CIFAR10 image on FRDM-MCXN947例程實現鞋和帽子的識別

評論