高级会员 
  
	- 积分
 - 857
 
        - 金钱
 - 857 
 
       - 注册时间
 - 2018-12-19
 
      - 在线时间
 - 174 小时
 
 
 
 | 
 
 本帖最后由 854278507 于 2024-4-26 22:49 编辑  
 
正点原子提供的LCD_Fill函数是使用CPU运算的方式,整屏填充需要10.375ms,算下来就是48.131帧,虽然已经很快了,但是如果使用DMA,还可以更快 
下面是我修改后的LCD_Fill函数 
- // 在指定区域内填充单个颜色
 
 - //(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)
 
 - // color:要填充的颜色
 
 - void LCD_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color)
 
 - {
 
  
-     uint16_t i, j;
 
 -     uint16_t xlen = 0;
 
 -     uint16_t temp;
 
  
 
-     if ((lcddev.id == 0x6804) && (lcddev.dir == 1)) // 6804横屏的时候特殊处理
 
 -     {
 
 -         temp = sx;
 
 -         sx = sy;
 
 -         sy = lcddev.width - ex - 1;
 
 -         ex = ey;
 
 -         ey = lcddev.width - temp - 1;
 
 -         lcddev.dir = 0;
 
 -         lcddev.setxcmd = 0x2A;
 
 -         lcddev.setycmd = 0x2B;
 
 -         LCD_Fill(sx, sy, ex, ey, color);
 
 -         lcddev.dir = 1;
 
 -         lcddev.setxcmd = 0x2B;
 
 -         lcddev.setycmd = 0x2A;
 
 -     }
 
 -     else
 
 -     {
 
 - #if 1
 
 -         uint16_t width;
 
 -         uint16_t height;
 
 -         
 
 -         width = ex - sx + 1;
 
 -         height = ey - sy + 1;
 
 -         
 
 -         
 
 -         
 
 -         LCD_Set_Window(sx, sy, width, height);
 
 -         LCD_WriteRAM_Prepare();
 
 -         
 
 -         uint32_t lcdsize = width * height;
 
 -         uint32_t dmatransfered = 0;
 
 -         
 
 -         uint16_t color_buf[2];
 
 -         
 
 -         color_buf[0] = color;
 
 -         color_buf[1] = color;
 
 -         
 
  
-         DMA_InitTypeDef DMA_InitStruct;
 
 -         
 
 -         lcdsize /= 2; /* 使用32位宽数据传输,数据量减少一半 */
 
 -         
 
 -         DMA_InitStruct.DMA_PeripheralBaseAddr  = (uint32_t)&LCD->LCD_RAM;   /* 外设地址为LCD_RAM */   
 
 -         DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)color_buf;            /* 内存地址为显示缓存 */
 
 -         DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;                     /* DMA方向为内存到外设 */    
 
 -         DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;       /* 外设地址固定 */
 
 -         DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Disable;               /* 内存地址固定 */
 
 -         DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;/* 外设数据宽度32位 */
 
 -         DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;        /* 内存数据宽度32位 */
 
 -         DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;                          /* 普通模式 */
 
 -         DMA_InitStruct.DMA_Priority = DMA_Priority_High;                    /* DMA优先级为高 */
 
 -         DMA_InitStruct.DMA_M2M = DMA_M2M_Enable;                            /* 内存到内存模式(不需要外部触发) */   
 
 -         
 
 -         while (lcdsize)
 
 -         {
 
 -             if (lcdsize >= 65535)
 
 -             {
 
 -                 DMA_InitStruct.DMA_BufferSize = 65535; /* 单次数据传输量不能超过65535 */
 
 -                 lcdsize -= 65535;
 
 -                 dmatransfered += 65535;
 
 -             }
 
 -             else
 
 -             {
 
 -                 DMA_InitStruct.DMA_BufferSize = lcdsize;
 
 -                 lcdsize = 0;
 
 -             }
 
 -             
 
 -             DMA_Init(DMA2_Channel5, &DMA_InitStruct);
 
 -             
 
 -             DMA_Cmd(DMA2_Channel5, ENABLE);
 
 -             
 
 -             while (DMA_GetFlagStatus(DMA2_FLAG_TC5) == RESET)
 
 -             {
 
 -                 
 
 -             }            
 
 -             
 
 -             DMA_ClearFlag(DMA2_FLAG_TC5);
 
  
-         }
 
 -         DMA_Cmd(DMA2_Channel5, DISABLE);
 
 -         
 
 -         LCD_Set_Window(0, 0, lcddev.width, lcddev.height);
 
 - //        LCD_WriteRAM_Prepare();
 
 -         
 
 - #else
 
 -         
 
 -         xlen = ex - sx + 1;
 
 -         for (i = sy; i <= ey; i++)
 
 -         {
 
 -             LCD_SetCursor(sx, i);      // 设置光标位置
 
 -             LCD_WriteRAM_Prepare();    // 开始写入GRAM
 
 -             for (j = 0; j < xlen; j++) // 显示颜色
 
 -             {
 
 -                 LCD->LCD_RAM = color;
 
 -             }
 
 -         }
 
 -         
 
 - #endif /* 0 */
 
 -     }
 
 - }
 
  复制代码 可能会有人有疑问,LCD是16位的8080 16位的接口,怎么可以使用32位的数据传输,实际上是可以的,也可以改成16位传输,这样速度会慢一点,因为 240 * 320 的屏用16位传输需要写 240 * 320 = 76800次,而STM32F103的DMA一次最多只能传输65535个数据,需要分两次传输,如果用32位传输就只需要 240 * 320 / 2 = 38400次,DMA一次就可以传输完成。 
由于是单色填充,需要先定义一个数组,填充好要用的颜色数值,然后把这地址设置为DMA的内存地址,初始化DMA的时候要设置内存地址不自增,这样就可以快速整屏填充了。 
 
下面是没有使用DMA刷屏速度截图 
 
 
从上面的图片可以看出没有使用DMA的时候刷一屏需要10.375ms,刷屏速度48.131帧。 
 
下面是使用DMA刷屏速度截图 
 
 
从上面的图片可以看出使用DMA后刷一屏只需要6.411ms,刷屏速度77.99帧。 
 
下面放上测试刷屏速度的代码 
 
- void lcd_test_play(void)
 
 - {
 
 - #if 1
 
  
-     const uint16_t color_table[] = 
 
 -     {
 
 -         //画笔颜色
 
 -         WHITE             ,
 
 -         BLACK             ,
 
 -         BLUE              ,
 
 -         BRED              ,
 
 -         GRED                           ,
 
 -         GBLUE                          ,
 
 -         RED               ,
 
 -         MAGENTA           ,
 
 -         GREEN             ,
 
 -         CYAN              ,
 
 -         YELLOW            ,
 
 -         BROWN                           ,
 
 -         BRRED                           ,
 
 -         GRAY                            ,
 
 -         DARKBLUE          ,
 
 -         LIGHTBLUE         ,
 
 -         GRAYBLUE          ,
 
 -         LIGHTGREEN        ,
 
 -         LGRAY                           ,
 
 -         LGRAYBLUE         ,
 
 -         LBBLUE            ,
 
 -     };
 
 -        
 
 -     uint8_t i;
 
  
-     
 
  
-     spb_delete();
 
 -         printf("\r\n[%s][%s][%04d]LCD刷屏 %d",
 
 -                __FILE__, __func__, __LINE__, system_task_return); 
 
 -     system_task_return = 0;
 
 -     
 
 -     while (1)
 
 -     {
 
 -         for (i = 0; i < sizeof(color_table) / 2; i++)
 
 -         {
 
 -             LCD_Fill(0, 0, lcddev.width - 1, lcddev.height - 1, color_table[i]);    
 
 -             LED_1_Turn();
 
 -         }
 
 -         
 
 -         if (system_task_return == 1)
 
 -         {
 
 -             if (TPAD_Scan(1))
 
 -             {
 
 -                 break;
 
 -             }
 
 -             else
 
 -             {
 
 -                 system_task_return = 0;
 
 -             }
 
 -         }
 
 -     }
 
 -     LED_1_Off();  
 
 -     
 
 - #else
 
 -  
 
  
-     uint16_t r;
 
 -     uint16_t g;
 
 -     uint16_t b;
 
 -     
 
  
-     spb_delete();
 
 -         printf("\r\n[%s][%s][%04d]LCD刷屏 %d",
 
 -                __FILE__, __func__, __LINE__, system_task_return); 
 
 -     system_task_return = 0;
 
 -     
 
 -     while (1)
 
 -     {
 
 - #define LCD_DELAY 20
 
  
-         for (r = 0; r < (1 << 5); r++)
 
 -         {
 
 -             for (g = 0; g < (1 << 6); g++)
 
 -             {
 
 -                 for (b = 0; b < (1 << 5); b++)
 
 -                 {
 
 -                     LCD_Fill(0, 
 
 -                     0, 
 
 -                     lcddev.width - 1,
 
 -                     lcddev.height - 1, 
 
 -                     (r << 11) | (g << 5) | b);
 
 -                     LED_1_Turn();
 
 -                     OSTimeDly(LCD_DELAY);
 
 -                 }
 
 -                 for (b = (1 << 5); b > 0; b--)
 
 -                 {
 
 -                     LCD_Fill(0, 
 
 -                     0, 
 
 -                     lcddev.width - 1,
 
 -                     lcddev.height - 1, 
 
 -                     (r << 11) | (g << 5) | b);
 
 -                     LED_1_Turn();
 
 -                     OSTimeDly(LCD_DELAY);
 
 -                 }                
 
 -             }
 
 -             for (g = (1 << 6); g > 0; g--)
 
 -             {
 
 -                 for (b = 0; b < (1 << 5); b++)
 
 -                 {
 
 -                     LCD_Fill(0, 
 
 -                     0, 
 
 -                     lcddev.width - 1,
 
 -                     lcddev.height - 1, 
 
 -                     (r << 11) | (g << 5) | b);
 
 -                     LED_1_Turn();
 
 -                     OSTimeDly(LCD_DELAY);
 
 -                 }
 
 -                 for (b = (1 << 5); b > 0; b--)
 
 -                 {
 
 -                     LCD_Fill(0, 
 
 -                     0, 
 
 -                     lcddev.width - 1,
 
 -                     lcddev.height - 1, 
 
 -                     (r << 11) | (g << 5) | b);
 
 -                     LED_1_Turn();
 
 -                     OSTimeDly(LCD_DELAY);
 
 -                 }                
 
 -             }            
 
 -         }
 
 -         
 
 -         for (r = (1 << 5); r > 0; r--)
 
 -         {
 
 -             for (g = 0; g < (1 << 6); g++)
 
 -             {
 
 -                 for (b = 0; b < (1 << 5); b++)
 
 -                 {
 
 -                     LCD_Fill(0, 
 
 -                     0, 
 
 -                     lcddev.width - 1,
 
 -                     lcddev.height - 1, 
 
 -                     (r << 11) | (g << 5) | b);
 
 -                     LED_1_Turn();
 
 -                     OSTimeDly(LCD_DELAY);
 
 -                 }
 
 -                 for (b = (1 << 5); b > 0; b--)
 
 -                 {
 
 -                     LCD_Fill(0, 
 
 -                     0, 
 
 -                     lcddev.width - 1,
 
 -                     lcddev.height - 1, 
 
 -                     (r << 11) | (g << 5) | b);
 
 -                     LED_1_Turn();
 
 -                     OSTimeDly(LCD_DELAY);
 
 -                 }                
 
 -             }
 
 -             for (g = (1 << 6); g > 0; g--)
 
 -             {
 
 -                 for (b = 0; b < (1 << 5); b++)
 
 -                 {
 
 -                     LCD_Fill(0, 
 
 -                     0, 
 
 -                     lcddev.width - 1,
 
 -                     lcddev.height - 1, 
 
 -                     (r << 11) | (g << 5) | b);
 
 -                     LED_1_Turn();
 
 -                     OSTimeDly(LCD_DELAY);
 
 -                 }
 
 -                 for (b = (1 << 5); b > 0; b--)
 
 -                 {
 
 -                     LCD_Fill(0, 
 
 -                     0, 
 
 -                     lcddev.width - 1,
 
 -                     lcddev.height - 1, 
 
 -                     (r << 11) | (g << 5) | b);
 
 -                     LED_1_Turn();
 
 -                     OSTimeDly(LCD_DELAY);
 
 -                 }                
 
 -             }            
 
 -         }        
 
 -         
 
 -         if (system_task_return == 1)
 
 -         {
 
 -             if (TPAD_Scan(1))
 
 -             {
 
 -                 break;
 
 -             }
 
 -             else
 
 -             {
 
 -                 system_task_return = 0;
 
 -             }
 
 -         }
 
 -     }
 
 -     LED_1_Off();    
 
 -     
 
 - #endif /* 1 */
 
 -    
 
 -     
 
 - }
 
 
  复制代码 
 
 |   
 
 
 
 |