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 接口则更适合引脚资源有限的情况。在实际开发中,可以根据具体需求选择合适的通信接口。

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/76782.shtml

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    Web开发-JavaEE应用动态接口代理原生反序列化危险Invoke重写方法利用链

    知识点&#xff1a; 1、安全开发-JavaEE-动态代理&序列化&反序列化 2、安全开发-JavaEE-readObject&toString方法 一、演示案例-WEB开发-JavaEE-动态代理 动态代理 代理模式Java当中最常用的设计模式之一。其特征是代理类与委托类有同样的接口&#xff0c;代理类…

    K8s是常用命令和解释

    K8s高频命令 获取资源信息&#xff0c;如获取 Pod、Service、Deployment等资源状态信息 kubectl get创建资源如创建Pod、Service、Deployment等资源 kubectl create删除资源&#xff0c;如删除Pod、Service、Deployment等资源 kubectl delete 应用配置文件&#xff0c;如引用D…

    【模态分解】EMD-经验模态分解

    算法配置页面&#xff0c;也可以一键导出结果数据 报表自定义绘制 获取和下载【PHM学习软件PHM源码】的方式 获取方式&#xff1a;Docshttps://jcn362s9p4t8.feishu.cn/wiki/A0NXwPxY3ie1cGkOy08cru6vnvc

    TDengine 语言连接器(Go)

    简介 driver-go 是 TDengine 的官方 Go 语言连接器&#xff0c;实现了 Go 语言 database/sql 包的接口。Go 开发人员可以通过它开发存取 TDengine 集群数据的应用软件。 Go 版本兼容性 支持 Go 1.14 及以上版本。 支持的平台 原生连接支持的平台和 TDengine 客户端驱动支持…

    链接世界:计算机网络的核心与前沿

    计算机网络引言 在数字化时代&#xff0c;计算机网络已经成为我们日常生活和工作中不可或缺的基础设施。从简单的局域网&#xff08;LAN&#xff09;到全球互联网&#xff0c;计算机网络将数以亿计的设备连接在一起&#xff0c;推动了信息交换、资源共享以及全球化的进程。 什…

    AI agents系列之全面介绍

    随着大型语言模型(LLMs)的出现,人工智能(AI)取得了巨大的飞跃。这些强大的系统彻底改变了自然语言处理,但当它们与代理能力结合时,才真正释放出潜力——能够自主地推理、规划和行动。这就是LLM代理大显身手的地方,它们代表了我们与AI交互以及利用AI的方式的范式转变。 …

    如何使用AI辅助开发CSS3 - 通义灵码功能全解析

    一、引言 CSS3 作为最新的 CSS 标准&#xff0c;引入了众多新特性&#xff0c;如弹性布局、网格布局等&#xff0c;极大地丰富了网页样式的设计能力。然而&#xff0c;CSS3 的样式规则繁多&#xff0c;记忆所有规则对于开发者来说几乎是不可能的任务。在实际开发中&#xff0c…

    复刻系列-星穹铁道 3.2 版本先行展示页

    复刻星穹铁道 3.2 版本先行展示页 0. 视频 手搓&#xff5e;星穹铁道&#xff5e;展示页&#xff5e;&#xff5e;&#xff5e; 1. 基本信息 作者: 啊是特嗷桃系列: 复刻系列官方的网站: 《崩坏&#xff1a;星穹铁道》3.2版本「走过安眠地的花丛」专题展示页现已上线复刻的网…

    爬虫:IP代理

    什么是代理 代理服务器 代理服务器的作用 就是用来转发请求和响应 在爬虫中为何需要使用代理&#xff1f; 有些时候&#xff0c;需要对网站服务器发起高频的请求&#xff0c;网站的服务器会检测到这样的异常现象&#xff0c;则会讲请求对应机器的ip地址加入黑名单&#xff…

    协程的原生挂起与恢复机制

    目录 &#x1f50d; 一、从开发者视角看协程挂起与恢复 &#x1f9e0; 二、协程挂起和恢复的机制原理&#xff1a;核心关键词 ✅ suspend 函数 ≠ 普通函数 ✅ Continuation&#xff08;协程的控制器&#xff09; &#x1f527; 三、编译器做了什么&#xff1f;&#xff0…

    c++11--std::forwaord--完美转发

    std::forword的作用 完美转发的核心目的是保持参数的原始类型&#xff08;包括const/volatile限定符和左值/右值性质&#xff09;不变地传递给其他函数。 为什么需要完美转发 在没有完美转发之前&#xff0c;我们面临以下问题&#xff1a; 模板参数传递中的值类别丢失 当参数…

    Linux安装开源版MQTT Broker——EMQX服务器环境从零到一的详细搭建教程

    零、EMQX各个版本的区别 EMQX各个版本的功能对比详情https://docs.emqx.com/zh/emqx/latest/getting-started/feature-comparison.html

    计算机组成原理-存储器

    1. 存储器的定义与作用 存储器是计算机系统中用于存储程序、数据和中间结果的硬件设备&#xff0c;是计算机五大核心部件之一。 核心功能&#xff1a; 提供数据的 临时或永久存储 能力。支持CPU按需快速存取指令和数据&#xff0c;是程序运行的物理基础。 2. 存储器的分类 …

    单片机领域中哈希表

    以下是单片机领域中哈希表的实际应用及编程实例&#xff1a; 1.哈希表在单片机中的实际应用场景 • 命令解析&#xff1a;在单片机通信中&#xff0c;经常需要解析接收到的命令。使用哈希表可以快速地将命令字符串映射到对应的处理函数&#xff0c;提高命令解析的效率。 • 数…

    算法思想之位运算(一)

    欢迎拜访&#xff1a;雾里看山-CSDN博客 本篇主题&#xff1a;算法思想之位运算(一) 发布时间&#xff1a;2025.4.12 隶属专栏&#xff1a;算法 目录 滑动窗口算法介绍六大基础位运算符常用模板总结 例题位1的个数题目链接题目描述算法思路代码实现 比特位计数题目链接题目描述…

    封装Tcp Socket

    封装Tcp Socket 0. 前言1. Socket.hpp2. 简单的使用介绍 0. 前言 本文中用到的Log.hpp在笔者的历史文章中都有涉及&#xff0c;这里就不再粘贴源码了&#xff0c;学习地址如下&#xff1a;https://blog.csdn.net/weixin_73870552/article/details/145434855?spm1001.2014.3001…

    全星APQP软件:为用户提供高效、合规、便捷的研发管理体验

    全星APQP软件&#xff1a;为用户提供高效、合规、便捷的研发管理体验 为什么选择全星APQP软件系统&#xff1f; 在汽车及高端制造行业&#xff0c;研发项目管理涉及APQP&#xff08;先期产品质量策划&#xff09;、FMEA&#xff08;失效模式与影响分析&#xff09;、CP&#x…

    CTF--网站被黑

    一、原题&#xff1a; &#xff08;1&#xff09;提示&#xff1a;网站被黑了 黑客会不会留下后门 &#xff08;2&#xff09;原网页&#xff1a; 二、步骤&#xff1a; 1.在终端扫描网址&#xff1a; 2.扫描后发现&#xff1a;shell.php 3.输入网址&#xff1a;http://117.…

    入门到精通,C语言十大经典程序

    以下是十个经典的C语言程序示例&#xff0c;这些程序涵盖了从基础到稍复杂的应用场景&#xff0c;适合初学者和有一定基础的开发者学习和参考。 1. Hello, World! 这是每个初学者学习编程时的第一个程序&#xff0c;用于验证开发环境是否正确配置。 #include <stdio.h>…

    神经网络入门—自定义神经网络续集

    修改网络 神经网络入门—自定义网络-CSDN博客 修改数据集&#xff0c;yx^2 # 生成一些示例数据 x_train torch.tensor([[1.0], [2.0], [3.0], [4.0]], dtypetorch.float32) y_train torch.tensor([[1.0], [4.0], [9.0], [16.0]], dtypetorch.float32) 将预测代码改为&…