STM 32:FSMC駆動TFT LCD(ST 7789)
17733 ワード
最近プロジェクトはSTM 32 F 407を使ってtftカラースクリーンを駆動して、スクリーンの内部の駆動チップはST 7789 Vで、このICのネット上の資料は多くありません.
くだらないことは言わないで、直接完全な駆動コードに行きます.
1.コード
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ビットの色の濃い画像であれば、体積が半分以下で、スムーズに表示できます.
くだらないことは言わないで、直接完全な駆動コードに行きます.
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ビットの色の濃い画像であれば、体積が半分以下で、スムーズに表示できます.