news 2026/4/18 13:57:13

STM32F407驱动3.5寸ILI9486屏幕

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32F407驱动3.5寸ILI9486屏幕

1、硬件原理图

2、软件模拟 8080 并行接口

  • 使用 GPIO 模拟 8080 时序,适合低速或简单应用。

  • 数据线:DB0~DB15 分散在PD、PE、PB、PF等多个 GPIO 口。

  • 控制线:

    • RS(D/C):PD11(命令/数据选择)

    • WR:PD5(写使能)

    • RD:PD4(读使能)

    • CS:PD7(片选)

    • BL:PB15(背光控制)

3、ILI9486芯片

3.1、关键寄存器

0x01: Software Reset 软件复位 0x11: Sleep Out 退出睡眠模式 0x29: Display ON 显示开启 0x2A: Column Address Set 列地址设置 0x2B: Page Address Set 页地址设置 0x2C: Memory Write 内存写入(开始传输像素数据) 0x36: Memory Access Control 内存访问控制(横竖屏) 0x3A: COLMOD: Pixel Format 像素格式设置 0xB1: Frame Rate Control 帧率控制 0xC0: Power Control 1 电源控制1 0xC1: Power Control 2 电源控制2 0xC5: VCOM Control 1 VCOM控制1 0xC7: VCOM Control 2 VCOM控制2 0xE0: Positive Gamma Gamma正校正 0xE1: Negative Gamma Gamma负校正

3.2、指令集详解

3.2.1、0x36 - MADCTL(内存访问控制)
位定义: D7: MY - 行地址顺序(0=上到下,1=下到上) D6: MX - 列地址顺序(0=左到右,1=右到左) D5: MV - 行列交换(横竖屏切换) D4: ML - 垂直刷新顺序 D3: BGR - RGB/BGR顺序(1=BGR,0=RGB) D2: MH - 水平刷新顺序 D1: - 保留 D0: - 保留 常用设置: 0x48 - 竖屏(MY=0, MX=1, MV=0, ML=1, BGR=0) 0x28 - 横屏(MY=0, MX=0, MV=1, ML=0, BGR=0) 0x88 - 竖屏镜像 0xE8 - 横屏镜像
3.2.2、0x3A - COLMOD(像素格式)
数据位: D7-D3: 保留(设置为0) D2-D0: 接口像素格式 000 - 3位/像素(8色) 001 - 保留 010 - 保留 011 - 12位/像素(4096色) 100 - 保留 101 - 16位/像素(RGB565) 110 - 18位/像素(RGB666) 111 - 保留 我们使用:0x55 (01010101) = 16位/像素
3.2.3、0xB1 - 帧率控制
格式:FRC[7:0] 对于240×320屏幕: 典型值:0x00, 0x18 (70Hz) 对于320×480(3.5寸): 可能需要:0x00, 0x1B (65Hz)

4、软件实现流程

4.1、头文件

#ifndef __LCD_H #define __LCD_H #include "stm32f4xx.h" /* 基本类型定义 */ typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; /* LCD尺寸定义 */ #define LCD_WIDTH 320 #define LCD_HEIGHT 480 /* LCD颜色定义 */ #define WHITE 0xFFFF #define BLACK 0x0000 #define RED 0xF800 #define GREEN 0x07E0 #define BLUE 0x001F #define YELLOW 0xFFE0 /* LCD设备结构体 */ typedef struct { u16 width; // LCD宽度 u16 height; // LCD高度 u16 type; // LCD类型 } _lcd_dev; /* 函数声明 */ void lcd_init(void); void lcd_port_init(void); void lcd_output_data(u16 data); void LCD_Write_CMD(u16 cmd); void LCD_Write_Data(u16 data); void LCD_EnterSleep(void); void LCD_ExitSleep(void); void LCD_Display_Dir(u8 dir); void lcd_clear(u16 color); void lcd_draw_point(u16 x, u16 y, u16 color); /* 外部变量 */ extern _lcd_dev lcddev; #endif

4.2、引脚初始化

void lcd_port_init(void);
  • 开启对应 GPIO 时钟(RCC->AHB1ENR)。

  • 配置数据线为推挽输出,速度 50MHz。

  • 配置控制线为输出,默认拉高。

void lcd_port_init(void) { //1、开引脚时钟 PD PE PB RCC->AHB1ENR |= (1<<3);//开PD RCC->AHB1ENR |= (1<<4);//开PE RCC->AHB1ENR |= (1<<1);//开PB //2、配置引脚 // 数据线:-----推挽输出 时钟50M // DB0---PD14 // DB1---PD15 // DB2---PD0 // DB3---PD1 GPIOD->MODER |=(0X1ul<<(2*14))|(0X1ul<<(2*15)); //配置成通用输出 GPIOD->OSPEEDR |=(0X2ul<<(2*14))|(0X2ul<<(2*15)); //配置成输出速率50M GPIOD->MODER |=(0X1<<(2*0))|(0X1<<(2*1)); //配置成通用输出 GPIOD->OSPEEDR |=(0X2<<(2*0))|(0X2<<(2*1)); //配置成输出速率50M // DB4---PE7 // DB5---PE8 // DB6---PE9 // DB7---PE10 // DB8---PE11 // DB9---PE12 // DB10---PE13 // DB11---PE14 // DB12---PE15 GPIOE->MODER |=0x55554000; //配置成通用输出 GPIOE->OTYPER |= 0; //配置成输出推挽 GPIOE->OSPEEDR |=0x55554000; //配置成输出速率50M // DB13---PD8 // DB14---PD9 // DB15---PD10 GPIOD->MODER |=(0X1<<(2*8))|(0X1<<(2*9))|(0X1<<(2*10)); //配置成通用输出 GPIOD->OSPEEDR |=(0X2<<(2*1))|(0X2<<(2*1))|(0X2<<(2*1)); //配置成输出速率50M // 控制线:-----推挽输出 时钟50M 空闲为高电平 // WR:PD5 // RD:PD4 GPIOD->MODER |=(0X1<<(2*4))|(0X1<<(2*5)); //配置成通用输出 GPIOD->OSPEEDR |=(0X2<<(2*4))|(0X2<<(2*5)); GPIOD->ODR |= (1<<4)|(1<<5); // CS : PD7 GPIOD->MODER |=(0X1<<(2*7)); //配置成通用输出 GPIOD->OSPEEDR |=(0X2<<(2*7)); GPIOD->ODR |= (1<<7); // RS : PD11 GPIOD->MODER |=(0X1<<(2*11)); //配置成通用输出 GPIOD->OSPEEDR |=(0X2<<(2*11)); GPIOD->ODR |= (1<<11); // BL -- 背光 PB15 1亮 三极管 GPIOB->MODER |=(0X1<<(2*15)); //配置成通用输出 GPIOB->OSPEEDR |=(0X2ul<<(2*15)); GPIOB->ODR &=~(1<<15);//关闭背光,在LCD初始化完后再打开 }

4.3、LCD输出数据操作

LCD的D0~D15为输出数据引脚,因此一次可以输出16为的数据。因为硬件设计的时候端口没有连续,因此获取到每一位的值后需要安装引脚单独设置。

/******************************************************************** * Function: lcd_output_data * Description: 往LCD8080数据总线输出数据 * Others: *********************************************************************/ void lcd_output_data(u16 data) { // DB0---PD14 // DB1---PD15 if(data&(1<<0)) GPIOD->BSRRL = (1<<14);//GPIOD->ODR |= 1<<14; else GPIOD->BSRRH = (1<<14); //GPIOD->ODR &= ~(1<<14); if(data&(1<<1)) GPIOD->BSRRL = (1<<15); else GPIOD->BSRRH = (1<<15); // DB2---PD0 // DB3---PD1 if(data&(1<<2)) GPIOD->BSRRL = (1<<0); else GPIOD->BSRRH = (1<<0); if(data&(1<<3)) GPIOD->BSRRL = (1<<1); else GPIOD->BSRRH = (1<<1); // DB4---PE7 if(data&(1<<4)) GPIOE->BSRRL = (1<<7); else GPIOE->BSRRH = (1<<7); // DB5---PE8 // DB6---PE9 // DB7---PE10 // DB8---PE11 // DB9---PE12 // DB10---PE13 // DB11---PE14 // DB12---PE15 if(data&(1<<5)) GPIOE->BSRRL = (1<<8); else GPIOE->BSRRH = (1<<8); if(data&(1<<6)) GPIOE->BSRRL = (1<<9); else GPIOE->BSRRH = (1<<9); if(data&(1<<7)) GPIOE->BSRRL = (1<<10); else GPIOE->BSRRH = (1<<10); if(data&(1<<8)) GPIOE->BSRRL = (1<<11); else GPIOE->BSRRH = (1<<11); if(data&(1<<9)) GPIOE->BSRRL = (1<<12); else GPIOE->BSRRH = (1<<12); if(data&(1<<10)) GPIOE->BSRRL = (1<<13); else GPIOE->BSRRH = (1<<13); if(data&(1<<11)) GPIOE->BSRRL = (1<<14); else GPIOE->BSRRH = (1<<14); if(data&(1<<12)) GPIOE->BSRRL = (1<<15); else GPIOE->BSRRH = (1<<15); // DB13---PD8 // DB14---PD9 // DB15---PD10 if(data&(1<<13)) GPIOD->BSRRL = (1<<8); else GPIOD->BSRRH = (1<<8); if(data&(1<<14)) GPIOD->BSRRL = (1<<9); else GPIOD->BSRRH = (1<<9); if(data&(1<<15)) GPIOD->BSRRL = (1<<10); else GPIOD->BSRRH = (1<<10); }

4.4、 写入命令引脚

8080 并行接口写命令时序图

/******************************************************************** * Function: LCD_Write_CMD * Description: LCD写命令函数 * Input: cmd--要写的命令 *********************************************************************/ void LCD_Write_CMD(u16 cmd) { GPIOD->ODR &= ~(1<<11); //D/C = 0;//命令 GPIOD->ODR &= ~(1<<7); //CS = 0; GPIOD->ODR &= ~(1<<5); //WR = 0; lcd_output_data(cmd);//准备数据 GPIOD->ODR |= (1<<5); //WR = 1; GPIOD->ODR |= (1<<7);//CS = 1; }

4.5、写入数据引脚

8080 并行接口写数据时序图

/******************************************************************** * Function: LCD_Write_Parameter * Description: LCD写数据函数 * Input: >4.6、屏幕休眠和退出休眠 -- 官网文档提供
/******************************************************************** * Function: LCD_EnterSleep * Description: LCD driver enter sleep mode *********************************************************************/ void LCD_EnterSleep(void) { LCD_Write_CMD(0x28); // Display off timer6_delay_ms(20); // 自定义延迟函数 LCD_Write_CMD(0x10); // Enter Sleep mode } /******************************************************************** * Function: LCD_ExitSleep * Description: LCD driver exit sleep mode *********************************************************************/ void LCD_ExitSleep(void) { LCD_Write_CMD(0x11); // Sleep out timer6_delay_ms(120); // 自定义延迟函数 LCD_Write_CMD(0x29); // Display on }

4.7、控制屏幕方向

/******************************************************************** * Function: LCD_Display_Dir * Description: Set LCD display direction * Input: dir - 0: portrait, 1: landscape *********************************************************************/ void LCD_Display_Dir(u8 dir) { // Set display direction (simplified version) // You can add more configuration here if needed if(dir == 0) // Portrait { lcddev.width = 320; lcddev.height = 480; } else // Landscape { lcddev.width = 480; lcddev.height = 320; } }

lcddev为全局变量:

/* LCD设备全局变量 */ _lcd_dev lcddev;

3.8、LCD打点函数

/******************************************************************** * Function: lcd_draw_point * Description: Draw a point on LCD * Input: x, y - coordinates, color - pixel color *********************************************************************/ void lcd_draw_point(u16 x, u16 y, u16 color) { // Set X coordinate LCD_Write_CMD(0x2A); LCD_Write_Data(x >> 8); LCD_Write_Data(x & 0xFF); LCD_Write_Data(x >> 8); LCD_Write_Data(x & 0xFF); // Set Y coordinate LCD_Write_CMD(0x2B); LCD_Write_Data(y >> 8); LCD_Write_Data(y & 0xFF); LCD_Write_Data(y >> 8); LCD_Write_Data(y & 0xFF); // Write color data LCD_Write_CMD(0x2C); LCD_Write_Data(color); }

3.9、使用颜色清除屏幕函数

/******************************************************************** * Function: lcd_clear * Description: Clear LCD screen with specified color * Input: color - fill color *********************************************************************/ void lcd_clear(u16 color) { u32 i; // Set X coordinate range LCD_Write_CMD(0x2A); LCD_Write_Data(0); LCD_Write_Data(0); LCD_Write_Data((lcddev.width >> 8) & 0xFF); LCD_Write_Data(lcddev.width & 0xFF); // Set Y coordinate range LCD_Write_CMD(0x2B); LCD_Write_Data(0); LCD_Write_Data(0); LCD_Write_Data((lcddev.height >> 8) & 0xFF); LCD_Write_Data(lcddev.height & 0xFF); // Write color data LCD_Write_CMD(0x2C); for(i = 0; i < lcddev.width * lcddev.height; i++) { LCD_Write_Data(color); } }

3.2、LCD 控制器初始化

void lcd_init(void);
  • 调用lcd_port_init()

  • 根据 LCD 芯片型号(如 ILI9341)发送初始化序列。

  • 设置显示方向、分辨率、颜色模式(如 16BPP RGB565)。

  • 清屏并打开背光。

/******************************************************************** * Function: lcd_init * Description: Initialize LCD *********************************************************************/ void lcd_init(void) { // 1. Initialize pins lcd_port_init(); // 2. LCD initialization sequence // Set 16-bit pixel format (RGB565) LCD_Write_CMD(0X3A); LCD_Write_Data(0X55); // Set Memory Access Control (0x36) - Configure RGB order // Bit 3 (BGR): 0 = RGB order, 1 = BGR order // Set to RGB order (BGR bit = 0) LCD_Write_CMD(0x36); LCD_Write_Data(0x48); // RGB order, normal orientation // Set display direction (0: portrait, 1: landscape) LCD_Display_Dir(0); // Exit sleep mode and turn on display LCD_ExitSleep(); // Set width and height lcddev.width = 320; lcddev.height = 480; // Clear screen to white lcd_clear(WHITE); // Turn on backlight GPIOB->ODR |= (0X1 << 15); }

5、测试代码

#include "stm32f4xx.h" #include "../CMSIS/system_stm32f4xx.h" #include "../Drivers/MCU/lcd.h" #include "../Drivers/MCU/usart.h" /** * @brief Main program * @param None * @retval None */ int main(void) { usart1_init(115200); // Initialize LCD lcd_init(); // Final: Clear to white lcd_clear(BLUE); // Main loop - keep running while(1) { } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 3:51:48

【RabbitMQ】RPC模式(请求/回复)

本章目标理解RabbitMQ RPC模式的工作原理和适用场景。掌握回调队列&#xff08;Callback Queue&#xff09;和关联ID&#xff08;Correlation Id&#xff09;的使用。实现基于RabbitMQ的异步RPC调用。学习RPC模式下的错误处理和超时机制。构建完整的微服务间同步通信解决方案。…

作者头像 李华
网站建设 2026/4/18 8:07:22

25、技术探索:从数据查询到包管理的全面指南

技术探索:从数据查询到包管理的全面指南 在软件开发和系统管理的领域中,数据查询和包管理是两个至关重要的方面。下面我们将深入探讨这两个领域的相关内容。 数据查询与路由 在数据处理中,从数据存储中获取特定记录是常见操作。以下是一段用于从数据存储中获取最后 10 条…

作者头像 李华
网站建设 2026/4/18 5:42:36

高频高速 PCB 能不能量产,打样阶段就能看出来吗?

本文基于深圳市充裕科技有限公司在高频高速 PCB 项目中的实际打样与量产经验整理。 很多高频高速 PCB 项目&#xff0c;在打样阶段都会经历一个“虚假的安全感”&#xff1a; 首版就过测试阻抗、插损数据漂亮项目推进顺利 但当项目进入量产后&#xff0c;却开始陆续出现&…

作者头像 李华
网站建设 2026/4/17 20:33:35

Go 语言未来会取代 Java 吗?

Go 语言&#xff08;Golang&#xff09;不会完全取代 Java&#xff0c;至少在可预见的未来&#xff08;包括 2025 年及以后&#xff09;不会。两者在编程领域有重叠&#xff0c;但各自的优势领域不同&#xff0c;Java 的庞大生态、遗留系统和企业主导地位让它难以被彻底取代&am…

作者头像 李华
网站建设 2026/4/18 10:53:36

1分钟原型:用快马快速验证Vue3生命周期想法

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 构建一个极简原型&#xff1a;1.单文件组件包含所有生命周期钩子&#xff1b;2.每个钩子触发时在界面显示阶段名称和时间戳&#xff1b;3.添加强制重新渲染按钮。要求&#xff1a;1…

作者头像 李华
网站建设 2026/4/18 10:07:03

AI一键配置:用快马自动下载安装MinGW-w64环境

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个自动化脚本&#xff0c;能够自动检测操作系统类型(Windows 10/11)&#xff0c;从官网下载最新版MinGW-w64安装包(64位)&#xff0c;自动完成安装并配置系统环境变量PATH。要…

作者头像 李华