本帖最后由 momoto 于 2023-4-13 00:15 编辑
各位大佬好,我是刚学32的一个小白,在学习CH32V307驱动ST7789V时出现了花屏以及错位,显示效果如下
开发板:官方CH32V307V-R1-1v0开发板
LCD:金逸晨2.4寸 ST7789V 240*320 4线SPI接口
参考例程:中景园 2.4LCD显示屏STM32F103硬件SPI+DMA例程
曾尝试的方法:软件模拟SPI,以及硬件SPI都是正常的。当在硬件SPI中加入DMA时,刷图片就会出现上图中的哪种情况,所以我判定是我的DMA弄的有问题,可是搞了好几天还是没解决,希望大佬们指点下,感谢感谢。
以下为DMA相关的代码:
1. DMA配置void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输
DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值
DMA1_MEM_LEN=cndtr;
DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外设ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //数据传输方向,从内存读取发送到外设
DMA_InitStructure.DMA_BufferSize = cndtr; //DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度为8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA_CHx, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
}
//开启一次DMA传输
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
DMA_Cmd(DMA_CHx, DISABLE );
DMA_SetCurrDataCounter(DMA_CHx,DMA1_MEM_LEN);
DMA_Cmd(DMA_CHx, ENABLE);
}
2. ShowPicture的函数void LCD_ShowPicture(u16 x,u16 y,u16 length,u16 width,const u8 pic[])
{
u8 t=1;
u32 num=length*width*2,num1;
LCD_Address_Set(x,y,x+length-1,y+width-1);
LCD_CS_Clr();
while(t)
{
if(num>65534)
{
num-=65534;
num1=65534;
}
else
{
t=0;
num1=num;
}
MYDMA_Config(DMA1_Channel3,(u32)&SPI1->DATAR,(u32)pic,num1);
SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,ENABLE);
MYDMA_Enable(DMA1_Channel3);
while(1)
{
if(DMA_GetFlagStatus(DMA1_FLAG_TC3)!=RESET)//等待通道3传输完成
{
DMA_ClearFlag(DMA1_FLAG_TC3);//清除通道3传输完成标志
break;
}
}
pic+=65534;
}
LCD_CS_Set();
}
另外也贴下SPI的设置
// 使用硬件SPI1读写数据
void SPI1_Init(void)
{
// 开启响应的RCC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 初始化GPIOA引脚
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // SCK,MOSI配置为复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7; // PA5-->SCK,PA7-->MOSI
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_5|GPIO_Pin_7);
// 初始化SPI1
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // 传输模式2线全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // MCU作为主机
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // 使用软件进行片选
// 使用SPI的模式0
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // 时钟线默认为低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // 在时钟线的第一个边沿读取数据
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 数据帧大小为8位
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 数据传输时高位在前
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // SPI波特率分频因子为4分频
SPI_InitStructure.SPI_CRCPolynomial = 7; // SPI的CRC校验中多项式的值
SPI_Init(SPI1, &SPI_InitStructure);
// 使能SPI1
SPI_Cmd(SPI1, ENABLE);
}
|