一、I2C协议概述
I2C(Inter-Integrated Circuit)是一种串行通信协议,用于连接微控制器和外部设备。它由两根线组成:SCL(时钟线)和SDA(数据线)。其中,SCL由主设备控制,用于同步数据传输;SDA用于在时钟信号的控制下传输数据。
I2C通信过程
-
起始条件(Start Condition):数据传输开始前,主设备发送一个起始信号,即SCL为高电平时,SDA由高变低。
-
地址传输:主设备发送从设备地址和读/写位,选择通信的从设备。
-
数据传输:按照时钟信号,主设备和从设备通过SDA线传输数据。
-
停止条件(Stop Condition):数据传输结束后,主设备发送一个停止信号,即SCL为高电平时,SDA由低变高。
二、OLED屏的工作原理
OLED(Organic Light-Emitting Diode)屏幕的工作原理,包括:
- OLED屏幕的构成和特点
- OLED显示原理和驱动方式
- OLED屏幕与传统显示屏的区别和优势
通过深入了解OLED屏幕的工作原理,可以更好地理解其在显示技术中的应用和优势。
汉字点阵显示原理
汉字点阵显示的原理,包括:
- 汉字点阵的构成和编码方式
- 汉字显示的像素点阵排列规则
- 如何通过点阵显示汉字并实现清晰的显示效果
三、U8g2库概述
U8g2库是一款适用于嵌入式系统的通用图形库,支持多种显示设备和控制器,具有以下特点:
- 提供丰富的图形显示功能,包括文字显示、图形绘制、位图显示等;
- 支持多种显示设备类型,如LCD、OLED等,以及多种控制器,如SSD1306、ST7920等;
- 轻量级且易于移植,适用于各种嵌入式平台。
U8g2库特性
U8g2库具有以下特性,使其成为嵌入式系统中常用的图形库之一:
- 支持多种字体和字形,可实现丰富的文字显示效果;
- 提供多种图形绘制函数,如直线、矩形、圆形等,方便绘制各种图形;
- 支持位图显示和图像处理,可实现复杂的图像显示效果;
- 提供简洁而灵活的API接口,易于学习和使用。
U8g2库在STM32上的应用
U8g2库在STM32等嵌入式平台上广泛应用,通过简单的移植和配置,可以实现图形界面的快速开发,包括:
- 在OLED屏幕上显示图形界面和文字信息;
- 实现简单的用户交互功能,如按钮、菜单等;
- 结合传感器数据显示实时监控信息等应用场景。
四、CubexMX配置
u8g2图形库压缩包:
链接:https://pan.quark.cn/s/59ef99a72f84
提取码:jZzg
五、代码实现
(1)stm32_u8g2.h文件
#ifndef __STM32_U8G2_H
#define __STM32_U8G2_H
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "u8g2.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#define u8 unsigned char // ?unsigned char ????
#define MAX_LEN 128 //
#define OLED_ADDRESS 0x78 // oled
#define OLED_CMD 0x00 //
#define OLED_DATA 0x40 //
/* USER CODE BEGIN Prototypes */
uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
void u8g2Init(u8g2_t *u8g2);
void draw(u8g2_t *u8g2);
void testDrawPixelToFillScreen(u8g2_t *u8g2);
#endif
(2)stm32_u8g2.c文件
#include "stm32_u8g2.h"
#include "tim.h"
#include "i2c.h"
uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* 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_I2C2_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:
{
if (HAL_I2C_Master_Transmit(&hi2c2, OLED_ADDRESS, buffer, buf_idx, 1000) != HAL_OK)
return 0;
}
break;
case U8X8_MSG_BYTE_SET_DC:
break;
default:
return 0;
}
return 1;
}
uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch (msg)
{
case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 na