一期我们介绍了如何使用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


#defineUSE_SOFEWARE_I2C#
#endif&nbsp;&nbsp;#
#ifndef__FRONT_H__#
嘉立创PCB

还没有评论,抢个沙发!