本帖最后由 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_InitTypeDef DMA_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刷屏的实验,麻烦帮我分析以下这样的问题,谢谢大家!
|
FSMC_NORSRAMTimingInitTypeDef p;
GPIO_InitTypeDef GPIO_InitStructure;
//config SRAM DATA lines configuration D0------->>D15
//please reference STC datasheet FSMC PINs Page37
//D0---->>D3 D13------->>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);
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);