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

news2024/12/25 23:46:43

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 ---- PB6
	  I2C1   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 0
  switch (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 seconds
		for (uint16_t n = 0; n < 320; n++)
		{
			__NOP();
		}
		break;
	case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
		HAL_Delay(1);
		break;
	case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
		// delay 5us
		delay_us(5); // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us

	case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin
		if (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 pin
	case 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 pin

	default:
		u8x8_SetGPIOResult(u8x8, 1); // default return value
		break;
	}
	return 1;
#elif 0
	switch (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 seconds
				for (uint16_t n = 0; n < 320; n++)
				{
					__NOP();
				}
				break;
		case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
				HAL_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.25us
		case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin
				break;                    // arg_int=1: Input dir with pullup high for I2C clock pin
		case U8X8_MSG_GPIO_I2C_DATA:  // arg_int=0: Output low at I2C data pin
				break;                    // arg_int=1: Input dir with pullup high for I2C data pin
		case 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 value
				break;
	}
	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

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

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

相关文章

《剑指Offer》笔记题解思路技巧优化 Java版本——新版leetcode_Part_3

《剑指Offer》笔记&题解&思路&技巧&优化_Part_3 &#x1f60d;&#x1f60d;&#x1f60d; 相知&#x1f64c;&#x1f64c;&#x1f64c; 相识&#x1f622;&#x1f622;&#x1f622; 开始刷题1. LCR 138. 有效数字——表示数值的字符串2. LCR 139. 训练计划…

【数据结构】17 二叉树的建立

二叉树的建立 由于树是非线性结构&#xff0c;创建一颗二叉树必须首先确定树中结点的输入顺序&#xff0c;常用方法是先序创建和层序创建。 层序创建所用的节点输入序列是按数的从上至下从左到右的顺序形成的各层的空结点输入数值0。在构造二叉树过程中需要一个队列暂时存储各…

AI数据中心网络架构需求:400/800G光模块

随着AI技术和相关应用的不断发展&#xff0c;大模型、大数据和AI计算能力在AI发展中的重要性日益凸显。大模型和数据集构成AI研究的软件基础&#xff0c;而AI算力是关键的基础设施。在本文中&#xff0c;我们将探讨AI发展对数据中心网络架构的影响。 Fat-Tree数据中心网络架构…

《白话C++》第10章 STL和boost,Page67~70 std::auto_ptr

std::auto_ptr可以不经意间转移裸指针控制权 std::auto_ptr持有裸指针的控制权&#xff0c;却可以随随便便看似不经意地转移给另一个auto_ptr: #include <iostream> #include <memory>using namespace std;struct S {int a;void SetA(int a){this->a a;}~S()…

跟着pink老师前端入门教程(JavaScript)-day02

三、变量 &#xff08;一&#xff09;变量概述 1、什么是变量 白话&#xff1a;变量就是一个装东西的盒子 通俗&#xff1a;变量是用于存放数据的容器&#xff0c;通过变量名获取数据&#xff0c;甚至数据可以修改 2、变量在内存中的存储 本质&#xff1a;变量是程序在内存…

记录:零基础小白初学云计算 第一天

一、认识【rootlocalhost ~】# root:当前登录用户的用户名 localhost&#xff1a;主机名 ~&#xff1a;当前用户的家目录 #&#xff1a;超级用户的命令提示符 基础命令 ifup ens33&#xff1a;启动网卡 ip a&#xff1a;查看IP地址 远程连接端口默认 &#xff1a;22 二…

WordPress主题YIA移动端文章页的面包屑不显示怎么办?

平时我们一般都会在文章页导航菜单下方显示面包屑&#xff0c;类似于“当前位置&#xff1a;boke112百科 WordPress 正文”。平时用浏览器调试站点的时候&#xff0c;在Edge浏览器的“切换设备仿真”中&#xff0c;不管是选择什么设备都会显示面包屑。具体如下图所示&#xf…

C#,整数转为短字符串(Short string)的加解密算法与源代码

1 整数转为短字符串的应用 网站生成的动态 URL 往往以内容序列号id为标识与参数&#xff0c;比如&#xff1a; http://www.jerry.com/tom.aspx?id1 使用 Web Rewrite&#xff0c;可以实现网页静态化&#xff0c;称为&#xff1a; http://www.jerry.com/content/1.html 对…

论文阅读-PIM-tree:一种面向内存处理的抗偏移索引

论文名称&#xff1a;PIM-tree: A Skew-resistant Index for Processing-in-Memory 摘要 当今的内存索引性能受到内存延迟/带宽瓶颈的限制。Processing-in-memory (PIM) 是一种新兴的方法&#xff0c;可能通过实现低延迟内存访问&#xff0c;其聚合内存带宽随 PIM 节点数量扩…

【Linux系统化学习】文件重定向

目录 文件内核对象 文件描述符的分配规则 重定向 重定向的概念 dup2系统调用 输出重定向 追加重定向 输入重定向 stderr解析 重定向到同一个文件中 分离常规输出和错输出 文件内核对象 上篇文章中我们介绍到了操作系统中的文件&#xff0c;操作系统为了方…

react使用Map方法遍历列表不显示的问题

问题&#xff1a; 在最开始搭建选项卡的时候&#xff0c;我的js代码是这样的 import React, { Component } from react import ./css/02-maizuo.css export default class App extends Component {state {list: [{id: 1,text: 电影},{id: 2,text: 影院}, {id: 3,text: 我的}…

MySQL DQL 基本查询

一.概念 数据查询不应只是简单返回数据库中存储的数据&#xff0c;还应该根据需要对数据进行筛选以及确定数据以什么样的格式显示。 二.语法格式 select 列名 from 表 where 条件 1.查询所有的商品 select * from product; 2.查询商品名和商品价格 select pname,price from…

Quantitative Analysis: PIM Chip Demands for LLAMA-7B inference

1 Architecture 如果将LLAMA-7B模型参数量化为4bit&#xff0c;则存储模型参数需要3.3GB。那么&#xff0c;至少PIM chip 的存储至少要4GB。 AiM单个bank为32MB&#xff0c;单个die 512MB&#xff0c;至少需要8个die的芯片。8个die集成在一个芯片上。 提供816bank级别的访存带…

Docker 第十四章 : Docker 三剑客之 Machine

第十四章 : Docker 三剑客之 Machine 本章知识点: Docker Machine 是 Docker 三剑客之一,它是一个工具,允许用户在本地或远程机器上创建 Docker 主机。它简化了 Docker 环境的设置,特别是在不同的操作系统和云平台上。通过 Docker Machine,用户可以轻松地在虚拟机或物理…

《白话C++》第9章 泛型,Page842~844 9.4.2 AutoPtr

源起&#xff1a; C编程中&#xff0c;最容易出的问题之一&#xff0c;就是内存泄露&#xff0c;而new一个对象&#xff0c;却忘了delete它&#xff0c;则是造成内存泄露的主要原因之一 例子一&#xff1a; void foo() {XXXObject* xo new XXXObject;if(!xo->DoSomethin…

支付交易——跨境交易

摘要 老王兢兢业业经营生意多年&#xff0c;一步步从小杂货店做到现在&#xff0c;成立大型贸易公司。在做大做强的过程中&#xff0c;老王觉得国内市场已经饱和&#xff0c;竞争处处是红海。老王留意海外很多年了&#xff0c;决定走出去&#xff0c;转向海外:将国外的商品引进…

蓝桥杯官网填空题(寻找整数)

问题描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 有一个不超过 10^17 的正整数 n&#xff0c;知道这个数除以 2 至 49 后的余数如下表所示&#xff0c;求这个正整数最小是多少。 运行限制 最大运行时间&#xff1a;…

C/C++重点解析——内存管理

1. C/C内存分布 我们先来看一段代码和其相关问题&#xff1a; int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3, 4 };char char2[] "abcd";const char* pChar3 "abcd"…

4 月 9 日至 4 月 10 日,Hack.Summit() 2024 首聚香江

Hack.Summit() 是一系列 Web3 开发者大会。2024 年的活动将于 2024 年 4 月 9 日至 4 月 10 日在香港数码港举行。自十年前首次举办以来&#xff0c;此次会议标志着 Hack.Summit() 首次在亚洲举办&#xff0c;香港被选为首次亚洲主办城市&#xff0c;这对 Hack VC 和该地区都具…

【大厂AI课学习笔记】【2.1 人工智能项目开发规划与目标】(4)数据准备的流程

今天学习的是数据准备的流程。 我们已经知道&#xff0c;数据准备占了AI项目超过一半甚至79%的时间。 那么数据准备&#xff0c;都做些什么&#xff0c;有哪些流程。 1.数据采集 观测数据人工收集调查问卷线上数据库 2.数据清洗 有缺失的数据有重复的数据有内容错误的数据…