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 ---- 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

无人驾驶LQR控制算法 c++ 实现

参考博客&#xff1a; &#xff08;1&#xff09;LQR的理解与运用 第一期——理解篇 &#xff08;2&#xff09;线性二次型调节器(LQR)原理详解 &#xff08;3&#xff09;LQR控制基本原理&#xff08;包括Riccati方程具体推导过程&#xff09; &#xff08;4&#xff09;【基础…

精品jsp+ssm鲜花销售管理系统-购物商城

《[含文档PPT源码等]精品jspssm鲜花销售管理系统[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 使用技术&#xff1a; 开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&#x…

微信小程序如何配置服务器域名

目录 一、微信小程序 二、域名 三、服务器 四、如何配置服务器域名 一、微信小程序 微信小程序是一种轻量级的应用程序&#xff0c;用户无需下载安装即可使用&#xff0c;具有便捷、快捷的特点。微信小程序可以在微信内直接使用&#xff0c;无需离开微信即可完成各种功能&…

Leetcode - 周赛384

目录 一&#xff0c;3033. 修改矩阵 二&#xff0c;3035. 回文字符串的最大数量 三&#xff0c;3036. 匹配模式数组的子数组数目 II 一&#xff0c;3033. 修改矩阵 这道题直接暴力求解&#xff0c;先算出每一列的最大值&#xff0c;再将所有为-1的区域替换成该列的最大值&am…

人工智能学习与实训笔记(七):神经网络之推荐系统处理

九、模型压缩与知识蒸馏 出于对响应速度&#xff0c;存储大小和能耗的考虑&#xff0c;往往需要对大模型进行压缩。 模型压缩方法主要可以分为以下四类&#xff1a; 参数修剪和量化&#xff08;Parameter pruning and quantization&#xff09;&#xff1a;用于消除对模型表…

Java 学习和实践笔记(12)

这个就比较有意思了&#xff01;所有的事情&#xff0c;拆分完之后&#xff0c;都有且只有这三种状态流程&#xff01; //TIP To <b>Run</b> code, press <shortcut actionId"Run"/> or // click the <icon src"AllIcons.Actions.Execute&…

Vue源码系列讲解——模板编译篇【二】(整体运行流程)

目录 1. 整体流程 2. 回到源码 3. 总结 1. 整体流程 上篇文章中我们说了&#xff0c;在模板解析阶段主要做的工作是把用户在<template></template>标签内写的模板使用正则等方式解析成抽象语法树&#xff08;AST&#xff09;。而这一阶段在源码中对应解析器&…

《区块链公链数据分析简易速速上手小册》第7章:数据获取和分析的挑战(2024 最新版)

文章目录 7.1 数据准确性和完整性验证7.1.1 基础知识7.1.2 重点案例&#xff1a;验证加密货币交易数据准备工作实现步骤步骤1: 从 API 获取比特币交易数据步骤2: 数据转换和初步校验步骤3: 验证交易数据的格式和范围 结论 7.1.3 拓展案例 1&#xff1a;使用哈希校验数据完整性准…

NLP_Transformer架构

文章目录 Transformer架构剖析编码器-解码器架构各种注意力的应用Transformer中的自注意力Transformer中的多头自注意力Transformer中的编码器-解码器注意力Transformer中的注意力掩码和因果注意力 编码器的输入和位置编码编码器的内部结构编码器的输出和编码器-解码器的连接解…

NBA2K24 精品蔡徐坤面补

NBA2K24 精品蔡徐坤面补 NBA2K23-NBA2K24通用 精品蔡徐坤面补 下载地址&#xff1a; https://www.changyouzuhao.cn/13072.html

BUGKU-WEB eval

题目描述 题目截图如下&#xff1a; 进入场景看看&#xff1a; <?phpinclude "flag.php";$a $_REQUEST[hello];eval( "var_dump($a);");show_source(__FILE__); ?>解题思路 PHP代码审计咯 相关工具 百度搜索PHP相关知识 解题步骤 分析脚…

C++数据结构与算法——栈与队列

C第二阶段——数据结构和算法&#xff0c;之前学过一点点数据结构&#xff0c;当时是基于Python来学习的&#xff0c;现在基于C查漏补缺&#xff0c;尤其是树的部分。这一部分计划一个月&#xff0c;主要利用代码随想录来学习&#xff0c;刷题使用力扣网站&#xff0c;不定时更…

java+SSM+mysql 开放式实验管理系统78512-计算机毕业设计项目选题推荐(免费领源码)

摘 要 我国高校开放式实验管理普遍存在实验设备使用率较低、管理制度不完善,实验设备共享程度不高等诸多问题。要在更大范围推行开放式实验管理,就必须在开放式实验教学管理流程中,通过引入信息化管理加大信息技术在其中的应用,才能真正发挥这种教学模式的开放性优势。 本系统…

C#,二进制数的非0位数统计(Bits Count)的算法与源代码

计算一个十进制数的二进制表示有多少位1&#xff1f; 1 遍历法&#xff08;递归或非递归&#xff09; 使用循环按位统计1的个数。 2 哈希查表法 利用一个数组或哈希生成一张表&#xff0c;存储不同二进制编码对应的值为1的二进制位数&#xff0c;那么在使用时&#xff0c;只…

MIT-BEVFusion系列八--onnx导出2 spconv network网络导出

这里写目录标题 export-scn.py加载模型设置每层的精度属性初始化输入参数导出模型model.encoder_layers 设置初始化参数设置 indice_key 属性更改 lidar backbone 的 forward更改lidar网络内各个层的forward带参数装饰器&#xff0c;钩子函数代码使用装饰器修改forward举例 跟踪…

GPU芯片逆势扩张,NVIDIA成为2023年全球芯片的唯一赢家

市调机构Gartner发布数据指出2023年全球诸多芯片行业都在下滑&#xff0c;唯一取得增长的仅有GPU/AI芯片&#xff0c;GPU芯片的市场规模增加了一倍&#xff0c;而领头羊NVIDIA无疑成为最大的赢家。 从2022年下半年以来&#xff0c;全球芯片行业就已步入供给过剩的阶段&#xff…

HarmonyOS—状态管理概述

在前文的描述中&#xff0c;我们构建的页面多为静态界面。如果希望构建一个动态的、有交互的界面&#xff0c;就需要引入“状态”的概念。 图1 效果图 上面的示例中&#xff0c;用户与应用程序的交互触发了文本状态变更&#xff0c;状态变更引起了UI渲染&#xff0c;UI从“He…

C++中对象的构造与析构顺序

一、对象的构造顺序 对象的构造&#xff0c;先被创建的对象&#xff0c;先被构造&#xff0c;先调用其构造函数 class A { private:int _a 0; public://构造函数A(int a 0){_a a;cout << "A(int a 0)" << " " << _a << endl…

【计算机网络】网际协议——互联网中的转发和编址

编址和转发是IP协议的重要组件 就像这个图所示&#xff0c;网络层有三个主要组件&#xff1a;IP协议&#xff0c;ICMP协议&#xff0c;路由选择协议IPV4 没有选项的时候是20字节 版本&#xff08;号&#xff09;&#xff1a;4比特&#xff1a;规定了IP协议是4还是6首部长度&am…

【Redis】Redis

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录 Nosql为什么使用Nosql什么是NosqlNosql特点 Redis入门windows安装Linux安装 Nosql 为什么使用N…