STM 32:FSMC駆動TFT LCD(ST 7789)

17733 ワード

最近プロジェクトはSTM 32 F 407を使ってtftカラースクリーンを駆動して、スクリーンの内部の駆動チップはST 7789 Vで、このICのネット上の資料は多くありません.
くだらないことは言わないで、直接完全な駆動コードに行きます.
1.コード
/*
*************************************************************************************************
*
*         : TFT         
*         : lcd_drv.h
*           : V1.0
*           :    .
*               lcddrv_FillColorPre    LCD    ,       LCDDRV_RAM       .
*                         lcddrv_FillColorPre  LCDDRV_RAM  
***************************************************************************************************
*/

#ifndef __LCD_DRV_H
#define __LCD_DRV_H

#include "stm32f4xx.h"

#define ST7789_REG        *(__IO u16 *)(((uint32_t)0x60000000))
#define ST7789_RAM        *(__IO u16 *)(((uint32_t)0x60000000) + (1 << 17)) //A16   1 

/******************* bsp     API**********************/
//      
#define BRIGHT_MAX        100
#define BRIGHT_MIN        0
#define BRIGHT_DEFAULT    BRIGHT_MAX

#define LCD_WIDTH   320  //         
#define LCD_HEIGHT  240  //         
#define LCDDRV_RAM  ST7789_RAM      //  GRAM    

extern void lcddrv_Init(void);      //     
extern void lcddrv_FillColorPre(u16 X, u16 Y, u16 Width , u16 Height);
extern void lcddrv_SetBackLight(u8 bright);//    
extern void lcddrv_DispOn(void);    //    
extern void lcddrv_DispOff(void);   //    

#endif

/***************************** (END OF FILE) *********************************/
#include "stm32f4xx.h"
#include 
#include 
#include "delay.h"
#include "lcd_drv.h"

#define lcddelay_ms(n) delay_ms(n)
#define LCD_RST_PIN  PFout(15)

//ST7789     
#define  ST7789_CMD_RDDID 0x04  //  ID
#define  ST7789_CMD_SLPIN 0x10
#define  ST7789_CMD_SLPOUT 0x11
#define  ST7789_CMD_DISPOFF 0x28
#define  ST7789_CMD_DISPON 0x29
#define  ST7789_CMD_CASETF 0x2A
#define  ST7789_CMD_RASETF 0x2B
#define  ST7789_CMD_RAMWR 0x2C  //       
#define  ST7789_CMD_PTLON 0x12  //      
#define  ST7789_CMD_NORON 0x13  //    
#define  ST7789_CMD_INVOFF 0x20 //     
#define  ST7789_CMD_INVON 0x21  //     
#define  ST7789_CMD_PTLAR 0x30  //                

//    (CMD)
//regval:    
static void ST7789_WR_REG(vu16 regval)
{
    regval = regval;        
    ST7789_REG = regval;    
}
//   
//data:     
static void ST7789_WR_DATA(vu16 data)
{
    data = data;          
    ST7789_RAM = data;
}
// LCD  
//   :    
static u16 ST7789_RD_DATA(void)
{
    vu16 ram;            
    ram = ST7789_RAM;
    return ram;
}

/*
*********************************************************************************************
*         : ST7789_ReadID
*        :   LCD    ID
*          :   
*         :  
*********************************************************************************************
*/
u16 ST7789_ReadID(void)
{
    u16 id = 0;
    ST7789_WR_REG(ST7789_CMD_RDDID);
    ST7789_RD_DATA();
    id = ST7789_RD_DATA();
    ST7789_RD_DATA();
    ST7789_RD_DATA() ;
    return id ;
}

/*
****************************************************************************************
*         : ST7789_REG_Init
*        :    LCD       
*          :   
*         :  
****************************************************************************************
*/
static void ST7789_REG_Init(void)
{
    /*    LCD, LCD        */
    lcddelay_ms(10);
    ST7789_WR_REG(ST7789_CMD_SLPOUT);    //exit SLEEP mode
    lcddelay_ms(150);

    ST7789_WR_REG(0x00D0);  //PWCTRL1: Power Control 1
    ST7789_WR_DATA(0x00A4);
    ST7789_WR_DATA(0x81);

    ST7789_WR_REG(0x00BB);
    ST7789_WR_DATA(0x0030);  //VCOMS: VCOM setting

    ST7789_WR_REG(0x0036);  //memory data access control
    ST7789_WR_DATA(0x60);   //MADCTL:     

    ST7789_WR_REG(0x003A);  // Interface Pixel Format
    ST7789_WR_DATA(0x05);   //COLMOD: 16bit

    ST7789_WR_REG(0x00E0);
    ST7789_WR_DATA(0x00D0);
    ST7789_WR_DATA(0x0000);
    ST7789_WR_DATA(0x0002);
    ST7789_WR_DATA(0x0007);
    ST7789_WR_DATA(0x000B);
    ST7789_WR_DATA(0x001A);
    ST7789_WR_DATA(0x0031);
    ST7789_WR_DATA(0x0054);
    ST7789_WR_DATA(0x0040);
    ST7789_WR_DATA(0x0029);
    ST7789_WR_DATA(0x0012);
    ST7789_WR_DATA(0x0012);
    ST7789_WR_DATA(0x0012);
    ST7789_WR_DATA(0x0017);            

    ST7789_WR_REG(0x00E1);
    ST7789_WR_DATA(0x00D0);
    ST7789_WR_DATA(0x0000);
    ST7789_WR_DATA(0x0002);
    ST7789_WR_DATA(0x0007);
    ST7789_WR_DATA(0x0005);
    ST7789_WR_DATA(0x0025);
    ST7789_WR_DATA(0x002D);
    ST7789_WR_DATA(0x0044);
    ST7789_WR_DATA(0x0045);
    ST7789_WR_DATA(0x001C);
    ST7789_WR_DATA(0x0018);
    ST7789_WR_DATA(0x0016);
    ST7789_WR_DATA(0x001C);
    ST7789_WR_DATA(0x001D);            

    ST7789_WR_REG(0x21);//  

    ST7789_WR_REG(ST7789_CMD_DISPON);// DISPALY ON
    lcddelay_ms(100);
}


/*
***************************************************************************************************
*         : ST7789_Init
*        :    LCD
*          :  
*         : 0/1:  /  
***************************************************************************************************
*/
u8 ST7789_Init(void)
{
    //   
    LCD_RST_PIN = 1 ;
    lcddelay_ms(3);
    LCD_RST_PIN = 0 ;
    lcddelay_ms(6);
    LCD_RST_PIN = 1 ;
    lcddelay_ms(150);

    if ( ST7789_ReadID() == 0x85 )
    {
        ST7789_REG_Init();    /*     IC    */
        return 1;
    }
    return 0;
}

/*
*************************************************************************************************
*         : STM_GPIOConfig
*        :   LCD    ,FSMC    
*          :  
*         :  
*************************************************************************************************
*/
/*
    LCD  RS(DC)      PD11/FSMC_A16 (0  ,1  )
    LCD  CS        PD7/FSMC_NE1
        NWE, NOE, D15~D0     FSMC    。
        :

    PD0/FSMC_D2
    PD1/FSMC_D3
    PD4/FSMC_NOE        ---      ,OE , N      ( )
    PD5/FSMC_NWE        ---      ,WE  ,N      ( )
    PD7/FSMC_NE1        ---    ,    CS
    PD8/FSMC_D13
    PD9/FSMC_D14
    PD10/FSMC_D15
    PD11/FSMC_A16        ---    RS DC (  OR    )
    PD14/FSMC_D0
    PD15/FSMC_D1

    PE7/FSMC_D4
    PE8/FSMC_D5
    PE9/FSMC_D6
    PE10/FSMC_D7
    PE11/FSMC_D8
    PE12/FSMC_D9
    PE13/FSMC_D10
    PE14/FSMC_D11
    PE15/FSMC_D12

    ----  TFT LCD       ( FSMC   )----

    PC13/LCD_PWM            --- LCD  PWM                 
    PF15/LCD_RST            ---    LCD
*/
static void STM_GPIOConfig(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    /*    GPIO   */
    RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | 
                            RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOF, ENABLE);

    /*   FSMC   */
    RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);

    /*    PD.00(D2), PD.01(D3), PD.04(NOE), PD.05(NWE), PD.08(D13), PD.09(D14),
     PD.10(D15), PD.14(D0), PD.15(D1)         + PD11(DC), PD7(CS) */
    GPIO_InitStructure.GPIO_Pin = 
        GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 |
        GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    /*    PE.07(D4), PE.08(D5), PE.09(D6), PE.10(D7), PE.11(D8), PE.12(D9), PE.13(D10),
    PE.14(D11), PE.15(D12)         */
    GPIO_InitStructure.GPIO_Pin = 
        GPIO_Pin_4 | GPIO_Pin_5 | 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);
    /*      */
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource7, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC);

    GPIO_PinAFConfig(GPIOE, GPIO_PinSource4 , GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource5 , GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource7 , GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource8 , GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource9 , GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource10 , GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource11 , GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource12 , GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource13 , GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource14 , GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource15 , GPIO_AF_FSMC);

    /*    PF15 (LCD/RST))       */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
    GPIO_Init(GPIOF, &GPIO_InitStructure);
    GPIO_SetBits(GPIOF, GPIO_Pin_15);
    /*    PF14 (LCD/EN))       */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
    GPIO_Init(GPIOF, &GPIO_InitStructure);
    GPIO_SetBits(GPIOF, GPIO_Pin_14 );
    
    /*         PWM */
    //     
}

/*
*************************************************************************************************
*         : STM_FSMCConfig
*        :   FSMC      
*          :  
*         :  
*************************************************************************************************
*/
static void STM_FSMCConfig(void)
{
    FSMC_NORSRAMInitTypeDef  fsmcinit;
    FSMC_NORSRAMTimingInitTypeDef  timingWrite;
    FSMC_NORSRAMTimingInitTypeDef  timingRead;
    //            AddressSetupTime   DataSetupTime ,     。   LCD  。
    timingWrite.FSMC_AddressSetupTime = 15;
    timingWrite.FSMC_AddressHoldTime = 0;
    timingWrite.FSMC_DataSetupTime = 20;
    timingWrite.FSMC_BusTurnAroundDuration = 0;
    timingWrite.FSMC_CLKDivision = 0;
    timingWrite.FSMC_DataLatency = 0;
    timingWrite.FSMC_AccessMode = FSMC_AccessMode_A;
    //            AddressSetupTime   DataSetupTime 
    timingRead.FSMC_AddressSetupTime = 8;
    timingRead.FSMC_AddressHoldTime = 0;
    timingRead.FSMC_DataSetupTime = 9;
    timingRead.FSMC_BusTurnAroundDuration = 0;
    timingRead.FSMC_CLKDivision = 0;
    timingRead.FSMC_DataLatency = 0;
    timingRead.FSMC_AccessMode = FSMC_AccessMode_A;

    fsmcinit.FSMC_Bank = FSMC_Bank1_NORSRAM1;
    fsmcinit.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
    fsmcinit.FSMC_MemoryType = FSMC_MemoryType_SRAM;
    fsmcinit.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
    fsmcinit.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
    fsmcinit.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
    fsmcinit.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
    fsmcinit.FSMC_WrapMode = FSMC_WrapMode_Disable;
    fsmcinit.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
    fsmcinit.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
    fsmcinit.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
    fsmcinit.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable; //     
    fsmcinit.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
    fsmcinit.FSMC_ReadWriteTimingStruct = &timingRead;
    fsmcinit.FSMC_WriteTimingStruct = &timingWrite;

    FSMC_NORSRAMInit(&fsmcinit);

    /* - BANK 1 (of NOR/SRAM Bank 1~4) is enabled */
    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
}

static void MCU_GpioFsmcInit( void )
{
    STM_GPIOConfig();
    STM_FSMCConfig();
}

/****************************        ****************************/

/*
*************************************************************************************************
*         : lcddrv_SetBackLight
*        :      LCD  ,   PWM  。
*          : _bright   ,0  ,BRIGHT_MAX  
*         :  
**************************************************************************************************
*/
void lcddrv_SetBackLight(uint8_t _bright)
{

    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;

    //  GPIOD     
    RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOD , ENABLE);

    if (_bright == 0)
    {
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
        GPIO_Init(GPIOD, &GPIO_InitStructure);

        GPIO_ResetBits(GPIOD, GPIO_Pin_13);

       //  TIM4
        TIM_Cmd(TIM4, DISABLE);
        return;
    }
    else if (_bright == BRIGHT_MAX)   //    ,      
    {
        //     GPIO        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
        GPIO_Init(GPIOD, &GPIO_InitStructure);

        GPIO_SetBits(GPIOD, GPIO_Pin_13);

        //  TIM4 
        TIM_Cmd(TIM4, DISABLE);
        return;
    }

    //    GPIO          
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_TIM4); //GPIO  
    
    //  TIM4     
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
    //TIM   :   1 PWM  ;
    //  10K,  /BRIGHT_MAX
    TIM_TimeBaseStructure.TIM_Period = BRIGHT_MAX - 1;   /* TIM_Period is  ARR Register */
    TIM_TimeBaseStructure.TIM_Prescaler = 7200 - 1;     //10k
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
    // PWM Channel2 
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = ((TIM_TimeBaseStructure.TIM_Period + 1) * _bright) / (BRIGHT_MAX);
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC2Init(TIM4, &TIM_OCInitStructure);
    TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);

    TIM_ARRPreloadConfig(TIM4, ENABLE);
    //   TIM4     
    TIM_Cmd(TIM4, ENABLE);
}

/*
*************************************************************************************************
*         : lcddrv_DispOn
*        :     
*          :  
*         :  
*************************************************************************************************
*/
void lcddrv_DispOn(void)
{
    ST7789_WR_REG(ST7789_CMD_DISPON);
}

/*
*************************************************************************************************
*         : lcddrv_DispOff
*        :     
*          :  
*         :  
*************************************************************************************************
*/
void lcddrv_DispOff(void)
{
    ST7789_WR_REG(ST7789_CMD_DISPOFF);
}

/*
*************************************************************************************************
*         : lcddrv_FillColorPre
*        :           。      ,        LCDDRV_RAM       .
*          :  
*         :  
*************************************************************************************************
*/
void lcddrv_FillColorPre(u16 _usX, u16 _usY, u16 _usWidth , u16 _usHeight)
{
    //      
    ST7789_WR_REG(ST7789_CMD_CASETF);
    ST7789_WR_DATA(_usX >> 8);
    ST7789_WR_DATA(_usX );
    ST7789_WR_DATA( (_usX + _usWidth - 1) >> 8);
    ST7789_WR_DATA( (_usX + _usWidth - 1) );

    ST7789_WR_REG(ST7789_CMD_RASETF );
    ST7789_WR_DATA(_usY >> 8);
    ST7789_WR_DATA(_usY );
    ST7789_WR_DATA( (_usY + _usHeight - 1) >> 8 );
    ST7789_WR_DATA( (_usY + _usHeight - 1) );
    //      
    ST7789_REG = ST7789_CMD_RAMWR;
}

/*
*************************************************************************************************
*         : lcddrv_Init
*        : LCD     
*          :  _ 
*         :  
**************************************************************************************************
*/
void lcddrv_Init(void)
{
    MCU_GpioFsmcInit();
    lcddrv_SetBackLight(0);
    // FSMC       
    if ( ST7789_Init() )
    {
        printf("LCD ok r
"); }else { printf("LCD err \r
"); } } /****************************(END OF FILE)*****************************/

2.デバッグプロセス
ここでは、デバッグ中に遭遇した穴について説明します.
1.最初はバックライトもつけられないことに気づきました.オシロスコープの電圧測定ではずっと低レベルであることが分かった.ソフトウェアの問題を排除して、ハードウェアエンジニアに渡して、錫がつながっていることに気づきました.
2.バックライトを解決した後、LCDがまだ黒くて表示できないことを発見した.ST 7789のIDさえ読めません.しばらくソフトウェアを振り回した後、回路図を開けて、最後に電源の足が電源に接続されていないことを発見して、ただ地に容量を加えただけです.ハードウェアエンジニアに渡して、フライングテストをして、やっと点灯しました.
3.LCDは明るくなったが、スクリーンが表示され、エッジにしか表示できず、正常に表示できない.初期化レジスタが正しくないと思って、振り回して、やはりだめです.最後に心を決めてコードをゆっくり見てみると,関数パラメータが変調に混ざっていることが分かった.修正完了、OK.
FSMCを使ってスクリーンを掃くのはまだ速いです.私が使っているLCDは16ビット色で、320*240ピクセルです.フルスクリーンの単色スイープ周波数では、描画プロセスは表示されません.SDカードを使用して圧縮されていないRGB 565ピクチャ(150 KB)を配置し、FATFSファイルシステムを使用してフルスクリーンピクチャ表示するには、100~180ミリ秒(SDタイプによって読み取り速度に差があります)が必要です.8ビットの色の濃い画像であれば、体積が半分以下で、スムーズに表示できます.