打印

STM32F103VET6 FSMC驱动R61581液晶屏的奇葩问题,请高手赐教

[复制链接]
3989|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jianghs521|  楼主 | 2013-11-18 20:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
长话短说。stm32f103vet6采用FSMC驱动3.5寸tft液晶屏(320*480)驱动芯片R61581。驱动成功了,但是刷屏速度非常慢大概刷一屏600~700ms,肯定有问题。下面说一下我使用的软硬件:
(1)软件环境IAR5.4
(2)重庆DQ电子的stm32开发板
(3)stm32的V3.5.0固件库
(4)移植的ucos2.92系统
我的系统下除了一个led闪烁任务,就是一个液晶屏刷屏任务,刷屏任务优先级最高。#define SYSCLK_FREQ_72MHz  72000000,系统时钟配置为72Mhz,采用固件库默认的/* HCLK = SYSCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;(即AHB总线速度是72Mhz,FSMC也是72Mhz吧?)这时刷屏特别慢600~700ms!!后来我把系统时钟设置为 #define SYSCLK_FREQ_56MHz  56000000,居然比72Mhz时快很多,刷屏速度能达到100ms左右,为真是怪了,请大神指点一下,不知道怎么回事!
最后我再把系统时钟定义为72Mhz,然后把/* HCLK = SYSCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV2;//修改后,居然速度变快了大概刷屏速度也能达到100ms左右。
真心求教!
以下是系统设置配置,和FSMC配置:
defined SYSCLK_FREQ_72MHz
/**
  * @brief  Sets System clock frequency to 72MHz and configure HCLK, PCLK2
  *         and PCLK1 prescalers.
  * @NOTE   This function should be used only after reset.
  * @param  None
  * @retval None
  */
static void SetSysClockTo72(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/   
  /* Enable HSE */   
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);

  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  

  if (HSEStatus == (uint32_t)0x01)
  {
    /* Enable Prefetch Buffer */
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /* Flash 2 wait state */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;   


    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
   
    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

#ifdef STM32F10X_CL
    /* Configure PLLs ------------------------------------------------------*/
    /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
        
    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
  
    /* Enable PLL2 */
    RCC->CR |= RCC_CR_PLL2ON;
    /* Wait till PLL2 is ready */
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
    {
    }
   
   
    /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
                            RCC_CFGR_PLLMULL9);
#else   
    /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
                                        RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
#endif /* STM32F10X_CL */

    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
   
    /* Select PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;   

    /* Wait till PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock
         configuration. User can add here some code to deal with this error */
  }
}


void FSMC_Configuration(void)
{
        FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
        FSMC_NORSRAMTimingInitTypeDef p;
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC , ENABLE);
               
        p.FSMC_AddressSetupTime = 1;
        p.FSMC_AddressHoldTime = 0;
        p.FSMC_DataSetupTime = 1;//改成2也试了,没效果
        p.FSMC_BusTurnAroundDuration = 0;
        p.FSMC_CLKDivision = 0;
        p.FSMC_DataLatency = 0;
        p.FSMC_AccessMode = FSMC_AccessMode_B;
       
        FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
        FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
        FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
        FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
        FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
        FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
        FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
        FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
        FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
        FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
        FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
        FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
        FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
        FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
        FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);

        FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
}

刷屏函数应该没问题,已经优化了。

沙发
jianghs521|  楼主 | 2013-11-18 20:53 | 只看该作者
在线等!!!

使用特权

评论回复
板凳
jianghs521|  楼主 | 2013-11-18 22:41 | 只看该作者
明天再等

使用特权

评论回复
地板
airwill| | 2013-11-19 09:04 | 只看该作者
我看还是刷屏函数的问题. 我用 FSMC 控制 ILI9320 320*240 可以达 20多屏每秒.
刷屏, 我用小块整块写的方式. 如果用逐个点的方式, 肯定会慢很多.

使用特权

评论回复
5
jianghs521|  楼主 | 2013-11-19 17:34 | 只看该作者
感谢您的回复,我就是用整块写程序,不是用的逐点

使用特权

评论回复
6
jianghs521|  楼主 | 2013-11-19 17:37 | 只看该作者
今天还是没调试好,HCLK在72Mhz的时候依然很慢,如果设置为56Mhz就快很多,请大神指点!

使用特权

评论回复
7
jianghs521|  楼主 | 2013-11-19 17:39 | 只看该作者
买液晶屏的时候卖家给的是在MDK4.2下面的程序(用FSMC驱动,刷屏挺快的),我自己改成IAR5.4下了,结果慢死了,刷一屏等1s左右。

使用特权

评论回复
8
jianghs521|  楼主 | 2013-11-19 21:45 | 只看该作者
刷屏都inline进去了,应该不是刷屏函数的问题吧
///////////////////////////////////////////////////////////////////////////////
//函数名:LCD_WR_REG
//描述  :R61851 写寄存器函数
//输入  :-index 寄存器
//输出  :无
//调用  :内部调用        
//////////////////////////////////////////////////////////////////////////////
static inline void LCD_WR_REG(u16 index)
{
    *(__IO u16 *) (Bank1_LCD_C) = index;
}

///////////////////////////////////////////////////////////////////////////////
//函数名:LCD_WR_Data
//描述  :R61851 向GRAM写入数据
//输入  :-val 写入的数据,16bit  
//输出  :无
//调用  :内部调用        
//////////////////////////////////////////////////////////////////////////////
static inline void LCD_WR_Data(unsigned int val)
{   
    *(__IO u16 *) (Bank1_LCD_D) = val;        
}

inline void LCD_Set_Window(u16 StartX,u16 StartY,u16 EndX,u16 EndY)      
{                                                                             
    LCD_WR_REG(0x002A);  //设置列地址
    LCD_WR_Data(StartX>>8);
    LCD_WR_Data(0x00FF&StartX);
    LCD_WR_Data(EndX>>8);
    LCD_WR_Data(0x00FF&EndX);

    LCD_WR_REG(0x002B);  //设置行地址
    LCD_WR_Data(StartY>>8);
    LCD_WR_Data(0x00FF&StartY);
    LCD_WR_Data(EndY>>8);
    LCD_WR_Data(0x00FF&EndY);

    LCD_WR_REG(0x003A);// 16/18 bits
    LCD_WR_Data(0x55);//16bits
    LCD_WR_REG(0x002C);//写液晶准备
}

void LCD_ColorBox(u16 xStart,u16 yStart,u16 xLong,u16 yLong,u16 Color)
{
    u32 temp;
    LCD_Set_Window(xStart,yStart,xStart+xLong-1,yStart+yLong-1);
    for (temp=0; temp<xLong*yLong; temp++)
    {       
        *(__IO u16 *) (Bank1_LCD_D) = Color;
    }
}

使用特权

评论回复
9
jianghs521|  楼主 | 2013-11-19 21:49 | 只看该作者
我用的这个函数测的系统主频:
INT32U  BSP_CPU_ClkFreq (void)
{
    RCC_ClocksTypeDef  rcc_clocks;     
    RCC_GetClocksFreq(&rcc_clocks);
    return ((INT32U)rcc_clocks.HCLK_Frequency);
}
串口1调试输出:
printf("  CPU Speed:%ld MHz  \r\n", BSP_CPU_ClkFreq() / 1000000L);

打印信息是:CPU Speed:72Mhz

但是刷屏却比系统频率为56MHZ时慢6~7倍(目测)

使用特权

评论回复
10
jianghs521|  楼主 | 2013-11-19 21:51 | 只看该作者
上源码!坐等大神

使用特权

评论回复
11
jianghs521|  楼主 | 2013-11-19 21:55 | 只看该作者
源码超过7M了传不了,真郁闷

使用特权

评论回复
12
jianghs521|  楼主 | 2013-11-20 21:00 | 只看该作者
求救啊!!!

使用特权

评论回复
13
jianghs521|  楼主 | 2013-11-23 11:56 | 只看该作者
经过几天的折腾终于发现问题了(IAR里的代码优化等级改为none就好了),但是还是不明白为什么?请大神指点。

使用特权

评论回复
14
cjhk| | 2013-11-23 18:19 | 只看该作者
这个问题   我也没有遇到过   楼主    不过   编译器   很多时候的设置  确实很重要   也比较难找

使用特权

评论回复
15
jianghs521|  楼主 | 2013-11-23 21:16 | 只看该作者
cjhk 发表于 2013-11-23 18:19
这个问题   我也没有遇到过   楼主    不过   编译器   很多时候的设置  确实很重要   也比较难找  ...

谢谢您,期待高人继续讨论

使用特权

评论回复
16
yicai1| | 2014-1-5 20:28 | 只看该作者
请教个问题,R61581可以读数据吗,为什么很多demo都没有这一步呢,请问楼主是尝试过吗?

使用特权

评论回复
17
jianghs521|  楼主 | 2014-1-18 14:54 | 只看该作者
R61581可以读数据,读三次分别去三个数据的前5、6、5位即可。

使用特权

评论回复
18
想跳水的朱| | 2020-12-10 13:40 | 只看该作者
用MCU直接描点切图,数据量大,MCU从FLASH读进来再往显存写进去,每一笔数据就要1读1写两个动作,MCU速度要非常快才行,且这样处理MCU大部分资源都要用到切图显示上,可靠性也不好。 可中间加个瑞佑RAIO的液晶屏控制IC,如RA8889,其直接挂FLASH, MCU发指令就可以把FLASH的图片数据DMA到显存上显示,显示数据不用通过MCU来处理,这样切图速度快,且MCU不用处理显示数据,可靠性也加强了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

14

帖子

0

粉丝