SPI到LCD的DMA如何调试呢

2019-07-20 23:49发布

之前调的一款屏,参考了原子哥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);//恢复默认窗口大小         
}



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。