前
言
上一期我们介绍了如何使用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中显示字符,我们需要先将屏幕分块,我们知道屏幕总共分为12864的像素点,
我们将一块区域块作为每个字符的显示,例如我们选择86的区域作为每个字符块。(取模软件默认,可以自己设置)
我们可以利用字库取模软件来生成字库信息。
取模方式修改为纵向取模,获得我们的十六进制数据。并且创建一个文件来存放这些数据。(这里偷个懒用现成的字库,为了防止观感,直接放到最后去了)
// 在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 != '') { // 检查是否超出显示范围 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