上一期我们介绍了如何使用GPIO翻转模拟软件I2C实现OLED屏幕的显示,本期我们介绍如何利用STM32中的硬件I2C来提高我们的传输效率以及字符串显示。
首先我们需要在CubeMX中开启我们对应的I2C设备。

//#define USE_SOFEWARE_I2C #define USE_HADEWARE_I2C
我们用宏定义来区分我们的I2C驱动是选用软件I2C还是硬件I2C。
uint8_t MY_IIC_WriteCommand(uint8_t Address,uint8_t Command,uint8_t Data)
{
#ifdef USE_SOFEWARE_I2C
MY_IIC_START();//I2C开始
MY_IIC_Write(Address);//发送设备地址
if(!MY_IIC_WaitACK())//如果没有响应
{
return 0;//返回失败
}
MY_IIC_Write(Command);//发送命令
if(!MY_IIC_WaitACK())//如果没有响应
{
return 0;//返回失败
}
MY_IIC_Write(Data);//发送数据
if(!MY_IIC_WaitACK())//如果没有响应
{
return 0;//返回失败
}
MY_IIC_STOP();//停止通信
#endif
#ifdef USE_HADEWARE_I2C
HAL_I2C_Mem_Write(&hi2c2,OLED_ADDRESS,Command,I2C_MEMADD_SIZE_8BIT,&Data,1,100);
#endif
}
在上一期的基础上,我们让软件I2C和硬件I2C的运行根据宏定义来区分。
在硬件I2C的定义中,我们只需要添加I2C的传输函数
#ifdef USE_HADEWARE_I2C HAL_I2C_Mem_Write(&hi2c2,OLED_ADDRESS,Command,I2C_MEMADD_SIZE_8BIT,&Data,1,100); #endif
本来按理来说是要使用HAL_I2C_Master_Transmit这个函数的,因为这个函数更像是主机到设备的传输函数,不过之所以使用HAL_I2C_Mem_Write这个函数,因为它的参数结构:硬件I2C句柄,设备地址,寄存器地址,数据宽度,数据缓存区,数据长度,超时时间。
这个结构更像是三段式发命令,所以我比较喜欢这个,用前者的话需要把命令和数据两个值合并,比较啰嗦。
..................
..................
然后就没了,硬件I2C就是如此简单。
接下来我们聊一聊OLED显示字符是如何实现的。在OLED中显示字符,我们需要先将屏幕分块,我们知道屏幕总共分为128*64的像素点, 我们将一块区域块作为每个字符的显示,例如我们选择8*6的区域作为每个字符块。(取模软件默认,可以自己设置)
我们可以利用字库取模软件来生成字库信息。

取模方式修改为纵向取模,获得我们的十六进制数据。并且创建一个文件来存放这些数据。(这里偷个懒用现成的字库,为了防止观感,直接放到最后去了)
// 在OLED.H中 void OLED_ShowChar(uint8_t x, uint8_t y, char chr); void OLED_ShowString(uint8_t x, uint8_t y, const char *str);
接着我们在OLED.H文件中添加显示字符和字符串的函数。
// 显示单个字符
void OLED_ShowChar(uint8_t x, uint8_t y, char chr)
{
uint8_t i;
// 检查坐标是否有效
if(x > 127 || y > 63) return;
// 计算字符在字库中的索引(支持ASCII码从0x20到0x7F)
if(chr < 0x20 || chr > 0x7F) return;
uint8_t char_index = chr - 0x20; // 0x20是空格的ASCII码
// 计算显示的页地址
uint8_t page = y / 8;
uint8_t y_offset = y % 8;
// 设置显示位置
MY_IIC_WriteCommand(OLED_ADDRESS, OLED_CMD, OLED_SET_PAGE_ADDR | page);
MY_IIC_WriteCommand(OLED_ADDRESS, OLED_CMD, OLED_SET_COL_LOW | (x & 0x0F));
MY_IIC_WriteCommand(OLED_ADDRESS, OLED_CMD, OLED_SET_COL_HIGH | (x >> 4));
// 写入6列数据
for(i = 0; i < 6; i++) {
uint8_t data = F6x8[char_index][i];
MY_IIC_WriteCommand(OLED_ADDRESS, OLED_DATA, data);
}
// 如果字符跨页显示
if(y_offset != 0 && page < 7) {
MY_IIC_WriteCommand(OLED_ADDRESS, OLED_CMD, OLED_SET_PAGE_ADDR | (page + 1));
MY_IIC_WriteCommand(OLED_ADDRESS, OLED_CMD, OLED_SET_COL_LOW | (x & 0x0F));
MY_IIC_WriteCommand(OLED_ADDRESS, OLED_CMD, OLED_SET_COL_HIGH | (x >> 4));
// 写入第二页的数据
for(i = 0; i < 6; i++) {
uint8_t data = F6x8[char_index][i] >> (8 - y_offset);
MY_IIC_WriteCommand(OLED_ADDRESS, OLED_DATA, data);
}
}
}
// 显示字符串
void OLED_ShowString(uint8_t x, uint8_t y, const char *str)
{
uint8_t x_pos = x;
while(*str != '\0') {
// 检查是否超出显示范围
if(x_pos > 122) break; // 留出6像素的宽度
// 显示当前字符
OLED_ShowChar(x_pos, y, *str);
// 移动到下一个字符位置
x_pos += 6; // 每个字符宽度为6像素
str++;
}
}
我们先完成字符填充函数,在字符填充函数的基础上增加字符串显示函数。
编写测试函数。

下期我们介绍如何利用硬件I2C配合DMA大幅度提高刷新效率
字库函数如下:
#ifndef __FRONT_H__
#include "OLED.h"
const unsigned char F6x8[][6] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp
0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// !
0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// "
0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14,// #
0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12,// $
0x00, 0x62, 0x64, 0x08, 0x13, 0x23,// %
0x00, 0x36, 0x49, 0x55, 0x22, 0x50,// &
0x00, 0x00, 0x05, 0x03, 0x00, 0x00,// '
0x00, 0x00, 0x1c, 0x22, 0x41, 0x00,// (
0x00, 0x00, 0x41, 0x22, 0x1c, 0x00,// )
0x00, 0x14, 0x08, 0x3E, 0x08, 0x14,// *
0x00, 0x08, 0x08, 0x3E, 0x08, 0x08,// +
0x00, 0x00, 0x00, 0xA0, 0x60, 0x00,// ,
0x00, 0x08, 0x08, 0x08, 0x08, 0x08,// -
0x00, 0x00, 0x60, 0x60, 0x00, 0x00,// .
0x00, 0x20, 0x10, 0x08, 0x04, 0x02,// /
0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
0x00, 0x00, 0x42, 0x7F, 0x40, 0x00,// 1
0x00, 0x42, 0x61, 0x51, 0x49, 0x46,// 2
0x00, 0x21, 0x41, 0x45, 0x4B, 0x31,// 3
0x00, 0x18, 0x14, 0x12, 0x7F, 0x10,// 4
0x00, 0x27, 0x45, 0x45, 0x45, 0x39,// 5
0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
0x00, 0x01, 0x71, 0x09, 0x05, 0x03,// 7
0x00, 0x36, 0x49, 0x49, 0x49, 0x36,// 8
0x00, 0x06, 0x49, 0x49, 0x29, 0x1E,// 9
0x00, 0x00, 0x36, 0x36, 0x00, 0x00,// :
0x00, 0x00, 0x56, 0x36, 0x00, 0x00,// ;
0x00, 0x08, 0x14, 0x22, 0x41, 0x00,// <
0x00, 0x14, 0x14, 0x14, 0x14, 0x14,// =
0x00, 0x00, 0x41, 0x22, 0x14, 0x08,// >
0x00, 0x02, 0x01, 0x51, 0x09, 0x06,// ?
0x00, 0x32, 0x49, 0x59, 0x51, 0x3E,// @
0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C,// A
0x00, 0x7F, 0x49, 0x49, 0x49, 0x36,// B
0x00, 0x3E, 0x41, 0x41, 0x41, 0x22,// C
0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C,// D
0x00, 0x7F, 0x49, 0x49, 0x49, 0x41,// E
0x00, 0x7F, 0x09, 0x09, 0x09, 0x01,// F
0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A,// G
0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F,// H
0x00, 0x00, 0x41, 0x7F, 0x41, 0x00,// I
0x00, 0x20, 0x40, 0x41, 0x3F, 0x01,// J
0x00, 0x7F, 0x08, 0x14, 0x22, 0x41,// K
0x00, 0x7F, 0x40, 0x40, 0x40, 0x40,// L
0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F,// M
0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F,// N
0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E,// O
0x00, 0x7F, 0x09, 0x09, 0x09, 0x06,// P
0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
0x00, 0x7F, 0x09, 0x19, 0x29, 0x46,// R
0x00, 0x46, 0x49, 0x49, 0x49, 0x31,// S
0x00, 0x01, 0x01, 0x7F, 0x01, 0x01,// T
0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F,// U
0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F,// V
0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F,// W
0x00, 0x63, 0x14, 0x08, 0x14, 0x63,// X
0x00, 0x07, 0x08, 0x70, 0x08, 0x07,// Y
0x00, 0x61, 0x51, 0x49, 0x45, 0x43,// Z
0x00, 0x00, 0x7F, 0x41, 0x41, 0x00,// [
0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55,// 55
0x00, 0x00, 0x41, 0x41, 0x7F, 0x00,// ]
0x00, 0x04, 0x02, 0x01, 0x02, 0x04,// ^
0x00, 0x40, 0x40, 0x40, 0x40, 0x40,// _
0x00, 0x00, 0x01, 0x02, 0x04, 0x00,// '
0x00, 0x20, 0x54, 0x54, 0x54, 0x78,// a
0x00, 0x7F, 0x48, 0x44, 0x44, 0x38,// b
0x00, 0x38, 0x44, 0x44, 0x44, 0x20,// c
0x00, 0x38, 0x44, 0x44, 0x48, 0x7F,// d
0x00, 0x38, 0x54, 0x54, 0x54, 0x18,// e
0x00, 0x08, 0x7E, 0x09, 0x01, 0x02,// f
0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C,// g
0x00, 0x7F, 0x08, 0x04, 0x04, 0x78,// h
0x00, 0x00, 0x44, 0x7D, 0x40, 0x00,// i
0x00, 0x40, 0x80, 0x84, 0x7D, 0x00,// j
0x00, 0x7F, 0x10, 0x28, 0x44, 0x00,// k
0x00, 0x00, 0x41, 0x7F, 0x40, 0x00,// l
0x00, 0x7C, 0x04, 0x18, 0x04, 0x78,// m
0x00, 0x7C, 0x08, 0x04, 0x04, 0x78,// n
0x00, 0x38, 0x44, 0x44, 0x44, 0x38,// o
0x00, 0xFC, 0x24, 0x24, 0x24, 0x18,// p
0x00, 0x18, 0x24, 0x24, 0x18, 0xFC,// q
0x00, 0x7C, 0x08, 0x04, 0x04, 0x08,// r
0x00, 0x48, 0x54, 0x54, 0x54, 0x20,// s
0x00, 0x04, 0x3F, 0x44, 0x40, 0x20,// t
0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C,// u
0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C,// v
0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C,// w
0x00, 0x44, 0x28, 0x10, 0x28, 0x44,// x
0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,// y
0x00, 0x44, 0x64, 0x54, 0x4C, 0x44,// z
0x14, 0x14, 0x14, 0x14, 0x14, 0x14,// horiz lines
};
#endif


登录 或 注册 后才可以进行评论哦!
还没有评论,抢个沙发!