本帖最后由 suncat0504 于 2024-7-20 10:36 编辑
之前在调试使用SD模块的过程中,在使用模拟SPI方式和SD卡的通讯过程,总是无法正常实现,就考虑使用FRDM-MCX-N947开发板的SPI外设,来实现这一个过程。为了呢个直观观测测试过程,确认通讯过程是否正常,准备使用SPI接口的TFT显示屏来完成这一个测试过程。 官方提供了frdmmcxn947_lpspi_polling_b2b_transfer_master例程,是以轮询方式实现SPI主设备的处理。我就在这个程序的基础上进行修改。这个例程中使用P0_24(SDO,MOSI)、P0_25(SCK)、P0_26(SDO,MISO)、P0_27(SS)作为接口,全都在J2上。同时为了匹配TFT显示屏的RST(复位),DC(命令寄存器/数据寄存器选择),使用J2的第2(P0_28)、4(P0_10)引脚作为。而且P0_10还是开发板上红色LED的驱动口,这样测试更方便。 原理图中,我用到的接口被圈了红色。因为TFT显示屏不需要向外输出数据,所以MISO没有被使用。 把显示屏的驱动程序做了修改,主要是去掉MOSI,SCK,CS的模拟处理部分,修改RST和DC的处理。 - <font face="Tahoma" size="4">#define LCD_RS_PORT GPIO0
- #define LCD_RS 10U // P0_10 ,使用红色LED的端口
- #define LCD_RST_PORT GPIO0
- #define LCD_RST 28U // P0_28
-
- //液晶控制口置1操作语句宏定义
- //#define LCD_SCL_SET GPIO_PinWrite(GPIO3, LCD_SCL, 1)
- //#define LCD_SDA_SET GPIO_PinWrite(GPIO3, LCD_SDA, 1)
- //#define LCD_CS_SET GPIO_PinWrite(GPIO3, LCD_CS, 1)
-
- #define LCD_RS_SET GPIO_PinWrite(LCD_RS_PORT, LCD_RS, 1)
- #define LCD_RST_SET GPIO_PinWrite(LCD_RST_PORT, LCD_RST, 1)
-
- //液晶控制口置0操作语句宏定义
- //#define LCD_SCL_CLR GPIO_PinWrite(GPIO3, LCD_SCL, 0)
- //#define LCD_SDA_CLR GPIO_PinWrite(GPIO3, LCD_SDA, 0)
- //#define LCD_CS_CLR GPIO_PinWrite(GPIO3, LCD_CS, 0)
- #define LCD_RS_CLR GPIO_PinWrite(LCD_RS_PORT, LCD_RS, 0)
- #define LCD_RST_CLR GPIO_PinWrite(LCD_RST_PORT, LCD_RST, 0)</font>
复制代码
接下来,要修改数据发送部分,改成使用SPI外设,每次发送一个字节。同时修改发送指令和发送数据时,DC(RS)的输出控制。 - <font face="Tahoma" size="4">//向SPI总线传输一个8位数据
- void SPI_WriteData(uint8_t Data) {
- masterXfer.txData = &Data;
- masterXfer.rxData = NULL;
- masterXfer.dataSize = 1;
- masterXfer.configFlags =
- EXAMPLE_LPSPI_MASTER_PCS_FOR_TRANSFER | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap;
-
- LPSPI_MasterTransferBlocking(EXAMPLE_LPSPI_MASTER_BASEADDR, &masterXfer);
-
- }
-
- //向液晶屏写一个8位指令
- void Lcd_WriteIndex(uint8_t Index) {
- //SPI 写命令时序开始
- //LCD_CS_CLR;
- LCD_RS_CLR;
- SPI_WriteData(Index);
- //LCD_CS_SET;
- }
-
- //向液晶屏写一个8位数据
- void Lcd_WriteData(uint8_t Data) {
- //LCD_CS_CLR;
- LCD_RS_SET;
- SPI_WriteData(Data);
- //LCD_CS_SET;
- }</font>
复制代码
接下来在PIN的初始化处理中,在原来代码的基础上加入RST和DC引脚的初始化处理 - <font face="Tahoma" size="4">// 控制DC和RST的口
- const port_pin_config_t port0_10_pinB12_config = {/* Internal pull-up/down resistor is disabled */
- kPORT_PullDisable,
- /* Low internal pull resistor value is selected. */
- kPORT_LowPullResistor,
- /* Fast slew rate is configured */
- kPORT_FastSlewRate,
- /* Passive input filter is disabled */
- kPORT_PassiveFilterDisable,
- /* Open drain output is disabled */
- kPORT_OpenDrainDisable,
- /* Low drive strength is configured */
- kPORT_LowDriveStrength,
- /* Pin is configured as PIO0_10 */
- kPORT_MuxAlt0,
- /* Digital input enabled */
- kPORT_InputBufferEnable,
- /* Digital input is not inverted */
- kPORT_InputNormal,
- /* Pin Control Register fields [15:0] are not locked */
- kPORT_UnlockRegister};
- /* PORT0_10 (pin B12) is configured as PIO0_10 */
- // 这个口作为TFT屏幕的DC(RS)控制口
- PORT_SetPinConfig(PORT0, 10U, &port0_10_pinB12_config);
- PORT_SetPinConfig(PORT0, 28U, &port0_10_pinB12_config);</font>
复制代码
这段代码参考了led_blinky。 在接下来在主程序中加入RST、DC对应管脚的输出方向的控制和TFT显示屏的初始化动作和显示语句。 - <font face="Tahoma" size="4">// 初始化管脚的输出电平
- GPIO_PinWrite(GPIO0, 10U, LOGIC_LED_OFF);
- GPIO_PinWrite(GPIO0, 28U, LOGIC_LED_ON);
- // PIO0_10、PIO0_28、PIO1_2:Output
- // 设置数据方向(输出)
- // LCD - DC(RS)
- GPIO0->PDDR |= (1U << 10U); // PIO0_10;
- GPIO0->PDDR |= (1U << 28U); // PIO0_28;</font>
复制代码
调整系统滴答器的频率 - <font face="Tahoma" size="4">SysTick_Config(12000UL);</font>
复制代码
这里改成12000UL是参考之前led_blinky工程。led_blinky工程中设置为12000000UL时,滴答器函数SysTick_Handler的调用周期为1秒,那么调整到1ms,就是改成12000UL,实际测试也确实是这样。但在lpspi例程中使用的是BOARD_BootClockPLL150M,那么SysTick_Config(12000UL)对应的滴答器是否是毫秒周期,我没有用示波器确认,暂且认为是正常的(实际上要是这个数据不正常,是非常有可能影响TFT显示屏的初始化的)。
然后信心满满地启动编译、测试,结果没有任何反应。哪怕是控制RST和DC的那两个引脚,也没有产生高低电平的而变化。TFT显示屏也没看到初始化的迹象。实测监测到SPI外设的数据输出有正常变化,但RST和DC没有正常输出该有的电平变化。接下来为这个过程,又折腾了一天,也没有啥成果。哪怕用单步调试、示波器监测引脚电平变化。简单想了想,应该是由于RST和DC没有正常工作,导致显示屏不能被正常初始化。对比led_blinky工程,发现初始化PIN的代码没有任何问题。 但在调试中发现一个有趣的现象,在主函数中,第一个语句“CLOCK_EnableClock(kCLOCK_Gpio0);”,是使能端口时钟的语句,而这条语句在执行BOARD_InitBootPins,经由BOARD_InitPins时,被又执行了一遍。如果主函数main中不要这一句,那么端口的输出控制就不能成功。同样,主函数中执行端口时钟使能,而在BOARD_InitPins中去掉端口时钟使能处理,结果是也不行。原因我是不懂,就是感觉挺神奇的。 在led_blinky工程的基础上,把SPI外设的处理和TFT显示屏的处理移植过来后,经过简单调整、编译、下载运行,发现TFT显示屏有变化了。再经过修改,已经可以正常显示了。然后对比frdmmcxn947_lpspi_polling_b2b_transfer_master例程,好像没啥变化,用这个例程测试,竟然也OK了。哈!真的是无语了。
|