OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 176|回复: 4

STM32F407VGT配合3.5寸TFTLCD可以点亮背光,无法显示颜色字体

[复制链接]

1

主题

5

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2025-9-18
在线时间
2 小时
发表于 2025-10-10 10:53:55 | 显示全部楼层 |阅读模式
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;

回复

使用道具 举报

1

主题

5

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2025-9-18
在线时间
2 小时
 楼主| 发表于 2025-10-10 11:07:11 | 显示全部楼层
LCD驱动芯片是NT35310或者ST7796
回复

使用道具 举报

13

主题

3459

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8911
金钱
8911
注册时间
2020-5-11
在线时间
4454 小时
发表于 2025-10-11 10:23:09 | 显示全部楼层
“无法显示颜色字体”意思是能显示黑色字符?
专治疑难杂症
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2025-9-18
在线时间
2 小时
 楼主| 发表于 2025-10-11 16:05:04 | 显示全部楼层
LcwSwust 发表于 2025-10-11 10:23
“无法显示颜色字体”意思是能显示黑色字符?

确定芯片为ST7796 ,我测试发现是id读取错误了,实际为7796 读到的是0x1E74,正在解决中
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2025-9-18
在线时间
2 小时
 楼主| 发表于 2025-10-11 16:05:29 | 显示全部楼层
孙八戒 发表于 2025-10-10 11:07
LCD驱动芯片是NT35310或者ST7796

确定是ST7796
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


关闭

原子哥极力推荐上一条 /1 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-10-24 08:56

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表