当前位置: 首页 > news >正文

HAL/LL/STD STM32 U8g2库 +I2C SSD1306/sh1106 WouoUI磁贴案例

HAL/LL/STD STM32 U8g2库 +I2C SSD1306/sh1106 WouoUI磁贴案例


  • 📍基于STM32F103C8T6 LL库驱动版本:https://gitee.com/chcsx/platform-test/tree/master/MDK-ARM
  • 🎬视频演示:

WouoUI移植磁贴案例,新增确认弹窗


  • 📍基于标准库驱动,STM32F103RCT6移植u8g2 硬件i2c WouoUI磁贴:https://gitee.com/henrycrh/stm32-f103-rct6_-wouo-ui/tree/master/STM32F10x_FWlib/src
  • 🎬视频演示:

[开源]STM32F103RCT6移植u8g2 > 硬件i2c > WouoUI移植

  • 🔖使用LL库和STD标准库的可以参照上面的例程测试。这里不多种说明。

✅功能部分说明

  • 🌿显示部分:U8g2库驱动
  • 🌿按键:采用Multi-button库驱动

  • 🎞SH1106驱动显示效果:
    在这里插入图片描述
  • 📺I2C SSD1306 0.96"屏幕显示效果:
    在这里插入图片描述
HAL库程序是基于上面的LL库移植过来的,采用的是STM32F103VET6。保留了按键控制功能,去掉了其他没有的外设。
  • 🔖AC6编译器,优化等级默认Level 1 (o1)
    在这里插入图片描述

  • 🔖AC5编译器,优化等级至少要设置Level 1 (o1),否则会报L6406E错误。
    在这里插入图片描述

  • 🌿屏蔽相关报警信息

--diag_suppress=1,111,223,1295
  • 🌿测试使用1.3“SH1106屏幕显示正常,0.96" ssd1306屏幕会闪屏。
  • 📚移植的HAL库程序:
链接:https://pan.baidu.com/s/1Oh3ysdU8-1X0I_JJVVemkg?pwd=slro 
提取码:slro

📄HAL库程序引脚说明

STM32F103VET6
按键控制
PE8 上翻页
PE7 下翻页
PB1  确认/长按返回
===================I2C1   SCL ---- PB6I2C1   SDA ---- PB7

🔨HAL库程序SSD1306/sh1106屏幕选择与代码调整

  • ✨在oled.c中,OLED初始化OLED_Init(void)函数。(sh1106屏幕刷SSD1306程序也可以显示,只是边框有一部分是马赛克雪花)
//*****************************   使用下面2个u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, stm32_gpio_and_delay); //1.3" sh1106 使用这个
// u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, stm32_gpio_and_delay); //0.96"SSD1306使用这个
//******************************  使用上面2个

🌼U8g2库移植说明

  • 🌿可以借用上面的LL库的工程,直接拷贝对应的驱动文件夹到自己所创建的工程目录下。
  • 🌿其他屏幕型号,需要提前准备一个能驱动显示的工程作为模板。
  • 🌿将以下3个核心函数,拷贝到能显示的模板工程中,根据驱动屏幕型号进行调整:
uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);//硬件I2C
uint8_t 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);
void OLED_Init(void);
uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)//硬件I2C
{/* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */static uint8_t buffer[128];static uint8_t buf_idx;uint8_t *data;switch (msg){case U8X8_MSG_BYTE_INIT:{/* add your custom code to init i2c subsystem */MX_I2C1_Init(); //I2C初始化}break;case U8X8_MSG_BYTE_START_TRANSFER:{buf_idx = 0;}break;case U8X8_MSG_BYTE_SEND:{data = (uint8_t *)arg_ptr;while (arg_int > 0){buffer[buf_idx++] = *data;data++;arg_int--;}}break;case U8X8_MSG_BYTE_END_TRANSFER:{int ret = HAL_I2C_Master_Transmit(&hi2c1, (OLED_ADDRESS), buffer, buf_idx, 1000);if (ret != HAL_OK){return 0;}}break;case U8X8_MSG_BYTE_SET_DC:break;default:return 0;}return 1;
}uint8_t 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)
{
#if 0switch (msg){
//  case U8X8_MSG_GPIO_AND_DELAY_INIT:
//       oled_init();                    
//  break;case U8X8_MSG_GPIO_SPI_DATA:if(arg_int)OLED_SDIN_Set();else OLED_SDIN_Clr();break;case U8X8_MSG_GPIO_SPI_CLOCK:if(arg_int)OLED_SCLK_Set();else OLED_SCLK_Clr();break;        case U8X8_MSG_GPIO_CS://CS????case U8X8_MSG_GPIO_DC:if(arg_int)OLED_DC_Set();else OLED_DC_Clr();break;case U8X8_MSG_GPIO_RESET:if(arg_int)OLED_RST_Set();else OLED_RST_Clr();break;//Function which delays 100ns  case U8X8_MSG_DELAY_100NANO:  __NOP();  break;  case U8X8_MSG_DELAY_MILLI:HAL_Delay(arg_int);break;default:return 0;//A message was received which is not implemented, return 0 to indicate an error}return 1;
#elif 0// printf("%s:msg = %d,arg_int = %d\r\n",__FUNCTION__,msg,arg_int);switch (msg){//		case U8X8_MSG_GPIO_AND_DELAY_INIT://				oled_init();//		break;case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds__NOP();break;case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro secondsfor (uint16_t n = 0; n < 320; n++){__NOP();}break;case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli secondHAL_Delay(1);break;case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz// delay 5usdelay_us(5); // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25uscase U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pinif (arg_int == 1){LL_GPIO_SetOutputPin(LCD_SCL_GPIO_Port, LCD_SCL_Pin);//        HAL_GPIO_WritePin(GPIOB, SCL2_Pin, GPIO_PIN_SET);}else if (arg_int == 0){LL_GPIO_ResetOutputPin(LCD_SCL_GPIO_Port, LCD_SCL_Pin);//        HAL_GPIO_WritePin(GPIOB, SCL2_Pin, GPIO_PIN_RESET);}break;					 // arg_int=1: Input dir with pullup high for I2C clock pincase U8X8_MSG_GPIO_I2C_DATA: // arg_int=0: Output low at I2C data pin//  printf("U8X8_MSG_GPIO_I2C_DATA:%d\r\n",arg_int);if (arg_int == 1){LL_GPIO_SetOutputPin(LCD_SDA_GPIO_Port, LCD_SDA_Pin);//        HAL_GPIO_WritePin(GPIOB, SDA2_Pin, GPIO_PIN_SET);}else if (arg_int == 0){LL_GPIO_ResetOutputPin(LCD_SDA_GPIO_Port, LCD_SDA_Pin);//        HAL_GPIO_WritePin(GPIOB, SDA2_Pin, GPIO_PIN_RESET);}break; // arg_int=1: Input dir with pullup high for I2C data pindefault:u8x8_SetGPIOResult(u8x8, 1); // default return valuebreak;}return 1;
#elif 0switch (msg){case U8X8_MSG_GPIO_AND_DELAY_INIT:break;case U8X8_MSG_DELAY_MILLI:HAL_Delay(arg_int);break;case U8X8_MSG_GPIO_I2C_CLOCK:break;case U8X8_MSG_GPIO_I2C_DATA:break;default:return 0;}return 1; // command processed successfully.
#elif 1	switch (msg){case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds__NOP();break;case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro secondsfor (uint16_t n = 0; n < 320; n++){__NOP();}break;case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli secondHAL_Delay(1);break;case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
//				delay_us(5);for (uint16_t n = 0; n < 160; n++){__NOP();}break;                    // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25uscase U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pinbreak;                    // arg_int=1: Input dir with pullup high for I2C clock pincase U8X8_MSG_GPIO_I2C_DATA:  // arg_int=0: Output low at I2C data pinbreak;                    // arg_int=1: Input dir with pullup high for I2C data pincase U8X8_MSG_GPIO_MENU_SELECT:u8x8_SetGPIOResult(u8x8, /* get menu select pin state */ 0);break;case U8X8_MSG_GPIO_MENU_NEXT:u8x8_SetGPIOResult(u8x8, /* get menu next pin state */ 0);break;case U8X8_MSG_GPIO_MENU_PREV:u8x8_SetGPIOResult(u8x8, /* get menu prev pin state */ 0);break;case U8X8_MSG_GPIO_MENU_HOME:u8x8_SetGPIOResult(u8x8, /* get menu home pin state */ 0);break;default:u8x8_SetGPIOResult(u8x8, 1); // default return valuebreak;}return 1;
}
#endif/*** @brief	OLED初始化
*/			    
void OLED_Init(void)
{ 	//	u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_4wire_sw_spi, stm32_gpio_and_delay);//	u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c, stm32_gpio_and_delay);u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, stm32_gpio_and_delay);u8g2_InitDisplay(&u8g2);u8g2_SetPowerSave(&u8g2, 0);
}

📚HAL库U8g2单独驱动程序SSD1306/sh1106屏幕

  • 🌿SSD1306/sh1106屏幕选择
//    u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8x8_stm32_gpio_and_delay); //1.3" sh1106 使用这个u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8x8_stm32_gpio_and_delay);//0.96"SSD1306使用这个
链接:https://pan.baidu.com/s/1_hQ1Op00aBoBkjhudml9pw?pwd=6z3u 
提取码:6z3u

相关文章:

HAL/LL/STD STM32 U8g2库 +I2C SSD1306/sh1106 WouoUI磁贴案例

HAL/LL/STD STM32 U8g2库 I2C SSD1306/sh1106 WouoUI磁贴案例 &#x1f4cd;基于STM32F103C8T6 LL库驱动版本&#xff1a;https://gitee.com/chcsx/platform-test/tree/master/MDK-ARM&#x1f3ac;视频演示&#xff1a; WouoUI移植磁贴案例&#xff0c;新增确认弹窗 &#x1f…...

手机如何改自己的ip地址

在现如今的数码时代&#xff0c;手机已经成为人们生活中不可或缺的一部分。然而&#xff0c;有时候我们可能需要改变手机的IP地址来实现一些特定的需求。本文将向大家介绍如何改变手机的IP地址&#xff0c;帮助大家更好地应对各种网络问题。 更改手机IP地址的原因&#xff1a;…...

ajax函数库axios基本使用

ajax函数库Axios基本使用 简介&#xff1a;Axios 对原生的Ajax进行了封装&#xff0c;简化书写&#xff0c;快速开发。 官网&#xff1a;https://www.axios-http.cn/ Axios使用步骤 引入Axios的js文件(参考官网)使用Axios发送请求,获取相应结果 <script src"https:…...

【nginx实践连载-4】彻底卸载Nginx(Ubuntu)

步骤1&#xff1a;停止Nginx服务 打开终端&#xff08;Terminal&#xff09;。停止Nginx服务&#xff1a;sudo systemctl stop nginx步骤2&#xff1a;卸载Nginx软件包 运行以下命令卸载Nginx软件包&#xff1a;sudo apt purge nginx nginx-common nginx-core步骤3&#xff1…...

究极小白如何自己搭建一个自动发卡网站-独角数卡

首页 | 十画IOSID​shihuaid.cn/​编辑 如果你也是跟我一样,什么都不懂,也想要搭建一个自己的自动发卡网站,可以参考一下我的步骤,不难,主要就是细心,一步步来一定成功!! 独角数卡: 举个例子:独角数卡就是一个店面,而且里面帮你装修好了,而你要做的就是把开店之…...

Java_方法(重载方法签名等详解)

在之前我们学习C语言时&#xff0c;当我们想要重复使用某段代码的功能时&#xff0c;我们会将这段代码定义为一个函数&#xff0c;而在java中我们把这段重复使用的代码叫做方法。 方法的定义 类体的内容分为变量的声明和方法的定义&#xff0c;方法的定义包括两部分&#xff1…...

VQ35 评论替换和去除(char_length()和replace函数的使用)

代码 select id ,replace(comment,&#xff0c;,) as comment from comment_detail where char_length(comment)>3知识点 要注意替换的是中文逗号 由于题目说的是汉字长度大于3&#xff0c;所以这里就要使用char_length()而不是length() char_length()&#xff1a;单位为字…...

【MySQL】学习多表查询和笛卡尔积

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-N8PeTKG6uLu4bJuM {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…...

RabbitMQ实现延迟消息的方式-死信队列、延迟队列和惰性队列

当一条消息因为一些原因无法被成功消费&#xff0c;那么这这条消息就叫做死信&#xff0c;如果包含死信的队列配置了dead-letter-exchange属性指定了一个交换机&#xff0c;队列中的死信都会投递到这个交换机内&#xff0c;这个交换机就叫死信交换机&#xff0c;死信交换机再绑…...

【运维测试】测试理论+工具总结笔记第1篇:测试理论的主要内容(已分享,附代码)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论测试理论测试工具相关知识。Python测试理论的主要内容&#xff0c;掌握软件测试的基本流程&#xff0c;知道软件测试的V和W模型的优缺点&#xff0c;掌握测试用例设计的要素&#xff0c;掌握等价类划分法、边界值法、因…...

【C语言】实现队列

目录 &#xff08;一&#xff09;队列 &#xff08;二&#xff09;头文件 &#xff08;三&#xff09; 功能实现 &#xff08;1&#xff09;初始化 &#xff08;2&#xff09; 销毁队列 &#xff08;3&#xff09; 入队 &#xff08;4&#xff09;出队 &#xff08;5&a…...

【友塔笔试面试复盘】八边形取反问题

问题&#xff1a;一个八边形每条边都是0&#xff0c;现在有取反操作&#xff0c;选择一条边取反会同时把当前边和2个邻边取反&#xff08;如果是0变为1&#xff0c;如果是1变为0&#xff09; 现在问你怎么取反能使得八条边都变为1. 当时陷入了暴力递归漩涡&#xff0c;给出一个…...

GB 18585-2023 壁纸中有害物质限量

壁纸/墙布因其色彩多样&#xff0c;图案丰富&#xff0c;施工方便&#xff0c;价格便宜等多种优势&#xff0c;广泛应用于室内装修材料&#xff0c;在国内&#xff0c;日本&#xff0c;欧美等地区非常普及。 GB 18585-2023壁纸中有害物质限量测试项目&#xff1a; 测试项目 测…...

全面的ASP.NET Core Blazor简介和快速入门

前言 因为咱们的MongoDB入门到实战教程Web端准备使用Blazor来作为前端展示UI&#xff0c;本篇文章主要是介绍Blazor是一个怎样的Web UI框架&#xff0c;其优势和特点在哪&#xff1f;并带你快速入门上手ASP.NET Core Blazor(当然这个前提是你要有一定的C#编程基础的情况&#x…...

HGAME 2024 WEEK2 Crypto WP

前言 我很菜&#xff0c;有没做出来的题目&#xff0c;带*号题为复现。 midRSA 题目&#xff1a; from Crypto.Util.number import * from secret import flagdef padding(flag):return flagb\xff*(64-len(flag))flagpadding(flag) mbytes_to_long(flag) pgetPrime(512) qg…...

Postman轻松签名,让SHA256withRSA保驾护航!

前言 在接口测试中&#xff0c;我们经常需要对请求进行签名&#xff0c;以保证数据的安全性。而SHA256withRSA是一种较为常见的签名算法&#xff0c;它可以使用私钥对数据进行签名&#xff0c;使用公钥进行验签。 但是&#xff0c;实现该算法签名可能会涉及到一些繁琐的操作&…...

C#面:简述装箱和拆箱

在C#中&#xff0c;装箱&#xff08;boxing&#xff09;和拆箱&#xff08;unboxing&#xff09;是用于在值类型和引用类型之间进行转换的过程。 装箱&#xff1a;&#xff08;Boxing&#xff09; 是将值类型转换为引用类型的过程。 将一个值类型赋值给一个对象类型时&#x…...

【Kubernetes in Action笔记】1.快速开始

在Kubernetes上运行一个程序 基础运行环境 当前的运行环境为使用虚拟机构建的单master集群。 [rootk8s-master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master Ready control-plane 109d v1.27.1 k8s-node1 Ready …...

踩坑实录(Fourth Day)

今天开工了&#xff0c;其实还沉浸在过年放假的喜悦中……今天在自己写 Vue3 的项目&#xff0c;虽说是跟着 B 站在敲&#xff0c;但是依旧是踩了一些个坑&#xff0c;就离谱……照着敲都能踩到坑&#xff0c;我也是醉了…… 此为第四篇&#xff08;2024 年 02 月 18 日&#x…...

【python】网络爬虫与信息提取--requests库

导学 当一个软件想获得数据&#xff0c;那么我们只有把网站当成api就可以 requests库:自动爬取HTML页面&#xff0c;自动网络请求提交 robots协议&#xff1a;网络爬虫排除标准&#xff08;网络爬虫的规则&#xff09; beautiful soup库&#xff1a;解析HTML页面 工具&…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...