原创 关于STM32 FSMC控制拓普微LM6029液晶模组出现"麻点"问题的解决

2010-4-29 10:27 5286 7 7 分类: 医疗电子
    工作中使用到100PIN的STM32和拓普微LM6029液晶模组,在需要读液晶内存的情况时,屏幕会出现麻点(即在文字周围随机的生成点),此问题苦恼了很久,降频,调整时序,改模拟总线,与同事前往拓普微公司都无法解决,而且也不是每块屏都会出现.
    TODAY,问题终于得到解决,总结造成问题的原因:
    1.由于此液晶模组属于黑白屏,其内部控制器不适合被高速的STM32所驱动,需要较大的降频与分频,以及时序也需要加大调整;
    2.由于100PIN的STM32的A0~A15地址线是与D0~D15复用的,较常用的将A0作RS控制线的方法不可行,所以使用了模拟IO的方法来生成RS信号,所以造成了STM32的FSMC信号的不完整,而此前这种方法应用到TFT彩屏上是没有问题的,但在拓普微的屏上就反应出问题了.

    解决方法:
    step1.将MCU倍频降到40M,并修改FSMC的时序如下:
    p.FSMC_AddressSetupTime = 5;
    p.FSMC_AddressHoldTime = 5;
    p.FSMC_DataSetupTime = 50;
    p.FSMC_BusTurnAroundDuration = 16;
    p.FSMC_CLKDivision = 16;
    p.FSMC_DataLatency = 17;
    p.FSMC_AccessMode = FSMC_AccessMode_A;

    step2.用FSMC的A16地址线自动生成液晶模组所需的RS信号,即往A16的地址分别写入命令值或数据值,代码如下:
    #define LCD_WR_REG(a)   {(*((volatile unsigned char *) 0x60000000)) = (a);}
    #define LCD_WR_RAM(a)   {(*((volatile unsigned char *) 0x60010000)) = (a);}

    u8 LCD_RD_RAM(void)   
    {
      return (*((volatile unsigned char *) 0x60010000));
    }

    对比之前使用模拟RS信号的代码:
    #define SET_RS  GPIO_SetBits(GPIOD,GPIO_Pin_11);
    #define CLR_RS  GPIO_ResetBits(GPIOD,GPIO_Pin_11);

    /* Note: LCD /CS is CE1 - Bank 4 of NOR/SRAM Bank 1~4 */
    #define LCD_BASE        ((u32)(0x60000000 | 0x0000000))
    #define LCD             ((LCD_TypeDef *) LCD_BASE)

    #define LCD_WR_REG(a)   {CLR_RS;LCD->LCD_REG = (a);}

    #define LCD_WR_RAM(a)   {SET_RS;LCD->LCD_RAM = (a);}

    typedef struct
    {
      vu8 LCD_REG;
      vu8 LCD_RAM;
    } LCD_TypeDef;

    u8 LCD_RD_RAM(void)    {SET_RS;return LCD->LCD_RAM;}

附图,所使用到的拓模组:
5f4a9695-30fc-462f-bc8c-911955a6c747.jpg

4/29/2010更新:
    以上都未真正解决问题,只是最大程度的降低了再现机率,但经过长时间验证,问题同样存在,真正解决问题的方法是弃用FSMC总线,用IO模拟并口,并在读数据前加入延时,底层代码如下:
#define SET_RS()  GPIOD->BSRR |= 0x00000800;
#define CLR_RS()  GPIOD->BSRR |= 0x08000000;
#define SET_nRD()  GPIOD->BSRR |= 0x00000010;
#define CLR_nRD()  GPIOD->BSRR |= 0x00100000;
#define SET_nWR()  GPIOD->BSRR |= 0x00000020;
#define CLR_nWR()  GPIOD->BSRR |= 0x00200000;
#define SET_nCS()  GPIOD->BSRR |= 0x00000080;
#define CLR_nCS()  GPIOD->BSRR |= 0x00800000;
#define SET_nRST()  GPIOD->BSRR |= 0x00001000;
#define CLR_nRST()  GPIOD->BSRR |= 0x10000000;

#define set_lcdbus(data) {GPIOE->CRL = 0x33333333; GPIOE->BSRR = (data & 0xff) | (~data & 0xff)<<16;}

u8 read_lcdbus(void)
{
    u8 data=0;
   
    GPIOE->CRL = 0x44444444; //浮空输入
    //GPIOE->CRL = 0x88888888; //x拉输入
    //GPIOE->CRL = 0xcccccccc; //reserved
   
    for(u8 i=0;i<5;i++);
   
    data = GPIOE->IDR & 0xff;
   
    return data;
}

//--------指令代码写入函数------------------
void LCD_WR_REG(u8 Command)
{
    CLR_RS();
    SET_nRD();
    CLR_nCS();
    set_lcdbus(Command);
    CLR_nWR();
    SET_nWR();
    SET_nCS();
}
//-----显示数据写入函数----------------------
void LCD_WR_RAM(u8 DData)
{
    SET_RS();
    SET_nRD();
    CLR_nCS();
    set_lcdbus(DData);
    CLR_nWR();
    SET_nWR();
    SET_nCS();
}
//-------显示数据读取函数---------------------
u8 LCD_RD_RAM()
{
    u8 DData;
    SET_RS();
    SET_nWR();
    CLR_nCS();   
    set_lcdbus(0xff);
    CLR_nRD();
    DData=read_lcdbus();
    SET_nRD();
    SET_nCS();
    return(DData);          // 返回数据值
}

    总结原因,STM32太快了也不是好事(PLL降低倍频,FSMC增大分频也是同样效果),很多外设跟芯片走的不是一个发展步伐。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
7
关闭 站长推荐上一条 /3 下一条