【0.96寸 OLED屏实现1500Fps的帧率】STM32 软件、硬件SPI、I2C驱动总结
目录
- SPI版
- OLED SPI 端口定义
- 七针OLED引脚定义
- 六针OLED引脚定义
- 软件SPI
- 硬件SPI
- 启用DMA
- 帧率测试
- I2C 版
- 软件I2C
- 硬件I2C
- DMA
STM32F103VET6
STM32 Cube IDE
SPI版
OLED SPI 端口定义
本节引自STM32驱动0.96寸OLED液晶屏(12864液晶屏) —— 小牧同学
两种屏幕的引脚数不一样,左边的有7个引脚,而右边的只有6个。其次,端口的标号也不完全一样,第一个分别标为GND,VCC,D0,D1,RES,DC和CS第二个分别标为GND,VCC,SCL,SDA,RST,D/C。
七针OLED引脚定义
GND — 接地端口
VCC — 接3.3V电源端口
D0 — CLK时钟信号(等同于上面的SCL)
D1 — 数据端口(等同于上面的SDA)
RES — 复位端口(等同于上面的RST)
DC — 数据/命令选择引脚(等同于上面的D/C)
CS — 片选引脚(低电平有效,也就是所需要接低电平,我实际试验过不接该引脚也是可以正常使用的)
六针OLED引脚定义
GND — 接地端口
VCC — 接3.3V电源端口
SCL — CLK时钟信号端口
SDA — MOSI数据端口
RST — 复位端口
D/C — 数据/命令选择引脚
软件SPI
指令解读见【51单片机快速入门指南】4.2: SSD1306 OLED屏(0.96寸、1.3寸)的I2C控制详解
各引脚初始化如下,均为推挽输出:
从【51单片机快速入门指南】5:软件SPI获取软件SPI程序。
修改控制电平的函数:
GPIOx->BSRR = GPIO_Pin;GPIOx->BSRR = (uint32_t)GPIO_Pin << 16u;
由于我们需要的只是单向的、半双工的SPI,只需修改部分函数即可
从SPI驱动0.96/1.3寸 OLED屏幕,易修改为DMA控制获取SPI版驱动程序。
将51特色的code改为const
修改对应引脚
修改延时函数
在主函数中添加测试程序:
如图,屏幕已轻松点亮。
帧率为180(见后文)
使用虚拟显存是时为46帧
硬件SPI
如图,使用硬件SPI
移除软件SPI的程序,修改OLED_WR_Byte函数
extern SPI_HandleTypeDef hspi1;
void OLED_WR_Byte(uint8_t dat, uint8_t cmd)
{OLED_CS_L();if (cmd)OLED_DC_H();elseOLED_DC_L();
// SOFT_SPI_RW_MODE2(dat);HAL_SPI_Transmit(&hspi1, &dat, 1, 10);OLED_DC_H();OLED_CS_H();
}
再次测试:
成功点亮
帧率为410
在oled.h中启用虚拟显存
修改OLED_Refresh_Gram函数,实现1024 Byte 显存连续写入
extern SPI_HandleTypeDef hspi1;
void OLED_Refresh_Gram(void)
{#if OLED_BUFFER_MODE
// uint16_t i;OLED_Set_Pos(0, 128);
// for (i = 0; i < Max_Row / 8 * Max_Column; i++)
// {// OLED_WR_Byte(OLED_GRAM[0][i], OLED_DATA);
// }OLED_CS_L();OLED_DC_H();HAL_SPI_Transmit(&hspi1, OLED_GRAM[0], Max_Row / 8 * Max_Column, 10);OLED_DC_H();OLED_CS_H();
#endif
}
再次测试,仍能成功点亮,帧率为969。
启用DMA
再次修改OLED_Refresh_Gram函数
extern SPI_HandleTypeDef hspi1;
void OLED_Refresh_Gram(void)
{#if OLED_BUFFER_MODE
// uint16_t i;OLED_Set_Pos(0, 128);
// for (i = 0; i < Max_Row / 8 * Max_Column; i++)
// {// OLED_WR_Byte(OLED_GRAM[0][i], OLED_DATA);
// }OLED_CS_L();OLED_DC_H();
// HAL_SPI_Transmit(&hspi1, OLED_GRAM[0], Max_Row / 8 * Max_Column, 10);HAL_SPI_Transmit_DMA(&hspi1, OLED_GRAM[0], Max_Row / 8 * Max_Column);while(hspi1.State != HAL_SPI_STATE_READY);OLED_DC_H();OLED_CS_H();
#endif
}
帧率测试
帧率的显示:
在1ms中断中统计1s内的帧数
在每次更新屏幕内容时FPS_Count自加1
这个帧率已经远远超过屏幕本身所能提供的刷新率了。
I2C 版
软件I2C
将SCL设为推挽输出,SDA设为开漏上拉输出
从【51单片机快速入门指南】4.2: SSD1306 OLED屏(0.96寸、1.3寸)的I2C控制详解和【51单片机快速入门指南】4: 软件 I2C获取控制程序。
修改对应引脚,其他部分同SPI的步骤。
//SCL拉高 移植时需修改
void I2C_SCL_H(void)
{OLED_SCL_GPIO_Port->BSRR = OLED_SCL_Pin;
}//SCL拉低 移植时需修改
void I2C_SCL_L(void)
{OLED_SCL_GPIO_Port->BSRR = (uint32_t)OLED_SCL_Pin << 16u;
}//SDA拉高 移植时需修改
void I2C_SDA_H(void)
{OLED_SDA_GPIO_Port->BSRR = OLED_SDA_Pin;
}//SDA拉低 移植时需修改
void I2C_SDA_L(void)
{OLED_SDA_GPIO_Port->BSRR = (uint32_t)OLED_SDA_Pin << 16u;
}//读取SDA 移植时需修改
uint8_t I2C_SDA_Read(void)
{OLED_SDA_GPIO_Port->BSRR = (uint32_t)OLED_SDA_Pin << 16u;i2c_delay();return ((OLED_SDA_GPIO_Port->IDR & OLED_SDA_Pin) == 0?0:1);
}
测试:
帧率约为60帧
硬件I2C
修改OLED_WR_Byte函数
extern I2C_HandleTypeDef hi2c1;
void OLED_WR_Byte(uint8_t dat, uint8_t cmd)
{if (cmd)HAL_I2C_Mem_Write(&hi2c1, OLED_ADDRESS << 1, OLED_WriteData_Addr, I2C_MEMADD_SIZE_8BIT, &dat, 1, 10);elseHAL_I2C_Mem_Write(&hi2c1, OLED_ADDRESS << 1, OLED_WriteCom_Addr, I2C_MEMADD_SIZE_8BIT, &dat, 1, 10);
}
此时帧率为49
开虚拟显存模式,修改OLED_Refresh_Gram函数
extern I2C_HandleTypeDef hi2c1;
void OLED_Refresh_Gram(void)
{#if OLED_BUFFER_MODE
// uint16_t i;OLED_Set_Pos(0, 128);
// for (i = 0; i < Max_Row / 8 * Max_Column; i++)
// {// OLED_WR_Byte(OLED_GRAM[0][i], OLED_DATA);
// }HAL_I2C_Mem_Write(&hi2c1, OLED_ADDRESS << 1, OLED_WriteData_Addr, I2C_MEMADD_SIZE_8BIT, OLED_GRAM[0], Max_Row / 8 * Max_Column, 1000);
#endif
}
发现会更慢
DMA
开中断
再次修改OLED_Refresh_Gram函数
extern I2C_HandleTypeDef hi2c1;
void OLED_Refresh_Gram(void)
{#if OLED_BUFFER_MODE
// uint16_t i;OLED_Set_Pos(0, 128);
// for (i = 0; i < Max_Row / 8 * Max_Column; i++)
// {// OLED_WR_Byte(OLED_GRAM[0][i], OLED_DATA);
// }
// HAL_I2C_Mem_Write(&hi2c1, OLED_ADDRESS << 1, OLED_WriteData_Addr, I2C_MEMADD_SIZE_8BIT, OLED_GRAM[0], Max_Row / 8 * Max_Column, 1000);while(hi2c1.State != HAL_I2C_STATE_READY);HAL_I2C_Mem_Write_DMA(&hi2c1, OLED_ADDRESS << 1, OLED_WriteData_Addr, I2C_MEMADD_SIZE_8BIT, OLED_GRAM[0], Max_Row / 8 * Max_Column);
#endif
}
如图,瓶颈应为400kHz的I2C速度
【0.96寸 OLED屏实现1500Fps的帧率】STM32 软件、硬件SPI、I2C驱动总结相关推荐
- 【STM32】HAL库在7针脚0.96寸OLED屏上的移植---硬件SPI(一)
目录 SPI背景和接线 1.什么是SPI 2.如何接线 STM32CubeMX部分 1.配置时钟 2.配置SPI 3.工程生成 MDK 5 部分 1.移植OLED文件 2.修改引脚 3.修改main函 ...
- 0.96寸OLED屏硬件驱动电路
0.96寸OLED屏硬件驱动电路 该电路适合把OLED驱动电路集成到自己的板子上,最终的原理图和PCB已经上传CSDN,可直接点击链接下载: https://download.csdn.net/dow ...
- 0.96寸OLED屏显示(IIC通信)Ⅰ
0.96寸OLED屏显示(IIC通信) 一.0.96寸OLED简介 0.96寸OLED屏内部驱动IC为SSD1306:兼容6800.8080两种并行接口方式,3线或 4线的串行SPI接口方式和 I ...
- 0.96寸OLED屏使用详解
如何理解OLED分辨率? 这里0.96寸OLED分辨率是128*64;即OLED显示是128行*64列; 但是由于OLED不能一次控制一个点阵,只能控制8个点阵;而且是垂直方向扫描控制;如下图;因此垂 ...
- 基于STM32的0.96寸OLED屏显示学号姓名和滚动显示
文章目录 **一.SPI(串行外设接口)** **二.使用0.96寸OLED显示屏显示学号姓名** **三.0.96寸OLED在STM32f103上实现滚动显示长字符** **四.参考资料** 一.S ...
- 基于STM32和阿里云的矿道环境监测系统(温湿度DHT117,NRF2401(2.4G模块),气体传感器(MQ-3),0.96寸OLED屏,wifi模块)
基于STM32和阿里云的矿道环境监测系统(温湿度DHT117,NRF2401(2.4G模块),气体传感器(MQ-3)) 系统实现的功能 系统实现的是运用一块STM32F103C8T6作为发射端节点,上 ...
- STM32 I2C驱动0.96寸OLED屏
本文以STM32F103C8T6最小系统板为例 OLED屏为128*64像素 驱动芯片SSD1306 本文讲解标准库 硬件IIC和软件IIC 驱动OLED 硬件IIC ...
- STM32Mini基于SPI接口的0.96寸OLED屏数据显示
文章目录 一.实验资料准备 1.下载工程包 2.引脚接法 3.字模软件准备 4.了解SPI(串行外设接口) (1)SPI的定义 (2)SPI的连接方式 (3)SPI的通讯过程 5.了解OLED屏的滚屏 ...
- 用stm32f103c8t6点亮0.96寸oled屏(附带百度云例程)
oled的技术文档中的例程好像时用keil4开发的,keil5打开时有问题,因此用自己建的c8t6工程做了移植,亲测有效. 首先挂出链接 链接:https://pan.baidu.com/s/19H5 ...
最新文章
- php登录失败后,php – X尝试失败后阻止登录
- 学习python的日常6
- 面试题:接口和抽象类的区别
- MFC CListCtrl 取消选中
- 从零开始netty学习笔记之BIO
- Redux源码全篇浅读
- Firefox浏览器常见问题开讲
- Autowire异常
- sharepoint被阻止的文件类型解释说明
- 设计模式学习之单例模式
- vscode python 远程调试_vscode 远程调试python的方法
- 三角形面积 java_java编程中求三角形面积肿么写?
- SendMessageTimeOut函数使用方法
- Linux从用户层到内核层系列 - GNU系列之glibc介绍
- Dev C++使用教程(使用Dev C++编写C语言程序)
- excel冻结窗口_东莞黄江办公自动化培训零基础电脑Excel培训中心
- None of the configured nodes are available
- 旧历九月十六是老爸的生日,现在我才晓得
- KTV点歌系统数字点歌功能
- R和RStudio安装包下载