打印
[活动]

【极海G32A1465测评】4、SPI点亮LCD

[复制链接]
327|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 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,对应引脚复用:



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。
 {
        .base            = PMD,
        .pinPmIdx        = 0U,                        //LPSPI1_SCK
        .pullCfg         = PM_INTERNAL_PULL_NOT_ENABLED,
        .drvSel          = PM_LOW_DRIVE_STRENGTH,
        .passiveFilt     = false,
        .mux             = PM_MUX_ALT3,
        .pinLk           = false,
        .intCfg          = PM_DMA_INT_DISABLED,
        .clrInt**       = false,
        .gpioBase        = NULL,
        .digitFilt       = false,
    },
{
        .base            = PMD,
        .pinPmIdx        = 2U,                //LPSPI1_SOUT
        .pullCfg         = PM_INTERNAL_PULL_NOT_ENABLED,
        .drvSel          = PM_LOW_DRIVE_STRENGTH,
        .passiveFilt     = false,
        .mux             = PM_MUX_ALT3,
        .pinLk           = false,
        .intCfg          = PM_DMA_INT_DISABLED,
        .clrInt**       = false,
        .gpioBase        = NULL,
        .digitFilt       = false,
    },
               
                {
        .base            = PMD,
        .pinPmIdx        = 3U,                //LPSPI1_PCS0
        .pullCfg         = PM_INTERNAL_PULL_NOT_ENABLED,
        .drvSel          = PM_LOW_DRIVE_STRENGTH,
        .passiveFilt     = false,
        .mux             = PM_MUX_AS_GPIO,
        .pinLk           = false,
        .intCfg          = PM_DMA_INT_DISABLED,
        .clrInt**       = false,
        .gpioBase        = GPIOD,
        .dir             = GPIO_OUTPUT_DIR,
        .digitFilt       = false,
        .initVal         = 0U,
    },


三、spi配置

LPSPI_MASTER_CFG_T g_spiMasterCfg = {
    .bitNumber          = 8U,
    .baudBitsPer        = 10000000UL,
    .lpspiModSrcClk     = 48000000UL,
    .selectPcs          = NULL,//LPSPI_PER_PCS0,
    .selectPcsPolar     = LPSPI_SIGNAL_ACTIVE_HIGH,
    .selectClkPhase     = LPSPI_CLOCK_PHASE_CFG_1ST,
    .clkPolar           = LPSPI_CLK_SIGNAL_HIGH,
    .callback           = NULL,
    .callbackParam      = NULL,
    .pcsKeeps           = false,
    .sendLsbFirst       = false,
    .transferType       = LPSPI_TRANSFER_DMA,
    .rxDMAChan          = 0U,
    .txDMAChan          = 1U
};
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。
DMA_CHANNEL_CONFIG_T g_dmaChannel0Config = {
    .channelPriority = DMA_CHANNEL_DEFAULT_PRIORITY,
    .vtChannel = DMA_CHANNEL0_NUM,
    .source = DMA_REQUEST_LPSPI1_RX,
    .callback = NULL,
    .callbackParam = NULL,
    .enableTrigger = false,
};

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

七、运行效果


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




使用特权

评论回复
沙发
光影捕手| | 2024-12-20 09:30 | 只看该作者
念头通达!韩老魔是你?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

38

主题

79

帖子

0

粉丝