本帖最后由 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
|
|