文章基于适用于STM32F4系列,作者使用STM32F401CCU6开发板。
本文章基于此系列和开发板展开讨论。
本系列以SSD1306为主控芯片的I2C接口的0.96寸OLED屏幕为例介绍
内容较多,分节进行
链接
需求分析
在OELD指定位置上显示字母和数字,汉字
流程
- 页面分割
- 寻找指定位置
- 显示
前置
屏幕分组
因为字母数字和符号是8 * 16 的点阵,汉字是 16 * 16的点阵
为了后续编程的方便,我将整个128 * 64的屏幕按照 8 * 16 的矩形分开
标号已经给出,先写x在写y。所以最左上是0-0
这张示意图中的每个小方格代表8 * 16的像素小格
表示字母数字和符号时每次输出占用一个,汉字输出时每个汉字占用横向连续的两格
寻址方式
因为这里并不是发送全屏的数据,因此使用页寻址模式
原理之前介绍过,传送门
这里只放设置起始地址的代码
//设置页寻址模式的其实地址,x是列数,y是页数
void OLED_Set_PageAddress(u8 x, u8 y)
{
// 0<=y<=7,0<=x<=127
if ((y <= 7) && (x <= 127))
{
OLED_Write_Ctrl_Start();
I2C_SendByte(0x20); //设置寻址模式 (0x00水平/0x01垂直/0x02页)
I2C_SendByte(0x10); //页寻址模式
I2C_SendByte(0xb0 | (y & 0x0f)); //设置页
I2C_SendByte(((x & 0xf0) >> 4) | 0x10); //设置列的高位
I2C_SendByte(x & 0x0f); //设置页的低位
I2C_End();
}
}
发送每页数据前调用这个函数,之后发送数据即可
显示字母,数字和符号
为了后续方便的调用,字母数字和符号我们建立一个结构体,内部存二维数组指针
typedef struct
{
uc8 (*TDArray)[8];
} OLED_Alphanumeric_Array;
取模出来的英文符号是[2][8]
的数组,即有两页,8列
为了便于后期数字和字母的调用,将大小写字母和大小写16进制数字编写为结构体数组
C文件(Alphanumeric.C)
const OLED_Alphanumeric_Array OLED_Num_HEX_Small[16] = {OLED_0, OLED_1, OLED_2, OLED_3, OLED_4, OLED_5, OLED_6, OLED_7, OLED_8, OLED_9};
const OLED_Alphanumeric_Array OLED_Num_HEX_Big[16] = {OLED_0, OLED_1, OLED_2, OLED_3, OLED_4, OLED_5, OLED_6, OLED_7, OLED_8, OLED_9, OLED_A, OLED_B, OLED_C, OLED_D, OLED_E, OLED_F};
const OLED_Alphanumeric_Array OLED_Letter_Small[26] = {OLED_a, OLED_b, OLED_c, OLED_d, OLED_e, OLED_f, OLED_g, OLED_h, OLED_i, OLED_j, OLED_k, OLED_l, OLED_m, OLED_n, OLED_o, OLED_p, OLED_q, OLED_r, OLED_s, OLED_t, OLED_u, OLED_v, OLED_w, OLED_x, OLED_y, OLED_z};
const OLED_Alphanumeric_Array OLED_Letter_Big[26] = {OLED_A, OLED_B, OLED_C, OLED_D, OLED_E, OLED_F, OLED_G, OLED_H, OLED_I, OLED_J, OLED_K, OLED_L, OLED_M, OLED_N, OLED_O, OLED_P, OLED_Q, OLED_R, OLED_S, OLED_T, OLED_U, OLED_V, OLED_W, OLED_X, OLED_Y, OLED_Z};
字模就不在此展示了
英系符号显示
使用页地址寻址,每一页前均需要设置地址
这里要注意了,这个函数中我设置的是先输入y,也就是先设置行,再设置列
C文件(OLED.C)
//指定位置写字母或数字 先输入选定的行数<4,再输入列数<16,再输入数据
void OLED_Alphanumeric(u8 y, u8 x, OLED_Alphanumeric_Array Data)
{
if (y < 4 && x < 16) //验证,避免超范围
{
for (int i = 0; i < 2; i++) //扫描字模的两页
{
OLED_Set_PageAddress(x * 8, y * 2 + i); //每页都需要设置地址
OLED_Write_Data_Start();
for (int j = 0; j < 8; j++) //扫描列
{
I2C_SendByte(Data.TDArray[i][j]);
}
I2C_End();
}
}
else
{
OLED_Error();
}
}
OLED_Error();
这个是一个自定义的函数,就是发送字母,在出现不正确的显示时展示出来
C文件(OLED.C)
// OLED上提示错误函数
void OLED_Error(void)
{
for (int i = 0; i < 4; i++)
{
OLED_Alphanumeric(i, 0, OLED_Letter_Big['E' - 'A']);
OLED_Alphanumeric(i, 1, OLED_Letter_Big['R' - 'A']);
OLED_Alphanumeric(i, 2, OLED_Letter_Big['R' - 'A']);
OLED_Alphanumeric(i, 3, OLED_Letter_Big['O' - 'A']);
OLED_Alphanumeric(i, 4, OLED_Letter_Big['R' - 'A']);
}
}
c语言是支持这种在函数中调用自身的
每一行最多显示16个字符,最多有4行
显示汉字
汉字的字模是一个16 * 16的点阵,按照之前的分组,需要占用横向连续两个小格
同样为了方便建立一个结构体
typedef struct
{
uc8 (*TDArray)[16];
} OLED_Chinese_Array;
字模是[2][16]
的数组,提供的源码没有中文字库,需要使用什么汉字请自行添加
发送函数和英文没什么太大区别,只需要修改下x,y的范围即可
C文件(OLED.C)
//指定位置写汉字
void OLED_Chinese(u8 y, u8 x, OLED_Chinese_Array Data)
{
if (y < 4 && x < 8)
{
for (int i = 0; i < 2; i++)
{
OLED_Set_PageAddress(x * 16, y * 2 + i);
OLED_Write_Data_Start();
for (int j = 0; j < 16; j++)
{
I2C_SendByte(Data.TDArray[i][j]);
}
I2C_End();
}
}
else
{
OLED_Error();
}
}
每一行最多显示8个汉字,最多有4行
取模教程
打开软件选择字符模式
设置
之前说过OLED编码规则,这里根据规则设置即可,传送门
输入内容,生成即可
汉字同理
成品
链接:百度网盘
提取码:ierk