liutogo 发表于 2016-11-20 12:02:04

【求助】F207用DMA方式驱动FSMC接口的LCD屏的问题

本帖最后由 liutogo 于 2016-11-20 12:03 编辑

最近在做的项目中有一个480x320的彩屏,刷屏比较慢,需要提速,于是乎想到了DMA。
屏与STM32使用16Bit总线连接,使用FSMC传输方式。

对于写数据LCD也就是写(0x60000000 | 0x08080000)空间

在STM32F2的DMA2支持Memory to Memory的DMA传输方式

写DMA驱动初始化如下:
uint8_t Image_DMA_init(void)
{
DMA_InitTypeDefDMA_InitStructure = {0};               
      //注意,由于在本函数中该结构体仅被部分初始化,必须在定义该局部变量时对其进行0初始化,否则将出现不可预料的错误。
      
      u32      TimeOver = 0xffffffff;

/* 此处需要使用Memory to Memory的DMA传输,仅DMA2支持此种传输*/
/* 此处使用DMA2Stream1 */
/* Ref:ST RM0033 Rev7 P183 Memory-to-memory mode */
/* Enable DMA clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);               

DMA_DeInit(DMA2_Stream1);      
while ((DMA_GetCmdStatus(DMA2_Stream1) != DISABLE) && TimeOver)
      {
                TimeOver--;      
      }

      if(!TimeOver){
                return !0;
      }
      /*      IN Memory-to-memory mode, DMA channels work without being triggered by a request from a peripheral
                So,DMA parameter DMA_Channel do not need to be assigned */
      //DMA_InitStructure.DMA_Channel = DMA_Channel_3;               

      /* Memory-to-memory mode Sourece Address: DMA_SxPAR Destination Address:DMA_SxM0AR */
      /* 初始化时不需要指定源地址,传输前指定 */
//DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(SPI1->DR));//0x4001300C;

/* 目的地址为LCD控制器对应的FSMC接口 */
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&LCD2->LCD_RAM;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;

      /* 初始化时不需要指定传输数据数,传输前指定NDTR */
//DMA_InitStructure.DMA_BufferSize = BGPIC_WIDTH * BGPIC_HEIGH << 1;               
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
/* When memory-to-memory mode is used, the Circular and direct modes are not allowed. */
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream1, &DMA_InitStructure);
/* DMA Stream enable */
DMA_Cmd(DMA2_Stream1, DISABLE);


return 0;
}DMA传输方式为从Memory的图像缓冲区地址空间(16位宽,递增),向(0x60000000 | 0x08080000)地址空间(16位宽,不递增)传输数据。
可是遇到的问题是:
每次传输(NDTR = 1下)本来应该只触发一次16Bit传输的FSMC时序(16Bit位宽的 565 RGB数据,对应一个像素点),实际被分成两次传输,触发了两次FSMC的写时序,结果在屏上绘制了两个点。



大家有没有类似的做过使用DMA通过FSMC刷屏的实验,麻烦帮我分析以下这样的问题,谢谢大家!

Robot@HCS 发表于 2016-12-15 16:25:23

FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
FSMC_NORSRAMTimingInitTypeDef p;
GPIO_InitTypeDef GPIO_InitStructure;


    //config SRAM DATA lines configuration D0------->>D15
//please reference STC datasheet FSMC PINs Page37
//D0---->>D3D13------->>D15
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | GPIO_Pin_9 |
                                  GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);

//D4----->>D12
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
      GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
      GPIO_Pin_15;
GPIO_Init(GPIOE, &GPIO_InitStructure);

    //config SRAM ADRESS lines configuration A0------->>A18
//please reference STC datasheet FSMC PINs Page37
//A0------>>A9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 |
                           GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_12 | GPIO_Pin_13 |
                           GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOF, &GPIO_InitStructure);

//A10---->>A15
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 |
                           GPIO_Pin_4 | GPIO_Pin_5;
GPIO_Init(GPIOG, &GPIO_InitStructure);

//A16------->>A18
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 ;
GPIO_Init(GPIOD, &GPIO_InitStructure);

    //config SRAM NOE NWE lines configuration
//please reference STC datasheet FSMC PINs Page37
//NOE-->PD4   
//NWE ----->PD5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 |GPIO_Pin_5;
GPIO_Init(GPIOD, &GPIO_InitStructure);

    //config SRAM NE3 lines configuration
//please reference STC datasheet FSMC PINs Page37
//NE4-->PG12
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOG, &GPIO_InitStructure);

    //config SRAM NBL0, NBL1 lines configuration
//please reference STC datasheet FSMC PINs Page37
//NBL0(LB)-->PE0 NBL1(UB)-->PE1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_Init(GPIOE, &GPIO_InitStructure);



//FSMC Structure Config
p.FSMC_AddressSetupTime = 0;//The time is used for duration address set up time
p.FSMC_AddressHoldTime = 0;//The time is used for duration address hold time
p.FSMC_DataSetupTime = 2;//The time is used for duration data set up time
p.FSMC_BusTurnAroundDuration = 0;//The time is used for the duration Bus turn
p.FSMC_CLKDivision = 0;//The division of HCLK
p.FSMC_DataLatency = 0;//The time is memory clock cycle before get first data
p.FSMC_AccessMode = FSMC_AccessMode_A;//


FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;//choose FSMC bank
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;//Address and Data line is not muxed
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;//The type of externed memory
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;//The memory data widthy
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;//disable burst access ,because this is only used for synchronous memory
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;//only used in burst mode
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; //only used in burst mode
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;//only used in burst mode
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;//enable write
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;//only used in burst mode
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;//disable extended mode
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;//disable burst write mode
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;

FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);

//enable FSMC bank1_NORSRAM
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);

Robot@HCS 发表于 2016-12-15 16:26:08

DMA_InitTypeDefDMA_InitStructure;

DMA_DeInit(DMA1_Channel4);
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)SRC_Const_Buffer;//The address of peripheral
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Bank1_SRAM3_ADDR;//The DAM RAM address
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//Peripheral is the source of data
DMA_InitStructure.DMA_BufferSize =32;//32 times
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;//The address of peripheral will be added
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//The address of DMA will be added
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;//32 bits
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;//32 bits
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//DMA Work in normal mode,not Circle
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA high Priority
DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;// enable Memory to Memory transfer

DMA_Init(DMA1_Channel4, &DMA_InitStructure);

//Enable DMA1 channel 4 transfer complete interrupt
DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);
//clear the flag
DMA_ClearFlag(DMA1_FLAG_TC4);

//Enable DAM1 channel4 transfer
DMA_Cmd(DMA1_Channel4, ENABLE);
页: [1]
查看完整版本: 【求助】F207用DMA方式驱动FSMC接口的LCD屏的问题