关于STMCubeMx生成FSMC驱动,把相关配置参数贴上来。
1.pinout配置。LCD register select A0,是选择FSMC地址线A0作为SSD1963 寄存器/数据选择位(RS)。
2.时钟配置。
3.FSMC配置。
操作SSD1963实际上只操作两个16位大小的地址,一个当做命令寄存器来操作,一个当做数据缓存来操作。
(地址线A0为1时是写数据操作,A0为0时是写命令操作)
例如:
/* USER CODE BEGIN 0 */
#define LCD_REG (volatile uint16_t *)(0x6c000000)
#define LCD_RAM (volatile uint16_t *)(0x6c000002)
void LCD_WREG(uint16_t command)
{
*LCD_REG = command;
}
void LCD_WRAM(uint16_t data)
{
*LCD_RAM = data ;
}
相关概念:前廊,后廊
显示器的一帧由若干横行组成,比如AT043TN25是800*272的屏就是有272个横行。SSD1963上的驱动信号比272多几个,多的就是FP(前廊) 和BP(后廊)。
这两段时间内,显示数据是不会刷新到屏上的。
main.c中的一段代码如下:
#define SSD_HOR_RESOLUTION 800 //水平像素
#define SSD_VER_RESOLUTION 272 //垂直像素
#define SSD_HOR_BACK_PORCH 46 //水平后廊
#define SSD_HOR_FRONT_PORCH 210 //水平前廊
#define SSD_VER_BACK_PORCH 23 //垂直后廊
#define SSD_VER_FRONT_PORCH 22 //垂直前廊
#define SSD_HT (SSD_HOR_RESOLUTION+SSD_HOR_BACK_PORCH+SSD_HOR_FRONT_PORCH)//显示+不显示
#define SSD_HPS (SSD_HOR_BACK_PORCH) //不显示
#define SSD_VT (SSD_VER_RESOLUTION+SSD_VER_BACK_PORCH+SSD_VER_FRONT_PORCH)//显示+不显示
#define SSD_VPS (SSD_VER_BACK_PORCH) //不显示
篇幅限制,部分main.c如下:
/* USER CODE BEGIN 0 */
#define LCD_REG (volatile uint16_t *)(0x6c000000)
#define LCD_RAM (volatile uint16_t *)(0x6c000002)
//LCD·Ö±æÂÊÉèÖÃ
#define SSD_HOR_RESOLUTION 800 //LCDˮƽ·Ö±æÂÊ
#define SSD_VER_RESOLUTION 272 //LCD´¹Ö±·Ö±æÂÊ
#define SSD_HOR_PULSE_WIDTH 1 //ˮƽÂö¿í
#define SSD_HOR_BACK_PORCH 46 //ˮƽǰÀÈ
#define SSD_HOR_FRONT_PORCH 210 //ˮƽºóÀÈ
#define SSD_VER_PULSE_WIDTH 1 //´¹Ö±Âö¿í
#define SSD_VER_BACK_PORCH 23 //´¹Ö±Ç°ÀÈ
#define SSD_VER_FRONT_PORCH 22 //´¹Ö±Ç°ÀÈ
#define SSD_HT (SSD_HOR_RESOLUTION+SSD_HOR_BACK_PORCH+SSD_HOR_FRONT_PORCH)//×ܵÄÖÜÆÚÊý£¬ÏÔʾµÄ+²»ÏÔʾµÄ
#define SSD_HPS (SSD_HOR_BACK_PORCH) //²»ÏÔʾµÄ
#define SSD_VT (SSD_VER_RESOLUTION+SSD_VER_BACK_PORCH+SSD_VER_FRONT_PORCH)//×ܵÄÖÜÆÚÊý£¬ÏÔʾµÄ+²»ÏÔʾµÄ
#define SSD_VPS (SSD_VER_BACK_PORCH) //²»ÏÔʾµÄ
//LCDÖØÒª²ÎÊý¼¯
typedef struct
{
uint16_t width; //LCD ¿í¶È
uint16_t height; //LCD ¸ß¶È
uint16_t ID;
uint8_t dir; //ºáÆÁ»¹ÊÇÊúÆÁ¿ØÖÆ£º0£¬ÊúÆÁ£»1£¬ºáÆÁ¡£
uint16_t wramcmd; //¿ªÊ¼Ð´gramÖ¸Áî
uint16_t setxcmd; //ÉèÖÃx×ø±êÖ¸Áî
uint16_t setycmd; //ÉèÖÃy×ø±êÖ¸Áî
} _lcd_dev;
//LCD²ÎÊý
_lcd_dev lcddev; //¹ÜÀíLCDÖØÒª²ÎÊý
uint16_t result;
uint32_t i ;
uint16_t color=0,pan=0;
void LCD_WREG(uint16_t command)
{
*LCD_REG = command;
}
void LCD_WRAM(uint16_t data)
{
*LCD_RAM = data ;
}
uint16_t LCD_RRAM(void)
{
uint16_t data;
data = *LCD_RAM;
return(data);
}
uint16_t LCD_Read_REG(uint16_t reg)
{
uint16_t ram;
LCD_WREG(reg);
HAL_Delay(1);
ram = LCD_RRAM();
return(ram);
}
void SSD1963_43_Init(void)
{
HAL_Delay(1);
LCD_WREG(0XA1);
result = LCD_RRAM();
result = LCD_RRAM(); //¶Á»Ø0X57
result <<= 8;
result |= LCD_RRAM(); //¶Á»Ø0X61
if(result == 0x5761)
result = 0x1963;
printf("ID = %x\n", result);
/*
set_pll_mn
Command 0xE2
Parameters 3
D/C D7 D6 D5 D4 D3 D2 D1 D0 Hex
Command 0 1 1 1 0 0 0 1 0 E2
Parameter 1 1 M7 M6 M5 M4 M3 M2 M1 M0 xx
Parameter 2 1 0 0 0 0 N3 N2 N1 N0 xx
Parameter 3 1 0 0 0 0 0 C2 0 0 xx
Description
Set the MN of PLL
M[7:0] : Multiplier (M) of PLL. (POR = 00101101)
N[3:0] : Divider (N) of PLL. (POR = 0011)
C[2] : Effectuate MN value (POR = 0)
0 Ignore the multiplier (N) and divider (N) values
1 Effectuate the multiplier and divider value
VCO = Reference input clock x (M + 1)
PLL frequency = VCO / (N + 1)
* Note : 250MHz < VCO < 800MHz
For a 10MHz reference clock to obtain 100MHz PLL frequency, user cannot program M = 19 and N = 1. The setting in
this situation is setting M=29 and N=2, where 10 x 30 / 3 = 100MHz.
*/
LCD_WREG(0xE2); //Set PLL with OSC = 10MHz (hardware), Multiplier N = 35, 250MHz < VCO < 800MHz = OSC*(N+1), VCO = 300MHz
LCD_WRAM(0x1D); //²ÎÊý1 M=29
LCD_WRAM(0x02); //²ÎÊý2 N=2
LCD_WRAM(0x04); //²ÎÊý3 Ó¦ÓòÎÊý
printf("PLL frequency= 100M\n");
HAL_Delay(1);
/*
set_pll
Command 0xE0
Parameters 1
D/C D7 D6 D5 D4 D3 D2 D1 D0 Hex
Command 0 1 1 1 0 0 0 0 0 E0
Parameter 1 1 0 0 0 0 0 0 A1 A0 xx
Description
Start the PLL. Before the start, the system was operated with the crystal oscillator or clock input.
A[1] : Lock PLL (POR = 0)
After PLL enabled for 100us, can start to lock PLL
0 Use reference clock as system clock
1 Use PLL output as system clock
A[0] : Enable PLL (POR = 0)
0 Disable PLL
1 Enable PLL
Before enabling PLL, the PLL setting (“0xE2”) have to be configured first. After PLL enabled for 100us, can start to
lock PLL. SSD1963 needed to switch to PLL output as system clock after PLL is locked. The following is the program
sequence.
WRITE COMMAND “0xE0”
WRITE DATA “0x01”
Wait 100us to let the PLL stable
WRITE COMMAND “0xE0”
WRITE DATA “0x03”
WRITE COMMAND “0x01”
* Note : SSD1963 is operating under reference clock before PLL is locked, registers cannot be set faster than half of the
reference clock frequency. For instance, SSD1963 with a 10MHz reference clock is not allowed to be programmed
higher than 5M words/s.
*/
LCD_WREG(0xE0); // Start PLL command
LCD_WRAM(0x01); // enable PLL
HAL_Delay(1);
LCD_WREG(0xE0); // Start PLL command again
LCD_WRAM(0x03); // now, use PLL output as system clock
HAL_Delay(1);
LCD_WREG(0x01); //Èí¸´Î»
HAL_Delay(1);
/*
set_lshift_freq
Command 0xE6
Parameters 3
D/C D7 D6 D5 D4 D3 D2 D1 D0 Hex
Command 0 1 1 1 0 0 1 1 0 E6
Parameter 1 1 0 0 0 0 LCDC_FPR19 LCDC_FPR18 LCDC_FPR17 LCDC_FPR16 xx
Parameter 2 1 LCDC_FPR15 LCDC_FPR14 LCDC_FPR13 LCDC_FPR12 LCDC_FPR11 LCDC_FPR10 LCDC_FPR9 LCDC_FPR8 xx
Parameter 3 1 LCDC_FPR7 LCDC_FPR6 LCDC_FPR 5 LCDC_FPR4 LCDC_FPR 3 LCDC_FPR2 LCDC_FPR1 LCDC_FPR0 xx
Description
Set the LSHIFT (pixel clock) frequency
LCDC_FPR[19:16] : The highest 4 bits for the pixel clock frequency settings. (POR = 0111)
LCDC_FPR[15:8] : The higher byte for the pixel clock frequency settings. (POR = 11111111)
LCDC_FPR[7:0] : The low byte for the pixel clock frequency settings. (POR = 11111111)
For parallel LCD interface:
Configure the pixel clock to PLL freq x ((LCDC_FPR + 1) / 1048576)
To obtain PCLK = 5.3MHz with PLL Frequency = 100MHz,
5.3MHz = 100MHz * ( LCDC_FPR+ 1) / 1048576
LCDC_FPR = 55574
WRITE COMMAND “0xE6”
WRITE DATA “0x00” (LCDC_FPR = 55574)
WRITE DATA “0xD9”
WRITE DATA “0x16”
For serial LCD interface:
Configure the pixel clock to PLL freq x ((LCDC_FPR + 1) / 1048576) *4
To obtain PCLK = 5.3MHz with PLL Frequency = 100MHz,
5.3MHz = 100MHz * ( ( LCDC_FPR+ 1) / 1048576 )*4
LCDC_FPR = 13892
WRITE COMMAND “0xE6”
WRITE DATA “0x00” (LCDC_FPR = 13892)
WRITE DATA “0x36”
WRITE DATA “0x44”
*/
LCD_WREG(0xE6); //ÉèÖÃÏñËØƵÂÊ,300Mhz
LCD_WRAM(0x2F);
LCD_WRAM(0xFF);
LCD_WRAM(0xFF);
/*
set_lcd_mode
Command 0xB0
Parameters 7
D/C D7 D6 D5 D4 D3 D2 D1 D0 Hex
Command 0 1 0 1 1 0 0 0 0 B0
Parameter 1 1 0 0 A5 A4 A3 A2 A1 A0 xx
Parameter 2 1 0 B6 B5 0 0 0 0 0 xx
Parameter 3 1 0 0 0 0 0 HDP10 HDP9 HDP8 xx
Parameter 4 1 HDP7 HDP6 HDP5 HDP4 HDP3 HDP2 HDP1 HDP0 xx
Parameter 5 1 0 0 0 0 0 VDP10 VDP9 VDP8 xx
Parameter 6 1 VDP7 VDP6 VDP5 VDP4 VDP3 VDP2 VDP1 VDP0 xx
Parameter 7 1 0 0 G5 G4 G3 G2 G1 G0 xx
Description
Set the LCD panel mode and resolution
A[5] : TFT panel data width (POR = 0)
0 18-bit
1 24-bit
A[4] : TFT color depth enhancement enable (POR = 0)
0 Disable FRC or dithering
1 Enable FRC or dithering for color depth enhancement
If the panel data width was set to 24-bit,
FRC and dithering feature will be disabled automatic regardless the value of this register.
A[3] : TFT FRC enable (POR = 0)
0 TFT dithering enable
1 TFT FRC enableSSD1963 Rev 1.1 P 45/93 Jan 2010 Solomon Systech
A[5] A[4] A[3] TFT FRC TFT dithering
0 0 X Disable Disable
0 1 0 Disable Enable
0 1 1 Enable Disable
1 X X Disable Disable
A[2] : LSHIFT polarity (POR = 0)
Set the dot clock pulse polarity.
0 Data latch in falling edge
1 Data latch in rising edge
A[1] : LLINE polarity (POR = 0)
Set the horizontal sync pulse polarity.
0 Active low
1 Active high
A[0] : LFRAME polarity (POR = 0)
Set the vertical sync pulse polarity.
0 Active low
1 Active high
B[6:5] : TFT type (POR = 01)
00, 01 TFT mode
10 Serial RGB mode
11 Serial RGB+dummy mode
HDP [10:8] : High byte of the horizontal panel size (POR = 010)
HDP [7:0] : Low byte of the horizontal panel size (POR = 01111111)
Horizontal panel size = (HDP + 1) pixels
VDP [10:8] : High byte of the vertical panel size (POR = 001)
VDP [7:0] : Low byte of the vertical panel size (POR = 11011111)
Vertical panel size = (VDP + 1) lines
G[5:3] : Even line RGB sequence for serial TFT interface (POR = 000)
000 RGB
001 RBG
010 GRB
011 GBR
100 BRG
101 BGR
11x Reserved
G[2:0] : Odd line RGB sequence for serial TFT interface (POR = 000)
000 RGB
001 RBG
010 GRB
011 GBR
100 BRG
101 BGR
11x Reserved
*/
LCD_WREG(0xB0); //ÉèÖÃLCDģʽ
LCD_WRAM(0x20); //24λģʽ
LCD_WRAM(0x00); //TFT ģʽ
LCD_WRAM((SSD_HOR_RESOLUTION - 1) >> 8); //ÉèÖÃLCDˮƽÏñËØ
LCD_WRAM(SSD_HOR_RESOLUTION - 1);
LCD_WRAM((SSD_VER_RESOLUTION - 1) >> 8); //ÉèÖÃLCD´¹Ö±ÏñËØ
LCD_WRAM(SSD_VER_RESOLUTION - 1);
LCD_WRAM(0x00); //RGBÐòÁÐ
printf("set_lcd_mode\n");
/*
set_hori_period
Command 0xB4
Parameters 8
D/C D7 D6 D5 D4 D3 D2 D1 D0 Hex
Command 0 1 0 1 1 0 1 0 0 B4
Parameter 1 1 0 0 0 0 0 HT10 HT9 HT8 xx
Parameter 2 1 HT7 HT6 HT5 HT4 HT3 HT2 HT1 HT0 xx
Parameter 3 1 0 0 0 0 0 HPS10 HPS9 HPS8 xx
Parameter 4 1 HPS7 HPS6 HPS5 HPS4 HPS3 HPS2 HPS1 HPS0 xx
Parameter 5 1 0 HPW6 HPW5 HPW4 HPW3 HPW2 HPW1 HPW0 xx
Parameter 6 1 0 0 0 0 0 LPS10 LPS9 LPS8 xx
Parameter 7 1 LPS7 LPS6 LPS5 LPS4 LPS3 LPS2 LPS1 LPS0 xx
Parameter 8 1 0 0 0 0 0 0 LPSPP1 LPSPP0 xx
Description
Set front porch and back porch
HT[10:8] : High byte of horizontal total period (display + non-display) in pixel clock (POR = 010)
HT[7:0] : Low byte of the horizontal total period (display + non-display) in pixel clock (POR = 10101111)
Horizontal total period = (HT + 1) pixels
HPS[10:8] : High byte of the non-display period between the start of the horizontal sync (LLINE) signal and the first
display data. (POR = 000)
HPS[7:0] : Low byte of the non-display period between the start of the horizontal sync (LLINE) signal and the first
display data. (POR = 00100000)
For TFT : Horizontal Sync Pulse Start Position = HPS pixels
For Serial TFT : Horizontal Sync Pulse Start Position = HPS pixels + LPSPP subpixels
HPW[6:0] : Set the horizontal sync pulse width (LLINE) in pixel clock. (POR = 0000111)
Horizontal Sync Pulse Width = (HPW + 1) pixelsSolomon Systech Jan 2010 P 48/93 Rev 1.1 SSD1963
LPS[10:8] : Set the horizontal sync pulse (LLINE) start location in pixel clock. (POR = 000)
LPS[7:0] : Set the horizontal sync pulse width (LLINE) in start. (POR = 00000000)
Horizontal Display Period Start Position = LPS pixels
LPSPP[1:0] : Set the horizontal sync pulse subpixel start position for serial TFT interface (POR = 00)
*/
LCD_WREG(0xB4); //Set horizontal period
LCD_WRAM((SSD_HT - 1) >> 8);
LCD_WRAM(SSD_HT - 1);
LCD_WRAM(SSD_HPS >> 8);
LCD_WRAM(SSD_HPS);
LCD_WRAM(SSD_HOR_PULSE_WIDTH - 1);
LCD_WRAM(0x00);
LCD_WRAM(0x00);
LCD_WRAM(0x00);
LCD_WREG(0xB6); //Set vertical period
LCD_WRAM((SSD_VT - 1) >> 8);
LCD_WRAM(SSD_VT - 1);
LCD_WRAM(SSD_VPS >> 8);
LCD_WRAM(SSD_VPS);
LCD_WRAM(SSD_VER_FRONT_PORCH - 1);
LCD_WRAM(0x00);
LCD_WRAM(0x00);
printf("set_hori_period\n");
/*
set_pixel_data_interface
Command 0xF0
Parameters 1
D/C D7 D6 D5 D4 D3 D2 D1 D0 Hex
Command 0 1 1 1 1 0 0 0 0 F0
Parameter 1 1 0 0 0 0 0 A2 A1 A0 xx
Description
Set the pixel data format to 8-bit / 9-bit / 12-bit / 16-bit / 16-bit(565) / 18-bit / 24-bit in the parallel host processor
interface. This command is used for display data only, the command format is always 8 bit.
A[2:0] : Pixel Data Interface Format (POR = 101)
000 8-bit
001 12-bit
010 16-bit packed
011 16-bit (565 format)
100 18-bit
101 24-bit
110 9-bit
Others Reserved
* Note : The un-used data bus will be driven to ground by SSD1963, so don’t connect the un-used data bus to
MCU
*/
LCD_WREG(0xF0); //ÉèÖÃSSD1963ÓëCPU½Ó¿ÚΪ16bit
LCD_WRAM(0x03); //16-bit(565 format) data for 16bpp
printf("set_pixel_data_interface\n");
/*
set_display_on
Command 0x29
Parameters None
D/C D7 D6 D5 D4 D3 D2 D1 D0 Hex
Command 0 0 0 1 0 1 0 0 1 29
Description
Show the image on the display panel
*/
LCD_WREG(0x29); //¿ªÆôÏÔʾ
printf("set_display_on\n");
/*
//ÉèÖÃPWMÊä³ö ±³¹âͨ¹ýÕ¼¿Õ±È¿Éµ÷
LCD_WREG(0xD0); //ÉèÖÃ×Ô¶¯°×ƽºâDBC
LCD_WRAM(0x00); //disable
LCD_WREG(0xBE); //ÅäÖÃPWMÊä³ö
LCD_WRAM(0x05); //1ÉèÖÃPWMƵÂÊ
LCD_WRAM(0xFE); //2ÉèÖÃPWMÕ¼¿Õ±È
LCD_WRAM(0x01); //3ÉèÖÃC
LCD_WRAM(0x00); //4ÉèÖÃD
LCD_WRAM(0x00); //5ÉèÖÃE
LCD_WRAM(0x00); //6ÉèÖÃF
LCD_WREG(0xB8); //ÉèÖÃGPIOÅäÖÃ
LCD_WRAM(0x03); //2¸öIO¿ÚÉèÖóÉÊä³ö
LCD_WRAM(0x01); //GPIOʹÓÃÕý³£µÄIO¹¦ÄÜ
LCD_WREG(0xBA);
LCD_WRAM(0X01); //GPIO[1:0]=01,¿ØÖÆLCD·½Ïò
*/
LCD_WREG(0x36); //ÉèÖÃɨÃèģʽ
LCD_WRAM(0x00);
}
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_FSMC_Init();
/* USER CODE BEGIN 2 */
SSD1963_43_Init();
printf("init end\n");
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
lcddev.wramcmd = 0X2C; //ÉèÖÃдÈëGRAMµÄÖ¸Áî
lcddev.setxcmd = 0X2A; //ÉèÖÃдX×ø±êÖ¸Áî
lcddev.setycmd = 0X2B; //ÉèÖÃдY×ø±êÖ¸Áî
lcddev.width = 800; //ÉèÖÿí¶È800
lcddev.height = 272; //ÉèÖø߶È272
LCD_WREG(lcddev.setxcmd);//ÉèÖùâ±êλÖÃ
LCD_WRAM(0);
LCD_WRAM(0);
LCD_WRAM((lcddev.width - 1) >> 8);
LCD_WRAM((lcddev.width - 1) & 0XFF);
LCD_WREG(lcddev.setycmd);//ÉèÖùâ±êλÖÃ
LCD_WRAM(0);
LCD_WRAM(0);
LCD_WRAM((lcddev.height - 1) >> 8);
LCD_WRAM((lcddev.height - 1) & 0XFF);
LCD_WREG(lcddev.wramcmd);
color = 0;
pan = 0;
for(i = 0; i < (lcddev.width * lcddev.height); i++)
{
pan = pan & 0xFF;
pan ++;
if(pan > 0xFF)
{
color += 15;
}
*LCD_RAM = color;
}
while(1);
}
/* USER CODE END 3 */
}
测试打印结果如下:
|