[活动] 【极海G32A1465测评】4、SPI点亮LCD

[复制链接]
 楼主| sujingliang 发表于 2024-12-16 20:01 | 显示全部楼层 |阅读模式
本帖最后由 sujingliang 于 2024-12-20 18:56 编辑

前不久购买了一个2.8寸TFT LCD 240*320,显示芯片为ILI9341。决定使用G32A1465驱动一下,但在MCU和LCD都是新的情况下,驱动起来还是花了一些时间。一方面需要修改ILI9341驱动代码做适配,另一方面要熟悉G32A1465的SPI和DMA模块。

G32A1465支持两种SPI:CFGIO_SPI和LPSPI。CFGIO是一个很意思的外设功能,应该是类似于NXP的FLEXIO,可以自定义IO的功能。感觉使用起来还是有些困难,先用LPSPI吧。


一、SPI选择
选用LPSP1,对应引脚复用:


21.png 22.png
PMD0---->LPSPI1_SCK     (SCK)
PMD1----> LPSPI1_SIN    (MISO)
PMD2----> LPSPI1_SOUT (MOSI)
PMD3----> LPSPI1_PCS0  (CS)

二、pin配置
由于是驱动LCD,实际上只需用MOSI和SCK就可以了。
在pin配置中,将PMD0配置为SPI SCK,PMD2配置为SPI MOSI,PMD3配置为gpio,自己控制SPI CS。
  1. {
  2.         .base            = PMD,
  3.         .pinPmIdx        = 0U,                        //LPSPI1_SCK
  4.         .pullCfg         = PM_INTERNAL_PULL_NOT_ENABLED,
  5.         .drvSel          = PM_LOW_DRIVE_STRENGTH,
  6.         .passiveFilt     = false,
  7.         .mux             = PM_MUX_ALT3,
  8.         .pinLk           = false,
  9.         .intCfg          = PM_DMA_INT_DISABLED,
  10.         .clrInt**       = false,
  11.         .gpioBase        = NULL,
  12.         .digitFilt       = false,
  13.     },
  14. {
  15.         .base            = PMD,
  16.         .pinPmIdx        = 2U,                //LPSPI1_SOUT
  17.         .pullCfg         = PM_INTERNAL_PULL_NOT_ENABLED,
  18.         .drvSel          = PM_LOW_DRIVE_STRENGTH,
  19.         .passiveFilt     = false,
  20.         .mux             = PM_MUX_ALT3,
  21.         .pinLk           = false,
  22.         .intCfg          = PM_DMA_INT_DISABLED,
  23.         .clrInt**       = false,
  24.         .gpioBase        = NULL,
  25.         .digitFilt       = false,
  26.     },
  27.                
  28.                 {
  29.         .base            = PMD,
  30.         .pinPmIdx        = 3U,                //LPSPI1_PCS0
  31.         .pullCfg         = PM_INTERNAL_PULL_NOT_ENABLED,
  32.         .drvSel          = PM_LOW_DRIVE_STRENGTH,
  33.         .passiveFilt     = false,
  34.         .mux             = PM_MUX_AS_GPIO,
  35.         .pinLk           = false,
  36.         .intCfg          = PM_DMA_INT_DISABLED,
  37.         .clrInt**       = false,
  38.         .gpioBase        = GPIOD,
  39.         .dir             = GPIO_OUTPUT_DIR,
  40.         .digitFilt       = false,
  41.         .initVal         = 0U,
  42.     },


三、spi配置

  1. LPSPI_MASTER_CFG_T g_spiMasterCfg = {
  2.     .bitNumber          = 8U,
  3.     .baudBitsPer        = 10000000UL,
  4.     .lpspiModSrcClk     = 48000000UL,
  5.     .selectPcs          = NULL,//LPSPI_PER_PCS0,
  6.     .selectPcsPolar     = LPSPI_SIGNAL_ACTIVE_HIGH,
  7.     .selectClkPhase     = LPSPI_CLOCK_PHASE_CFG_1ST,
  8.     .clkPolar           = LPSPI_CLK_SIGNAL_HIGH,
  9.     .callback           = NULL,
  10.     .callbackParam      = NULL,
  11.     .pcsKeeps           = false,
  12.     .sendLsbFirst       = false,
  13.     .transferType       = LPSPI_TRANSFER_DMA,
  14.     .rxDMAChan          = 0U,
  15.     .txDMAChan          = 1U
  16. };
baudBitsPer:SPI波特率。由于缺乏资料,这个不知道设成多大合适,是否有上限。先设成10000000UL
.lpspiModSrcClk = 48000000UL;:设置LPSPI模块的源时钟频率为48MHz。这个同上,由于缺乏资料,也不知道设成多大合适。 .selectPcs  =NULL,自己控制CS
下面三个参数和DMA有关:
.transferType = LPSPI_TRANSFER_DMA;:设置传输类型为直接存储器访问(DMA)。
.rxDMAChan = 0U;:设置接收DMA通道号为0。
.txDMAChan = 1U;:设置发送DMA通道号为1。


四、DMA配置
通道0配置为LPSPI1_RX,但是没有用。
通道1配置为LPSPI1_TX,用于MOSI。
  1. DMA_CHANNEL_CONFIG_T g_dmaChannel0Config = {
  2.     .channelPriority = DMA_CHANNEL_DEFAULT_PRIORITY,
  3.     .vtChannel = DMA_CHANNEL0_NUM,
  4.     .source = DMA_REQUEST_LPSPI1_RX,
  5.     .callback = NULL,
  6.     .callbackParam = NULL,
  7.     .enableTrigger = false,
  8. };

  9. DMA_CHANNEL_CONFIG_T g_dmaChannel1Config = {
  10.     .channelPriority = DMA_CHANNEL_DEFAULT_PRIORITY,
  11.     .vtChannel = DMA_CHANNEL1_NUM,
  12.     .source = DMA_REQUEST_LPSPI1_TX,
  13.     .callback = NULL,
  14.     .callbackParam = NULL,
  15.     .enableTrigger = false,
  16. };
五、初始化
1、PIN
  1. PINS_Init(NUM_OF_CONFIGURED_PINS0, g_spiPinsConfig);
2、DMA
  1. if(STATUS_SUCCESS==DMA_Init(&g_dmaState, &g_dmaInitConfig, g_dmaChannelStateArray,
  2.                                  g_dmaChannelConfigArray, DMA_CHANNELS_COUNT))
  3.                 {
  4.                          printf("DMA_Init success\r\n");
  5.                 };
3、LPSPI
  1. if(STATUS_SUCCESS==LPSPI_MasterInit(LPSPI_1, &g_spiState, &g_spiMasterCfg))
  2.                 {
  3.                         printf("LPSPI_MasterInit success\r\n");
  4.                 };
六、LCD驱动
SPI写一个byte
  1. void SPI_WriteaByte(uint8_t spiTxBuf)
  2. {
  3.         LPSPI_MasterTransferBlocking(LPSPI_1, &spiTxBuf, NULL, 1, SPI_TIMEOUT);
  4. }
SPI写多个byte
  1. void SPI_WriteByte(uint8_t *spiTxBuf,uint16_t len)
  2. {
  3.         LPSPI_MasterTransferBlocking(LPSPI_1, spiTxBuf, NULL, len, SPI_TIMEOUT);
  4. }
LCD之GPIO控制部分(CS、RS、RST、背光)
  1. #define        LCD_CS_SET  PINS_SetPins(GPIOD,1<<3)   //片选端口   D3
  2. #define        LCD_RS_SET        PINS_SetPins(GPIOB,1<<2)   //数据/命令          B2  
  3. #define        LCD_RST_SET        PINS_SetPins(GPIOD,1<<5)   //复位                          D5
LCD写命令
  1. void LCD_WR_REG(uint8_t data)
  2. {
  3.    LCD_CS_CLR;     
  4.          LCD_RS_CLR;         
  5.    SPI_WriteByte(&data,1);
  6.    LCD_CS_SET;        
  7. }
LCD写数据
  1. void LCD_WR_DATA(uint8_t data)
  2. {
  3.    LCD_CS_CLR;
  4.          LCD_RS_SET;
  5.                 SPI_WriteByte(&data,1);
  6.    LCD_CS_SET;
  7. }
LCD写寄存器
  1. void LCD_WriteReg(uint8_t LCD_Reg, uint16_t LCD_RegValue)
  2. {        
  3.         LCD_WR_REG(LCD_Reg);  
  4.         LCD_WR_DATA(LCD_RegValue);                             
  5. }           
LCD DMA清屏
  1. void LCD_Clear_DMA(uint16_t Color)
  2. {
  3.   unsigned int i,m;  
  4.         uint8_t aLine[LCD_W*2]={0};
  5.         
  6.         for(i=0;i<LCD_W;i++)
  7.         {
  8.                 aLine[2*i]=Color>>8;
  9.                 aLine[2*i+1]=Color;
  10.         }
  11.         LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);   
  12.         LCD_CS_CLR;
  13.         LCD_RS_SET;
  14.         for(i=0;i<lcddev.height;i++)
  15.         {
  16.     SPI_WriteByte(aLine,LCD_W*2);
  17.         }
  18.          LCD_CS_SET;
  19. }

七、运行效果

tutieshi_480x272_7s.gif
感觉还有优化的空间。时钟、SPI参数还可以调一调。
调了一下LPSPI1_CLK:
  1. {
  2.         .clkName = LPSPI1_CLK,
  3.         .clkSrc = CLK_SRC_HSI_DIV1,//CLK_SRC_LSI_DIV2,
  4.         .clkGate = true,
  5.         .div = DIV_BY_ONE,
  6.         .frac = MUL_BY_ONE,
  7.     },
选择内部高速时钟48Mhz
tutieshi_480x270_5s (1).gif



光影捕手 发表于 2024-12-20 09:30 | 显示全部楼层
念头通达!韩老魔是你?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

84

主题

146

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部