U8G2移植到STM32,SSD13XXXOLED(硬件SPI DMA通讯)

文章目录

  • 一、前言
    • 1.1 U8g2的特点
    • 1.2 U8G2的优势
    • 1.3 U8G2的下载地址
    • 1.4 U8g2支持的显示控制器
  • 二、STM32Cubexm SPI DMA配置
    • 2.1 SPI设置为半双工模式
    • 2.2 SPI DMA设置
    • 2.3 oled其他引脚配置
  • 三、移植U8G2框架
    • 3.1 精简U8G2库文件
    • 3.2 去掉csrc文件夹中无用的驱动文件
    • 3.3 文件移动到keil
    • 3.4 精简u8g2_d_setup.c(注意不是u8x8_setup.c)
    • 3.5 精简u8g2_d_memory.c
    • 3.6 编写回调函数
    • 3.7 main函数调用
  • 四、最终效果
  • 五、工程下载

一、前言

在嵌入式开发中,显示屏是常见的外设之一。OLED屏幕因其高对比度和低功耗,被广泛应用于各种嵌入式系统中。本文将详细介绍如何在STM32平台上使用SPI DMA方式移植U8G2库到 SSD1306 OLED屏幕。

1.1 U8g2的特点

U8G2是一个流行的图形显示库,用于控制嵌入式系统中的各种图形显示器。它由Oliver Kraus开发和维护,广泛支持多种显示屏控制器。U8G2库特别适合资源受限的微控制器平台,如Arduino、STM32和ESP8266/ESP32等。

  • U8g2的特点
    1. 多种显示器支持U8G2库支持许多不同的显示器控制器,包括常见的OLEDLCD显示器。例如,SSD1306、SSD1322、ST7920等控制器都在U8G2库的支持范围内。
    2. 多种接口支持U8G2支持多种接口协议,如I2CSPI和并行接口。这使得它可以与不同类型的显示器和微控制器配合使用。
    3. 多种字体和图形功能:U8G2库内置了丰富的字体和图形功能,可以显示文本、图形、图标和形状。用户可以选择不同的字体大小和样式来满足不同的显示需求。
    4. 双缓冲和单缓冲模式:U8G2支持双缓冲和单缓冲模式。双缓冲模式可以实现更流畅的屏幕刷新效果,但需要更多的内存;单缓冲模式则适用于内存较为紧张的系统。
    5. 易于使用的API:U8G2提供了一组易于使用的API,使得开发者可以快速实现复杂的图形显示功能。其API设计简洁明了,适合各种编程水平的用户。

1.2 U8G2的优势

  • 跨平台性:U8G2库可以在多种平台上使用,包括Arduino、STM32、ESP8266/ESP32等。这使得开发者可以在不同的硬件平台上复用相同的代码。
  • 丰富的文档和社区支持:U8G2库有详细的文档和大量的示例代码,方便开发者快速上手。此外,U8G2社区活跃,开发者可以在GitHub和各大技术论坛上找到许多有价值的讨论和资源。
  • 性能优化:U8G2库经过优化,可以在资源受限的微控制器上高效运行。同时,U8G2还支持硬件加速和DMA传输等高级功能,以提高显示性能。

1.3 U8G2的下载地址

u8g2 git链接

1.4 U8g2支持的显示控制器

SSD1305SSD1306SSD1309SSD1312SSD1316SSD1320
SSD1322SSD1325SSD1327SSD1329SSD1606SSD1607
SH1106SH1107SH1108SH1122T6963RA8835
LC7981PCD8544PCF8812HX1230UC1601UC1604
UC1701UC1608UC1610UC1611UC1617UC1638
ST7511ST7528ST7565ST7567ST7571ST7586
ST7588ST75256ST75320NT7534ST7920IST3020
IST7920LD7032KS0108KS0713HD44102T7932
SED1520SBN1661IL3820MAX7219

可以说,基本上主流的显示控制器都支持,比如我们常见的SSD1306等,读者在使用该库之前请查阅自己的OLED显示控制器是否处于支持列表中。

二、STM32Cubexm SPI DMA配置

这里就不说怎么创建工程,怎么设置时钟,基本配置自行配置

2.1 SPI设置为半双工模式

OLED只有发送数据的模式,所以只需要发送就可以了。(速度不要大于9M)

在这里插入图片描述

2.2 SPI DMA设置

在这里插入图片描述

2.3 oled其他引脚配置

CS拉高 其他拉低
在这里插入图片描述

然后就可以生成代码了

三、移植U8G2框架

3.1 精简U8G2库文件

如果没下载,下载地址在 1.3 请自行下载

  • U8g2支持多种显示驱动的屏幕,因为源码中也包含了各个驱动对应的文件(因此不需要自己去写屏幕底层驱动了),为了减小整个工程的代码体积和芯片资源占用,在移植U8g2时,可以删除一些无用的文件。
  • 这里我们主要关注的是U8g2库文件中的csrc文件夹
    在这里插入图片描述

3.2 去掉csrc文件夹中无用的驱动文件

这些驱动文件通常是u8x8_d_xxx.cxxx包括驱动的型号屏幕分辨率ssd1306驱动芯片的OLED,使用u8x8_ssd1306_128x64_noname.c这个文件,其它的屏幕驱动和分辨率的文件可以删掉。

在这里插入图片描述

3.3 文件移动到keil

  • .c 文件加入keil 工程

在这里插入图片描述

  • 添加 .h 文件的路径

在这里插入图片描述

3.4 精简u8g2_d_setup.c(注意不是u8x8_setup.c)

由于本文使用的OLED是SPI接口,只留一个本次要用到u8g2_Setup_ssd1306_128x64_noname_f就好(如果是IIC接口,需要使用u8g2_Setup_ssd1306_i2c_128x64_noname_f这个函数,多了i2c注意区分),其它的可以删掉或注释掉。
在这里插入图片描述

注意,与这个函数看起来十分相似的函数的有:

  • u8g2_Setup_ssd1306_128x64_noname_1
  • u8g2_Setup_ssd1306_128x64_noname_2
  • u8g2_Setup_ssd1306_128x64_noname_f
  • u8g2_Setup_ssd1306_i2c_128x64_noname_1
  • u8g2_Setup_ssd1306_i2c_128x64_noname_2
  • u8g2_Setup_ssd1306_i2c_128x64_noname_f

其中,前面3个,是给SPI接口的OLED用的,后面3个,是给I2C用的函数最后的数字或字母,代表显示时的buf大小:

  • 1:128字节

  • 2:256字节

  • f:1024字节也有可能是512字节

3.5 精简u8g2_d_memory.c

u8g2_d_memory.c文件中,由于用到的u8g2_Setup_ssd1306_128x64_noname_f函数中,只调用了u8g2_m_16_8_f这个函数,所以只用留下这个函数,如果你用的其他函数,在8g2_d_memory.c留下它相对应调用到的函数即可,其它的函数要删掉或注释,否则编译时很可能会导致内存不足
在这里插入图片描述

3.6 编写回调函数

#include "u8g2.h"#define MD_OLED_RST_Clr() HAL_GPIO_WritePin(OLED_RES_GPIO_Port,OLED_RES_Pin,GPIO_PIN_RESET) //oled 复位端口操作
#define MD_OLED_RST_Set() HAL_GPIO_WritePin(OLED_RES_GPIO_Port,OLED_RES_Pin,GPIO_PIN_SET)uint8_t u8x8_byte_4wire_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,void *arg_ptr)
{switch (msg){case U8X8_MSG_BYTE_SEND: /*通过SPI发送arg_int个字节数据*/
//           HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *)arg_ptr, arg_int);while(hspi1.TxXferCount);/*配置了DMA取消上一行注释即可*/HAL_SPI_Transmit(&hspi1,(uint8_t *)arg_ptr,arg_int,200);/*这是CubeMX生成的初始化*/break;case U8X8_MSG_BYTE_INIT: /*初始化函数*/break;case U8X8_MSG_BYTE_SET_DC: /*设置DC引脚,表明发送的是数据还是命令*/HAL_GPIO_WritePin(OLED_DC_GPIO_Port,OLED_DC_Pin,(GPIO_PinState)arg_int);break;case U8X8_MSG_BYTE_START_TRANSFER: u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);break;case U8X8_MSG_BYTE_END_TRANSFER: u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);break;default:return 0;}return 1;
}uint8_t u8x8_stm32_gpio_and_delay(U8X8_UNUSED u8x8_t *u8x8,U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int,U8X8_UNUSED void *arg_ptr) 
{switch (msg){case U8X8_MSG_GPIO_AND_DELAY_INIT: /*delay和GPIO的初始化,在main中已经初始化完成了*/break;case U8X8_MSG_DELAY_MILLI: /*延时函数*/HAL_Delay(arg_int);     //调用谁stm32系统延时函数break;case U8X8_MSG_GPIO_CS: /*片选信号*/ //由于只有一个SPI设备,所以片选信号在初始化时已经设置为常有效HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, (GPIO_PinState)arg_int);break;case U8X8_MSG_GPIO_DC: /*设置DC引脚,表明发送的是数据还是命令*/HAL_GPIO_WritePin(OLED_DC_GPIO_Port,OLED_DC_Pin,(GPIO_PinState)arg_int);break;case U8X8_MSG_GPIO_RESET:break;}return 1;
}void u8g2Init(u8g2_t *u8g2)
{
/********************************************     
U8G2_R0     //不旋转,不镜像     
U8G2_R1     //旋转90度
U8G2_R2     //旋转180度   
U8G2_R3     //旋转270度
U8G2_MIRROR   //没有旋转,横向显示左右镜像
U8G2_MIRROR_VERTICAL    //没有旋转,竖向显示镜像
********************************************/
//    u8g2_Setup_sh1106_128x64_noname_2(u8g2, U8G2_R0, u8x8_byte_4wire_hw_spi, u8x8_stm32_gpio_and_delay);  // 初始化1.3寸OLED u8g2 结构体u8g2_Setup_ssd1306_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_4wire_hw_spi, u8x8_stm32_gpio_and_delay);  // 初始化0.96寸OLED u8g2 结构体u8g2_InitDisplay(u8g2);     //初始化显示u8g2_SetPowerSave(u8g2, 0); //开启显示
}
/*官方logo的Demo*/
void draw(u8g2_t *u8g2)
{u8g2_SetFontMode(u8g2, 1); /*字体模式选择*/u8g2_SetFontDirection(u8g2, 0); /*字体方向选择*/u8g2_SetFont(u8g2, u8g2_font_inb24_mf); /*字库选择*/u8g2_DrawStr(u8g2, 0, 20, "U");u8g2_SetFontDirection(u8g2, 1);u8g2_SetFont(u8g2, u8g2_font_inb30_mn);u8g2_DrawStr(u8g2, 21,8,"8");u8g2_SetFontDirection(u8g2, 0);u8g2_SetFont(u8g2, u8g2_font_inb24_mf);u8g2_DrawStr(u8g2, 51,30,"g");u8g2_DrawStr(u8g2, 67,30,"\xb2");u8g2_DrawHLine(u8g2, 2, 35, 47);u8g2_DrawHLine(u8g2, 3, 36, 47);u8g2_DrawVLine(u8g2, 45, 32, 12);u8g2_DrawVLine(u8g2, 46, 33, 12);u8g2_SetFont(u8g2, u8g2_font_4x6_tr);u8g2_DrawStr(u8g2, 1,54,"github.com/olikraus/u8g2");
}

3.7 main函数调用

int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_USART1_UART_Init();MX_SPI1_Init();/* USER CODE BEGIN 2 */
u8g2_t u8g2; // 显示器初始化结构体MD_OLED_RST_Set(); //显示器复位拉高u8g2Init(&u8g2);   //显示器调用初始化函数/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

四、最终效果

在这里插入图片描述

五、工程下载

代码工程下载


文章是自己总结而记录,有些知识点没说明白的,请各位看官多多提意见,多多交流,欢迎大家留言
如果技术交流可以加以下群,方便沟通
QQ群:370278903
点击链接加入群聊【蜡笔小芯的嵌入式交流群】
![])

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

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

相关文章

庆余年2火了,却把热爱开源的程序员给坑了

庆余年 2 终于开播了,作为一名剧粉,苦等了五年终于盼来了。开播即爆火,虽然首播的几集剧情有些拖沓,不过也不影响这是一部好剧。 然而,庆余年 2 的爆火,却把 npmmirror 镜像站给坑惨了。npmmirror 镜像站&…

gem5模拟器入门(二)——创建一个简单的配置脚本

本章教程将引导您设置一个简单的 gem5 仿真脚本,并首次运行 gem5。假设您已经完成了gem5模拟器入门(一)——环境配置-CSDN博客,并成功构建了带有可执行文件 build/X86/gem5.opt 的 gem5。 配置脚本将模拟一个非常简单的系统&#…

LangChain实战 | 3分钟学会SequentialChain怎么传多个参数

SequentialChain参数传递,总结了以下四种类型 参数传递入参出参一 对 一11一 对 多1n多 对 一n1多 对 多nn 0.连接大模型 先选一个llm,参考这篇博客选择一个国内大模型 LangChain连接国内大模型测试|智谱ai、讯飞星火、通义千问 from langchain_comm…

网络侦察技术

网络侦察技术 收集的信息网络侦察步骤搜索引擎检索命令bing搜索引擎Baidu搜索引擎Shodan钟馗之眼(zoomeye) whois数据库:信息宝库查询注册资料 域名系统网络拓扑社交网络跨域拓展攻击 其它侦察手段社会工程学社会工程学常见形式Web网站查询 其它非技术侦察手段总结网…

巅峰对决:OpenAI与Google如何用大模型开创未来

2024年,人工智能领域正引领着一场波澜壮阔的全球技术革命。 5月14日,OpenAI揭开了其新一代多模态人工智能大模型GPT4系列的神秘面纱,其中GPT-4o不仅拥有流畅迷人的嗓音,还展现出幽默、机智和深刻的洞察力……紧接着,在…

linux下cp和mv命令显示进度条

1.查看当前系统下coreutils工具包的版本号: [rootk8s-master ~]# rpm -qa | grep -w coreutils coreutils-8.22-24.el7_9.2.x86_64当前版本为8.22。 因为cp 和 mv 命令由 coreutils 软件包提供,所以需要重新下载 coreutils 软件包配置补丁 2.下载core…

数据结构——顺序表基本操作的实现(初始化、取值、查找、插入)

一、线性表与顺序表的概述 线性表的数据元素的逻辑特征是线性的,是一种典型的线性结构。这样的结构可以借鉴数组,如数组a[10]中,a[1]前一定是a[0],a[1]后一定是a[2],首结点(a[0])前面无元素&am…

java医院管理系统源码(springboot+vue+mysql)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的医院管理系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 医院管理系统的主要使用者分…

VR法治教育展厅互动体验突破了地域限制

VR全景互动展厅搭建编辑器以其卓越的特点、强大的功能及实际应用中的显著优势,成为企业级VR应用的得力助手。这款软件不仅能够制作逼真的虚拟场景,更能让用户沉浸其中,体验前所未有的真实感。 它拥有高度逼真的视觉效果,采用先进的…

智能单款计划助力品牌利润增长

零售品牌若要在激烈的市场竞争中胜出,季中单款的管理无疑是商品生命周期管理的核心环节之一。而单款计划的制定,首先依赖于对爆款、平销及滞销产品的敏锐洞察。一个利润现象不得不引起我们的关注:爆款产品的销售,往往成为拉动品牌…

svix - webhooks

文章目录 一、关于 SvixClient Library Overview与 Svix 托管服务的区别 二、运行服务器1、部署1.1 Docker1) 使用 Docker Compose2) 独立容器 1.2 预编译的二进制文件1.3 从源代码构建 2、运行时依赖项3、Redis/Valkey 注意事项持久性 Eviction 政策4、服务器配置4.1 配置文件…

express.js--生成token(二)

主要作用是访问路由接口时,生成身份权限信息 下载依赖 npm i express-jwt npm i jsonwebtoken 配置管理 config/index.js module.exports {app: {port: process.PORT || 3000,//jwt密钥jwtSecret: jwtSecret,//token过期时间expiresIn: 60 * 60 * 24,} } con…

从零开始:如何集成美颜SDK和优化美颜接口

今天,小编将从零开始,详细讲解如何集成SDK并优化美颜接口。 一、选择合适的美颜SDK 评估SDK的功能 在评估过程中,可以通过阅读官方文档、查看示例代码以及实际测试来确定SDK是否符合需求。 兼容性和性能 确保其支持你开发的应用平台&…

Android15 Beta更新速览

Android15 Beta更新速览 前台服务变更 前台服务使应用保持活动状态,以便它们可以执行关键且对用户可见的操作,通常以牺牲电池寿命为代价。在 Android 15 Beta 2 中,dataSync 和 mediaProcessing 前台服务类型现在具有约 6 小时的超时时间&a…

内网安全--隧道技术-CS上线本地

免责声明:本文仅做技术交流与学习...请勿非法搞破坏... ---隧道技术:硬刚网络协议,(你不让我走我偏走!) 解决不出网协议上线的问题(利用出网协议进行封装出网) 代理协议: SOCKS4/5 代理软件: SocksCap Proxifier ProxyChains(…

磁盘管理以及文件系统08

1、为什么要对磁盘进行分区? 业务层面:为满足一定的需求所是做的特定操作。 2、硬盘是什么,以及硬盘的作用 硬盘:计算机的存储设备,一个或者多个带磁性的盘组成的,可以在盘片上进行数据的读写。硬盘的最…

LVGL圆弧、线条、图片、色环、按钮矩阵、文本区域、键盘部件

目录 LVGL圆弧部件 LVGL线条部件 LVGL图片部件 LVGL色环部件 LVGL按钮矩阵部件 LVGL文本区域部件 LVGL键盘部件 LVGL圆弧部件 圆弧部件以弧形滑动的形式来调节、显示某个参数的值。 圆弧部件组成部分: 背景弧(LV_PART_MAIN) 前景弧&am…

浏览器提示网站不安全怎么办?有什么解决办法吗?

当你在浏览器中访问一个网站时,如果看到提示说该网站不安全,这通常是由于网站没有使用SSL证书或者SSL证书存在问题。SSL证书在这里扮演着非常关键的角色,下面我会详细解释它的作用以及如何解决这类不安全提示。 SSL证书的作用: 1…

【CTF Web】CTFShow web11 Writeup(RCE+PHP+代码审计)

web11 1 阿呆听完自己菜死了&#xff0c;自己呆了。决定修好漏洞&#xff0c;绝对不能让自己再菜死了。 解法 可知 flag 在 config.php。 <?php # flag in config.php include("config.php"); if(isset($_GET[c])){$c $_GET[c];if(!preg_match("/system…

WorldSpace下的合批策略与ScreenSpace有什么区别

1&#xff09;WorldSpace下的合批策略与ScreenSpace有什么区别 2&#xff09;在iOS上用Metal取代OpenGL的多么 3&#xff09;在动画蓝图中将两个或多个动画同时融合到同一个网格 4&#xff09;Mipmap如何限定层级 这是第387篇UWA技术知识分享的推送&#xff0c;精选了UWA社区的…