之前调的一款屏,参考了原子哥F103的SPI Flash到LCD的DMA,移植到F407上了,DMA显示成功!
最近换了一款屏,还是8080接口,显示都已经调好了,现在试了下Flash到LCD的DMA,并没有显示出来。
DMA相关的代码,和上一款屏是一模一样的,我一行都没改。
原子哥的代码中,在DMA之前,屏相关的寄存器就写了下面这一个,wramcmd的值我也确认过是对的。
void LCD_WriteRAM_Prepare(void)
{
LCD->LCD_REG=lcddev.wramcmd;
}
是否还有啥需要配或者改的呢?
void slcd_dma_init(void)
{
RCC->AHB1ENR|=1<<22; //DMA2时钟使能
while(DMA2_Stream2->CR&0X01);//等待DMA2_Stream2可配置
DMA2->LIFCR|=0X0F7D0F7D; //清空Stream2的通道0-3上所有中断标志
DMA2_Stream2->FCR=0X0000021;//设置为默认值
DMA2_Stream2->PAR=(u32)&SPI1->DR; //外设地址为:SPI1->DR
DMA2_Stream2->M0AR=(u32)&LCD->LCD_RAM; //目标地址为LCD_RAM
DMA2_Stream2->M1AR=0; //不用设置
DMA2_Stream2->NDTR=0; //暂时设置长度为0
DMA2_Stream2->CR=0; //先全部复位CR寄存器值
DMA2_Stream2->CR|=0<<6; //外设到存储器模式
DMA2_Stream2->CR|=0<<8; //普通模式
DMA2_Stream2->CR|=0<<9; //外设非增量模式
DMA2_Stream2->CR|=0<<10; //存储器非增量模式
DMA2_Stream2->CR|=1<<11; //外设数据长度:16位
DMA2_Stream2->CR|=1<<13; //存储器数据长度:16位
DMA2_Stream2->CR|=2<<16; //高优先级
DMA2_Stream2->CR|=0<<18; //单缓冲模式
DMA2_Stream2->CR|=0<<21; //外设突发单次传输
DMA2_Stream2->CR|=0<<23; //存储器突发单次传输
DMA2_Stream2->CR|=3<<25; //选择通道0
DMA2_Stream2->FCR&=~(1<<2); //不使用FIFO模式
DMA2_Stream2->FCR&=~(3<<0); //无FIFO 设置
}
void slcd_spi2_mode(u8 mode)
{
u16 tempreg=0;
if(mode==0) //8位普通模式,重新配置SPI
{
//这里只针对SPI口初始化
RCC->APB2RSTR|=1<<12; //复位SPI1
RCC->APB2RSTR&=~(1<<12);//停止复位SPI1
tempreg|=0<<10; //全双工模式
tempreg|=1<<9; //软件nss管理
tempreg|=1<<8;
tempreg|=1<<2; //SPI主机
tempreg|=0<<11; //8位数据格式
tempreg|=1<<1; //空闲模式下SCK为1 CPOL=1
tempreg|=1<<0; //数据采样从第2个时间边沿开始,CPHA=1
tempreg|=0<<3; //2分频,设置为42Mhz频率
tempreg|=0<<7; //MSB First
tempreg|=1<<6; //SPI启动
SPI1->CR1=tempreg; //设置CR1
SPI1->I2SCFGR&=~(1<<11);//选择SPI模式
}else //16位DMA模式
{
SPI1->CR1|=1<<10; //仅接收模式
SPI1->CR1|=1<<11; //16bit数据格式
SPI1->CR2|=1<<0; //使用DMA接收
}
}
void slcd_dma_enable()
{
u32 lcdsize=spbdev.spbwidth*spbdev.spbheight;
u32 dmatransfered=0;
while(lcdsize)
{
DMA2_Stream2->CR&=~(1<<0); //关闭DMA传输
while(DMA2_Stream2->CR&0X01); //等待DMA2_Stream2可配置
DMA2->LIFCR|=1<<21; //清除上次的传输完成标记
if(lcdsize>SLCD_DMA_MAX_TRANS)
{
lcdsize-=SLCD_DMA_MAX_TRANS;
DMA2_Stream2->NDTR=SLCD_DMA_MAX_TRANS; //设置传输长度
}else
{
DMA2_Stream2->NDTR=lcdsize; //设置传输长度
lcdsize=0;
}
// DMA2_Stream2->PAR=(u32)(sramlcdbuf+x*spbdev.spbheight+dmatransfered);
dmatransfered+=SLCD_DMA_MAX_TRANS;
DMA2_Stream2->CR|=1<<0; //开启DMA传输
while((DMA2->LISR&(1<<21))==0); //等待传输完成
}
DMA2_Stream2->CR&=~(1<<0); //关闭DMA传输
}
void slcd_frame_show(u16 x)
{
OS_CPU_SR cpu_sr=0;
u32 addr=SPILCD_BASE+1+(x*spbdev.spbheight)*2;
LCD_Scan_Dir(U2D_L2R); //设置扫描方向
if(lcddev.id==0X9341||lcddev.id==0X5310||lcddev.id==0X5510||lcddev.id==0X6804)
{
LCD_Set_Window(spbdev.stabarheight,0,spbdev.spbheight,spbdev.spbwidth);
LCD_SetCursor(spbdev.stabarheight,0);//设置光标位置
}else
{
LCD_Set_Window(0,spbdev.stabarheight,spbdev.spbwidth,spbdev.spbheight);
if(lcddev.id!=0X1963)LCD_SetCursor(0,spbdev.stabarheight);//设置光标位置
}
LCD_WriteRAM_Prepare(); //开始写入GRAM
W25QXX_CS=0; //使能器件
SPI1_ReadWriteByte(W25X_FastReadData); //发送快速读取命令
SPI1_ReadWriteByte((u8)((addr)>>16)); //发送24bit地址
SPI1_ReadWriteByte((u8)((addr)>>8));
SPI1_ReadWriteByte((u8)addr);
SPI1_ReadWriteByte(0XFF); //8 dummy clock
slcd_spi2_mode(1); //设置为16位宽,DMA接收
OS_ENTER_CRITICAL(); //进入临界区(无法被中断打断)
slcd_dma_enable(); //启动一次SPI到LCD的dma传输
OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
slcd_spi2_mode(0); //恢复8位模式
//加入读数据,判断是不是白屏.
W25QXX_CS=1; //禁止W25QXX
LCD_Scan_Dir(DFT_SCAN_DIR); //恢复默认方向
LCD_Set_Window(0,0,lcddev.width,lcddev.height);//恢复默认窗口大小
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一周热门 更多>