STM32 HAL库 OLED驱动实现
一、概述
1.1 OLED 显示屏简介
OLED(Organic Light - Emitting Diode)即有机发光二极管,与传统的 LCD 显示屏相比,OLED 具有自发光、视角广、响应速度快、对比度高、功耗低等优点。在嵌入式系统中,OLED 显示屏常被用于显示系统状态信息、图形界面等。
1.2 STM32F407 与 HAL 库
STM32F407 是意法半导体(ST)推出的一款高性能 32 位微控制器,基于 ARM Cortex - M4 内核,具有丰富的外设资源和强大的处理能力。HAL(Hardware Abstraction Layer)库是 ST 为 STM32 系列微控制器提供的硬件抽象层,它简化了开发流程,提高了代码的可移植性。
1.3 通信接口
OLED 显示屏通常支持多种通信接口,本文主要介绍 8080 并行接口和 IIC(Inter - Integrated Circuit)串行接口的驱动实现。8080 接口通信速度快,适合显示大数据量的图像;IIC 接口则具有引脚少、布线简单的优点,适用于对引脚资源要求较高的场景。
二、硬件连接
2.1 8080 接口连接
当使用 8080 接口连接 OLED 显示屏和 STM32F407 时,一般需要以下引脚:
| 引脚功能 | STM32F407 引脚 |
|---|---|
| 数据总线(D0 - D7) | 任意 8 个 GPIO 引脚 |
| 命令 / 数据选择(DC) | 一个 GPIO 引脚 |
| 写信号(WR) | 一个 GPIO 引脚 |
| 片选信号(CS) | 一个 GPIO 引脚 |
| 复位信号(RST) | 一个 GPIO 引脚 |
2.2 IIC 接口连接
使用 IIC 接口连接时,需要连接两根线:
| 引脚功能 | STM32F407 引脚 |
|---|---|
| SDA(数据线) | I2C 的 SDA 引脚 |
| SCL(时钟线) | I2C 的 SCL 引脚 |
同时,还需要一个复位引脚(RST)用于复位 OLED 显示屏。
三、HAL 库配置
3.1 开发环境搭建
使用 STM32CubeMX 进行硬件配置和代码生成,然后在 Keil MDK 或者 STM32CubeIDE 中进行代码开发和调试。
3.2 8080 接口配置
在 STM32CubeMX 中,将用于连接 OLED 的 GPIO 引脚配置为输出模式。对于数据总线引脚,设置为推挽输出;对于控制信号引脚(DC、WR、CS、RST),同样设置为推挽输出。
3.3 IIC 接口配置
在 STM32CubeMX 中,选择相应的 I2C 外设(如 I2C1),配置为标准模式,时钟频率设置为合适的值(如 100kHz)。同时,将连接 SDA 和 SCL 的 GPIO 引脚配置为 I2C 功能。
四、8080 接口驱动实现(可参考光子物联的OLED驱动)
零基础国产GD32单片机编程入门(五)OLED显示及实战含源码_gd32 oled-CSDN博客
4.1 初始化函数
//初始化SSD1306
void OLED_Init(void)
{ GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOD_CLK_ENABLE();GPIO_InitStruct.Pin = GPIO_PIN_8;//配置管脚为输出GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;//配置管脚为输出GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_14;//配置管脚为输出GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8|GPIO_PIN_9, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_10|GPIO_PIN_14, GPIO_PIN_SET);HAL_Delay(100);OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panelOLED_WR_Byte(0x00,OLED_CMD);//---set low column addressOLED_WR_Byte(0x10,OLED_CMD);//---set high column addressOLED_WR_Byte(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control registerOLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current BrightnessOLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常OLED_WR_Byte(0xA6,OLED_CMD);//--set normal displayOLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 dutyOLED_WR_Byte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)OLED_WR_Byte(0x00,OLED_CMD);//-not offsetOLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequencyOLED_WR_Byte(0xF0,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/SecOLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge periodOLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 ClockOLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configurationOLED_WR_Byte(0x12,OLED_CMD);OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomhOLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect LevelOLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)OLED_WR_Byte(0x02,OLED_CMD);//OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disableOLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disableOLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panelOLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/ OLED_Clear();OLED_Set_Pos(0,0);
}
4.2 写命令和写数据函数
//向SSD1106写入一个字节。
//dat:要写入的数据/命令
//cmd:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 cmd)
{ u8 i; if(cmd)OLED_DC_Set();else OLED_DC_Clr(); OLED_CS_Clr();for(i=0;i<8;i++){ OLED_SCLK_Clr();if(dat&0x80)OLED_SDIN_Set();else OLED_SDIN_Clr();OLED_SCLK_Set();dat<<=1; } OLED_CS_Set();OLED_DC_Set();
}
4.3 各种显示驱动函数
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示
//size:选择字体 16/12
void OLED_ShowChar(u8 x,u8 y,u8 chr)
{ unsigned char c=0,i=0; c=chr-' ';//得到偏移后的值 if(x>Max_Column-1){x=0;y=y+2;}if(SIZE ==16){OLED_Set_Pos(x,y); for(i=0;i<8;i++)OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);OLED_Set_Pos(x,y+1);for(i=0;i<8;i++)OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);}else { OLED_Set_Pos(x,y+1);for(i=0;i<6;i++)OLED_WR_Byte(F6x8[c][i],OLED_DATA);}
}
//m^n函数
u32 oled_pow(u8 m,u8 n)
{u32 result=1; while(n--)result*=m; return result;
}
//显示2个数字
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//mode:模式 0,填充模式;1,叠加模式
//num:数值(0~4294967295);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size)
{ u8 t,temp;u8 enshow=0; for(t=0;t<len;t++){temp=(num/oled_pow(10,len-t-1))%10;if(enshow==0&&t<(len-1)){if(temp==0){OLED_ShowChar(x+(size/2)*t,y,' ');continue;}else enshow=1; }OLED_ShowChar(x+(size/2)*t,y,temp+'0'); }
}
//显示一个字符号串
void OLED_ShowString(u8 x,u8 y,u8 *chr)
{unsigned char j=0;while (chr[j]!='\0'){ OLED_ShowChar(x,y,chr[j]);x+=8;if(x>120){x=0;y+=2;}j++;}
}
//显示汉字
void OLED_ShowCHinese(u8 x,u8 y,u8 no)
{ u8 t,adder=0;OLED_Set_Pos(x,y); for(t=0;t<16;t++){OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);adder+=1;} OLED_Set_Pos(x,y+1); for(t=0;t<16;t++){ OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);adder+=1;}
}
取模软件下载地址:字模软件(ATK-XFONT) 版本:v2.0.3 — 正点原子资料下载中心 1.0.0 文档
五、IIC 接口驱动实现
5.1 IIC 通信基础
IIC 是一种串行通信协议,使用两根线(SDA 和 SCL)进行数据传输。在 STM32F407 中,可以使用 HAL 库提供的 I2C 函数进行通信。
5.2 初始化函数
#include "stm32f4xx_hal.h"// 定义I2C句柄
extern I2C_HandleTypeDef hi2c1;// OLED I2C地址
#define OLED_I2C_ADDR 0x78// 初始化OLED
void OLED_Init_I2C(void)
{// 复位OLEDHAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_RESET);HAL_Delay(100);HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_SET);HAL_Delay(100);// 发送初始化命令OLED_WriteCmd_I2C(0xAE); // 关闭显示OLED_WriteCmd_I2C(0xD5); // 设置时钟分频因子OLED_WriteCmd_I2C(0x80);// 其他初始化命令...OLED_WriteCmd_I2C(0xAF); // 开启显示
}
5.3 写命令和写数据函数
// 写命令(I2C)
void OLED_WriteCmd_I2C(uint8_t cmd)
{uint8_t data[2] = {0x00, cmd}; // 0x00表示写命令HAL_I2C_Master_Transmit(&hi2c1, OLED_I2C_ADDR, data, 2, 100);
}// 写数据(I2C)
void OLED_WriteData_I2C(uint8_t data)
{uint8_t data_to_send[2] = {0x40, data}; // 0x40表示写数据HAL_I2C_Master_Transmit(&hi2c1, OLED_I2C_ADDR, data_to_send, 2, 100);
}
代码解释
8080 接口代码
OLED_Init函数:对 OLED 进行复位操作,并发送一系列初始化命令来开启显示。OLED_WriteCmd函数:用于向 OLED 发送命令,通过控制 DC 引脚为低电平来指示写入的是命令。OLED_WriteData函数:用于向 OLED 发送数据,通过控制 DC 引脚为高电平来指示写入的是数据。OLED_ShowChar函数:在指定位置显示字符,通过调用OLED_WriteData函数将字符的点阵数据写入 OLED。
IIC 接口代码
OLED_Init_I2C函数:同样对 OLED 进行复位操作,并通过 I2C 接口发送初始化命令。OLED_WriteCmd_I2C函数:使用 HAL 库的HAL_I2C_Master_Transmit函数向 OLED 发送命令。OLED_WriteData_I2C函数:使用HAL_I2C_Master_Transmit函数向 OLED 发送数据。OLED_ShowChar_I2C函数:在指定位置显示字符,通过调用OLED_WriteData_I2C函数将字符的点阵数据写入 OLED。
六、代码优化与调试
6.1 代码优化
- 减少重复代码:将一些通用的操作封装成函数,如延时函数、引脚操作函数等。
- 优化数据传输:在 8080 接口中,可以考虑使用 DMA(Direct Memory Access)进行数据传输,提高传输效率。
6.2 调试技巧
- 使用调试工具:利用 STM32CubeIDE 或 Keil MDK 的调试功能,单步执行代码,观察变量的值和程序的执行流程。
- 添加调试信息:在关键位置添加打印语句,输出调试信息,帮助定位问题。
七、总结
通过本文的介绍,你可以基于 STM32F407 HAL 库实现 OLED 显示屏的 8080 接口和 IIC 接口驱动。8080 接口适合对通信速度要求较高的场景,而 IIC 接口则更适合引脚资源有限的情况。在实际开发中,可以根据具体需求选择合适的通信接口。
相关文章:
STM32 HAL库 OLED驱动实现
一、概述 1.1 OLED 显示屏简介 OLED(Organic Light - Emitting Diode)即有机发光二极管,与传统的 LCD 显示屏相比,OLED 具有自发光、视角广、响应速度快、对比度高、功耗低等优点。在嵌入式系统中,OLED 显示屏常被用…...
Excel通过VBA脚本去除重复数据行并保存
一、方法1:使用字典动态去重并保存 适用场景:需要灵活控制去重逻辑(如保留最后一次出现的重复项)时 Sub 动态去重保存到新表()Dim srcSheet As Worksheet, destSheet As WorksheetDim dict As Object, lastRow As Long, i As LongDim key A…...
大模型Prompt提示词越狱相关知识
大模型Prompt提示词越狱相关知识 一、什么是Prompt提示词越狱? 什么是Prompt提示词 Prompt是指你向AI输入的内容,它直接指示AI该做什么任务或生成什么样的输出,简而言之, Prompt就是你与AI之间的“对话内容”,可…...
3DMAX笔记-UV知识点和烘焙步骤
1. 在展UV时,如何点击模型,就能选中所有这个模型的uv 2. 分多张UV时,不同的UV的可以设置为不同的颜色,然后可以通过颜色进行筛选。 3. 烘焙步骤 摆放完UV后,要另存为一份文件,留作备份 将模型部件全部分成…...
【新人系列】Golang 入门(十三):结构体 - 下
✍ 个人博客:https://blog.csdn.net/Newin2020?typeblog 📝 专栏地址:https://blog.csdn.net/newin2020/category_12898955.html 📣 专栏定位:为 0 基础刚入门 Golang 的小伙伴提供详细的讲解,也欢迎大佬们…...
Spring Boot 自定义商标(Logo)的完整示例及配置说明( banner.txt 文件和配置文件属性信息)
Spring Boot 自定义商标(Logo)的完整示例及配置说明 1. Spring Boot 商标(Banner)功能概述 Spring Boot 在启动时会显示一个 ASCII 艺术的商标 LOGO(默认为 Spring 的标志)。开发者可通过以下方式自定义&a…...
Ubuntu虚拟机Linux系统入门
目录 一、安装 Ubuntu Linux 20.04系统 1.1 安装前准备工作 1.1.1 镜像下载 1.1.2 创建新的虚拟机 二、编译内核源码 2.1 下载源码 2.2 指定编译工具 2.3 将根文件系统放到源码根目录 2.4 配置生成.config 2.5 编译 三、安装aarch64交叉编译工具 四、安装QEMU 五、…...
【蓝桥杯】2025省赛PythonB组复盘
前言 昨天蓝桥杯python省赛B组比完,今天在洛谷上估了下分,省一没有意外的话应该是稳了。这篇博文是对省赛试题的复盘,所给代码是省赛提交的代码。PB省赛洛谷题单 试题 A: 攻击次数 思路 这题目前有歧义,一个回合到底是只有一个…...
深入解析区块链技术:原理、应用与未来展望
1 区块链技术原理 1.1 基本概念 区块链本质上是一个分布式账本,它由一系列按照时间顺序排列的数据块组成,每个数据块包含了一定时间内的交易信息。这些数据块通过密码学技术相互链接,形成一个不可篡改的链条。其核心特点包括去中心化、不可篡…...
Linux进程替换与自定义shell详解
引言 进程替换和shell编程是Linux系统中极其重要的概念,它们不仅是系统内部工作的基础机制,也是系统管理员和开发者必备的技能。本文将深入探讨Linux中的进程替换原理、系统调用实现以及如何创建自定义shell,帮助你全面理解这些重要概念并掌…...
【数据结构_4下篇】链表
一、链表的概念 链表,不要求在连续的内存空间,链表是一个离散的结构。 链表的元素和元素之间,内存是不连续的,而且这些元素的空间之间也没有什么规律: 1.顺序上没有规律 2.内存空间上也没有规律 *如何知道链表中包…...
Mybatis的简单介绍
文章目录 MyBatis 简介 1. MyBatis 核心特点2. MyBatis 核心组件3. MyBatis 基本使用示例(1) 依赖引入(Maven)(2) 定义 Mapper 接口(3) 定义实体类(4) 在 Service 层调用 4. MyBatis 与 JPA/Hibernate 对比 MyBatis 简介 MyBatis 是一款优秀的 持久层框…...
JavaScript 性能优化实战:深入探讨 JavaScript 性能瓶颈,分享优化技巧与最佳实践
在当今 Web 应用日益复杂的时代,JavaScript 性能对于用户体验起着决定性作用。缓慢的脚本执行会导致页面加载延迟、交互卡顿,严重影响用户留存率。本文将深入剖析 JavaScript 性能瓶颈,并分享一系列实用的优化技巧与最佳实践,助你…...
1g内存电脑sqlite能支持多少并发
1. SQLite的并发机制 写操作:默认使用串行锁,同一时间仅允许一个写操作(其他写/读需等待)。读操作:支持多并发读取,但受内存、磁盘I/O和配置限制。 2. 关键限制因素 (1)内存资源 …...
jetpack之jetpack的概括和其中组件的简单使用
注意⚠:此篇文章由deepseek大力支持!!!(╹ڡ╹ ) 主要是对不知道学什么,对各个组件一头雾水的jetpack新手准备的文章 不知道jetpack学什么,就看这篇文章!! 1. DataBindingÿ…...
音视频 五 看书的笔记 MediaCodec
MediaCodec 用于访问底层媒体编解码器框架,编解码组件。通常与MediaExtractor(解封装,例如Mp4文件分解成 video和audio)、MediaSync、MediaMuxer(封装 例如音视频合成Mp4文件)、MediaCrypto、Image(cameraX 回调的ImageReader对象可以获取到Image帧图像,可转换成YU…...
物联网|无人自助台球厅源码|哪些框架支持多设备连接?
在无人自助台球厅的智能化管理中,物联网(IoT)技术是核心支撑。如何实现不同设备(如智能门锁、环境传感器、支付终端、灯光控制系统等)的高效连接与协同工作,是系统开发的关键挑战。本文将带大家探讨支持多设…...
Python中NumPy的统计运算
在数据分析和科学计算领域,Python凭借其丰富的库生态系统成为首选工具之一,而NumPy作为Python数值计算的核心库,凭借其高效的数组操作和强大的统计运算功能,广泛应用于机器学习、信号处理、统计分析等场景。本文将系统介绍NumPy在…...
uniapp实现H5页面麦克风权限获取与录音功能
1.权限配置 在uni-app开发H5页面时,需要在manifest.json文件中添加录音权限的配置。具体如下: {"h5": {"permissions": {"scope.record": {"desc": "请授权使用录音功能"}}} }这段配置代码是用于向…...
两个树莓派如何通过wifi direct传输视频并显示
这里写自定义目录标题 在两台设备上安装必要软件Wi-Fi Direct接收端IP(自动发现或静态设置)设置摄像头参数显示初始化网络设置 系统架构概述 发送端树莓派:捕获视频(摄像头或视频文件)→ 编码 → 通过Wi-Fi Direct传输…...
ubuntu 系统安装Mysql
安装 mysql sudo apt update sudo apt install mysql-server 启动服务 sudo systemctl start mysql 设置为开机自启 sudo systemctl enable mysql 查看服务状态 (看到类似“active (running)”的状态信息代表成功) sudo systemctl status mysql …...
selenium快速入门
一、操作浏览器 from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By# 设置选项 q1 Options() q1.add_argument("--no-sandbo…...
Redis:线程模型
单线程模型 Redis 自诞生以来,一直以高性能著称。很多人好奇,Redis 为什么早期采用单线程模型,它真的比多线程还快吗? 其实,Redis 的“快”并不在于并发线程,而在于其整体架构设计极致简单高效,…...
Transformer模型解析与实例:搭建一个自己的预测语言模型
目录 1. 前言 2. Transformer 的核心结构 2.1 编码器(Encoder) 2.2 解码器(Decoder) 2.3 位置编码(Positional Encoding) 3. 使用 PyTorch 构建 Transformer 3.1 导入所需的模块: 3.2 定…...
Java常用安全编码的规范整理及工具
对Java安全编码的主要规范及要求的一些整理: 一、输入验证与数据校验 外部输入校验 对所有外部输入(如用户输入、文件、网络数据)进行合法性校验,采用白名单机制限制输入内容范围 。校验前对输入数据做归一化处理ÿ…...
重返JAVA之路——面向对象
目录 面向对象 1.什么是面向对象? 2.面向对象的特点有哪些? 3.什么是对象? 4.什么是类? 5.什么是构造方法? 6.构造方法的特性有哪些? 封装 1.什么是封装? 2.封装有哪些特点? 数据隐…...
Java设计模式全解析(共 23 种)
一、设计模式全解: Java 中的设计模式是为了解决在软件开发中常见问题的一些“最佳实践”总结。设计模式分为三大类,共 23 种经典模式: 1. 创建型模式(5 种) 用于对象的创建,解决对象实例化过程中的问题。…...
Python10天突击--Day 2: 实现观察者模式
以下是 Python 实现观察者模式的完整方案,包含同步/异步支持、类型注解、线程安全等特性: 1. 经典观察者模式实现 from abc import ABC, abstractmethod from typing import List, Anyclass Observer(ABC):"""观察者抽象基类""…...
springboot框架集成websocket依赖实现物联网设备、前端网页实时通信!
需求: 最近在对接一个物联网里设备,他的通信方式是 websocket 。所以我需要在 springboot框架中集成websocket 依赖,从而实现与设备实时通信! 框架:springboot2.7 java版本:java8 好了,还是直接…...
【玩泰山派】5、点灯,驱动led-(2)ubuntu18.04 升级python3.6到python3.7,安装pip3
文章目录 前言升级python3.71、安装 software-properties-common 包2、添加 deadsnakes PPA 源3、安装 Python 3.71. 安装 Python 3.72. 安装 Python 3.7 的开发包和虚拟环境支持(可选但推荐)3. 设置 Python 3.7 为默认版本4. 验证 Python 版本注意事项 …...
