新手入门
- 积分
- 16
- 金钱
- 16
- 注册时间
- 2025-9-18
- 在线时间
- 2 小时
|
1金钱
void HAL_SRAM_MspInit(SRAM_HandleTypeDef *hsram)
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_FSMC_CLK_ENABLE(); // 使能FSMC时钟
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE(); // 使能GPIOD时钟(包含CS/RS/WR/RD/数据线)
__HAL_RCC_GPIOE_CLK_ENABLE(); // 使能GPIOE时钟(包含数据线)
/* 初始化GPIOD的FSMC引脚:包含CS(RD7)、RS(PD11)、RD(PD4)、WR(PD5)、数据线(PD0~1、PD8~10、PD14~15) */
gpio_init_struct.Pin = GPIO_PIN_4 // PD4: FSMC_NOE(LCD_RD)
| GPIO_PIN_5 // PD5: FSMC_NWE(LCD_WR)
| GPIO_PIN_0 | GPIO_PIN_1 // PD0~1: 数据线D2~D3
| GPIO_PIN_7 // PD7: FSMC_NE1(LCD_CS)
| GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 // PD8~10: 数据线D13~D15
| GPIO_PIN_11 // PD11: FSMC_A16(LCD_RS)
| GPIO_PIN_14 | GPIO_PIN_15; // PD14~15: 数据线D0~D1
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 推挽复用(FSMC必需) */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉防悬空 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速匹配FSMC */
gpio_init_struct.Alternate = GPIO_AF12_FSMC; /* FSMC复用功能号AF12 */
HAL_GPIO_Init(GPIOD, &gpio_init_struct); /* 初始化GPIOD */
/* 初始化GPIOE的FSMC引脚:数据线D4~D12(PE7~PE15) */
gpio_init_struct.Pin = 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;
HAL_GPIO_Init(GPIOE, &gpio_init_struct); /* 初始化GPIOE */
}
/**
* @brief 初始化LCD
* @note 该初始化函数可以初始化各种型号的LCD(详见本.c文件最前面的描述)
*
* @param 无
* @retval 无
*/
void lcd_init(void)
{
GPIO_InitTypeDef gpio_init_struct;
FSMC_NORSRAM_TimingTypeDef fsmc_read_handle;
FSMC_NORSRAM_TimingTypeDef fsmc_write_handle;
// -------------------------- 1. 初始化背光GPIO --------------------------
LCD_BL_GPIO_CLK_ENABLE(); /* 开启背光引脚时钟 */
gpio_init_struct.Pin = LCD_BL_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
gpio_init_struct.Pull = GPIO_PULLUP;
gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LCD_BL_GPIO_PORT, &gpio_init_struct);
HAL_GPIO_WritePin(LCD_BL_GPIO_PORT, LCD_BL_GPIO_PIN, GPIO_PIN_SET); // 开启背光
// -------------------------- 2. LCD硬件复位(若有RST引脚) --------------------------
LCD_RST_GPIO_CLK_ENABLE(); /* 开启RST引脚时钟 */
gpio_init_struct.Pin = LCD_RST_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(LCD_RST_GPIO_PORT, &gpio_init_struct);
LCD_RST_HIGH();
HAL_Delay(500);
LCD_RST_LOW();
HAL_Delay(500);
// -------------------------- 3. 初始化FSMC --------------------------
g_sram_handle.Instance = FSMC_NORSRAM_DEVICE;
g_sram_handle.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
g_sram_handle.Init.NSBank = FSMC_NORSRAM_BANK1; /* 使用NE1(CS=PD7) */
g_sram_handle.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE; /* 地址/数据线不复用 */
g_sram_handle.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16; /* 16位数据宽度(适配ST7796) */
g_sram_handle.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE; /* 禁止突发访问 */
g_sram_handle.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW; /* 等待信号低电平 */
g_sram_handle.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS; /* 等待周期前使能NWAIT */
g_sram_handle.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE; /* 使能写操作 */
g_sram_handle.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE; /* 禁止等待信号 */
g_sram_handle.Init.ExtendedMode = FSMC_EXTENDED_MODE_ENABLE; /* 读写时序分离 */
g_sram_handle.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE; /* 禁止同步等待 */
g_sram_handle.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE; /* 禁止突发写 */
// FSMC读时序(适配ST7796)
fsmc_read_handle.AddressSetupTime = 0x02; /* 2个时钟(≈23.8ns) */
fsmc_read_handle.AddressHoldTime = 0x00; /* 0个时钟 */
fsmc_read_handle.DataSetupTime = 0x08; /* 4个时钟(≈47.6ns) */
fsmc_read_handle.AccessMode = FSMC_ACCESS_MODE_A; /* 模式A */
// FSMC写时序(适配ST7796)
fsmc_write_handle.BusTurnAroundDuration = 0x00; /* 0个时钟 */
fsmc_write_handle.AddressSetupTime = 0x02; /* 2个时钟(≈23.8ns) */
fsmc_write_handle.AddressHoldTime = 0x00; /* 0个时钟 */
fsmc_write_handle.DataSetupTime = 0x08; /* 6个时钟(≈71.4ns) */
fsmc_write_handle.AccessMode = FSMC_ACCESS_MODE_A; /* 模式A */
// 初始化FSMC(自动调用HAL_SRAM_MspInit)
if (HAL_SRAM_Init(&g_sram_handle, &fsmc_read_handle, &fsmc_write_handle) != HAL_OK)
{
// printf("FSMC初始化失败!\r\n");
while(1);
}
HAL_Delay(50); // 等待FSMC稳定
/* 尝试9341 ID的读取 */
lcd_wr_regno(0xD3);
lcddev.id = lcd_rd_data(); /* dummy read */
lcddev.id = lcd_rd_data(); /* 读到0x00 */
lcddev.id = lcd_rd_data(); /* 读取93 */
lcddev.id <<= 8;
lcddev.id |= lcd_rd_data(); /* 读取41 */
if (lcddev.id != 0x9341) /* 不是 9341 , 尝试看看是不是 ST7789 */
{
lcd_wr_regno(0x04);
lcddev.id = lcd_rd_data(); /* dummy read */
lcddev.id = lcd_rd_data(); /* 读到0x85 */
lcddev.id = lcd_rd_data(); /* 读取0x85 */
lcddev.id <<= 8;
lcddev.id |= lcd_rd_data(); /* 读取0x52 */
if (lcddev.id == 0x8552) /* 将8552的ID转换成7789 */
{
lcddev.id = 0x7789;
}
if (lcddev.id != 0x7789) /* 也不是ST7789, 尝试是不是 NT35310 */
{
lcd_wr_regno(0xD4);
lcddev.id = lcd_rd_data(); /* dummy read */
lcddev.id = lcd_rd_data(); /* 读回0x01 */
lcddev.id = lcd_rd_data(); /* 读回0x53 */
lcddev.id <<= 8;
lcddev.id |= lcd_rd_data(); /* 这里读回0x10 */
if (lcddev.id != 0x5310) /* 也不是NT35310,尝试看看是不是ST7796 */
{
lcd_wr_regno(0XD3);
lcddev.id = lcd_rd_data(); /* dummy read */
lcddev.id = lcd_rd_data(); /* 读到0X00 */
lcddev.id = lcd_rd_data(); /* 读取0X77 */
lcddev.id <<= 8;
lcddev.id |= lcd_rd_data(); /* 读取0X96 */
if (lcddev.id != 0x7796) /* 也不是ST7796,尝试看看是不是NT35510 */
{
/* 发送密钥(厂家提供) */
lcd_write_reg(0xF000, 0x0055);
lcd_write_reg(0xF001, 0x00AA);
lcd_write_reg(0xF002, 0x0052);
lcd_write_reg(0xF003, 0x0008);
lcd_write_reg(0xF004, 0x0001);
lcd_wr_regno(0xC500); /* 读取ID低八位 */
lcddev.id = lcd_rd_data(); /* 读回0x80 */
lcddev.id <<= 8;
lcd_wr_regno(0xC501); /* 读取ID高八位 */
lcddev.id |= lcd_rd_data(); /* 读回0x00 */
delay_ms(5); /* 等待5ms, 因为0XC501指令对1963来说就是软件复位指令, 等待5ms让1963复位完成再操作 */
if (lcddev.id != 0x5510) /* 也不是NT5510,尝试看看是不是ILI9806 */
{
lcd_wr_regno(0XD3);
lcddev.id = lcd_rd_data(); /* dummy read */
lcddev.id = lcd_rd_data(); /* 读回0X00 */
lcddev.id = lcd_rd_data(); /* 读回0X98 */
lcddev.id <<= 8;
lcddev.id |= lcd_rd_data(); /* 读回0X06 */
if (lcddev.id != 0x9806) /* 也不是ILI9806,尝试看看是不是SSD1963 */
{
lcd_wr_regno(0xA1);
lcddev.id = lcd_rd_data();
lcddev.id = lcd_rd_data(); /* 读回0x57 */
lcddev.id <<= 8;
lcddev.id |= lcd_rd_data(); /* 读回0x61 */
if (lcddev.id == 0x5761) lcddev.id = 0x1963; /* SSD1963读回的ID是5761H,为方便区分,我们强制设置为1963 */
}
}
}
}
}
}
/* 特别注意, 如果在main函数里面屏蔽串口1初始化, 则会卡死在printf
* 里面(卡死在f_putc函数), 所以, 必须初始化串口1, 或者屏蔽掉下面
* 这行 printf 语句 !!!!!!!
*/
// printf("LCD ID:%x\r\n", lcddev.id); /* 打印LCD ID */
if (lcddev.id == 0x7789)
{
lcd_ex_st7789_reginit(); /* 执行ST7789初始化 */
}
else if (lcddev.id == 0x9341)
{
lcd_ex_ili9341_reginit(); /* 执行ILI9341初始化 */
}
else if (lcddev.id == 0x5310)
{
lcd_ex_nt35310_reginit(); /* 执行NT35310初始化 */
}
else if (lcddev.id == 0x7796)
{
lcd_ex_st7796_reginit(); /* 执行ST7796初始化 */
}
else if (lcddev.id == 0x5510)
{
lcd_ex_nt35510_reginit(); /* 执行NT35510初始化 */
}
else if (lcddev.id == 0x9806)
{
lcd_ex_ili9806_reginit(); /* 执行ILI9806初始化 */
}
else if (lcddev.id == 0x1963)
{
lcd_ex_ssd1963_reginit(); /* 执行SSD1963初始化 */
lcd_ssd_backlight_set(100); /* 背光设置为最亮 */
}
/* 初始化完成以后,提速 */
if (lcddev.id == 0x7789 || lcddev.id == 0x9341 || lcddev.id == 0x1963) /* 7789/9341/1963 提速 */
{
/* 重新配置写时序控制寄存器的时序 */
fsmc_write_handle.AddressSetupTime = 6; /* 地址建立时间(ADDSET)为3个fsmc_ker_ck=6*3=18ns */
fsmc_write_handle.DataSetupTime = 6; /* 数据保持时间(DATAST)为3个fsmc_ker_ck=6*3=18ns */
FSMC_NORSRAM_Extended_Timing_Init(g_sram_handle.Extended, &fsmc_write_handle, g_sram_handle.Init.NSBank, g_sram_handle.Init.ExtendedMode);
}
else if (lcddev.id == 0x5310 || lcddev.id == 0x7796 || lcddev.id == 0x5510 || lcddev.id == 0x9806) /* 如果是这几个IC, 则设置WR时序为最快 */
{
/* 重新配置写时序控制寄存器的时序 */
fsmc_write_handle.AddressSetupTime = 8; /* 地址建立时间(ADDSET)为2个fsmc_ker_ck=6*2=12ns */
fsmc_write_handle.DataSetupTime = 8; /* 数据保持时间(DATAST)为2个fsmc_ker_ck=6*2=12ns */
FSMC_NORSRAM_Extended_Timing_Init(g_sram_handle.Extended, &fsmc_write_handle, g_sram_handle.Init.NSBank, g_sram_handle.Init.ExtendedMode);
}
lcd_display_dir(1); /* 默认为竖屏 */
LCD_BL(1); /* 点亮背光 */
lcd_display_on();
lcd_fill(0,0, lcddev.width-1, lcddev.height-1, RED);
}
初始化部分代码如此,LCD_CS 和 LCD_RS对应引脚为GPIOD_PIN_7 和 GPIOD_PIN_11;
|
|