FSMC驱动的显示屏使用DMA传输问题

2019-03-23 17:56发布

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

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

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

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

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

  6.         u32   TimeOver = 0xffffffff;

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

  12.         DMA_DeInit(DMA2_Stream1);
  13.         while ((DMA_GetCmdStatus(DMA2_Stream1) != DISABLE) && TimeOver)
  14.         {
  15.                 TimeOver--;
  16.         }

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

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

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

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

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



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

此帖出自小平头技术问答
0条回答