@[TOC]stm32 OLED显示
1、OLED基本结构
大小:128X64个点阵
X方向128bit
Y方向64B,且分为8页,一页8B
2、显现原理
当对应的某一个像素点为1时,对应的小方格点亮。且每一列对应一个字节,低位在最上面,高位在下面
3、字体大小
一般英文8X16,中文16X16
4、驱动芯片(SSD1306)
SSD1306常用命令
5、将文字写入相应的位置
需要设置同时两个命令,一个是列地址低4位命令,一个是列地址高4位命令,假如我当前要锁定第125列,125对应的16进制是0x7D,那么我只需要同时发0x17和0x0D就可以了(其中没有先后顺序)
6、字模的获取
(1)我用的是PCtoLCD2002完美版
(2)取模方法
如果想要显示图片则选择图片模式(注意选择图片模式,图片不能是彩色,只能是纯白和纯黑的组合,且图片是BMP文件,像素大小不能大于128X64)
(3)设置好后,可以在方框内输入自己需要显现的文字
(4)再将生成的字模复制到文件中即可
7、和单片机相连常用的协议
I2c,和SPI
8、以下为用I2C实现OLED的显示的主要代码
以下是oled.c文件
#include "oled.h"
#include "stdarg.h"
#include "stdio.h"
#include "redirect.h"
/* 初始化命令 */
uint8_t CMD_Data[]={
0xAE, 0x00, 0x10, 0x40, 0xB0, 0x81, 0xFF, 0xA1, 0xA6, 0xA8, 0x3F,
0xC8, 0xD3, 0x00, 0xD5, 0x80, 0xD8, 0x05, 0xD9, 0xF1, 0xDA, 0x12,
0xD8, 0x30, 0x8D, 0x14, 0xAF};
/* 向设备写控制命令 */
void OLED_WR_CMD(uint8_t cmd)
{
HAL_I2C_Mem_Write(&OLED_I2C , 0x78, 0x00, I2C_MEMADD_SIZE_8BIT, &cmd, 1, 0xFF);
}
/* 向设备写数据 */
void OLED_WR_DATA(uint8_t data)
{
HAL_I2C_Mem_Write(&OLED_I2C , 0x78, 0x40, I2C_MEMADD_SIZE_8BIT, &data, 1, 0xFF);
}
/* 设置光标坐标 */
void OLED_Set_Pos(uint8_t x, uint8_t y)
{
OLED_WR_CMD(0xb0+y);
OLED_WR_CMD(((x&0xf0)>>4)|0x10);
OLED_WR_CMD(x&0x0f);
}
/* 写一个字节到指定坐标 */
void WriteByte(uint8_t x, uint8_t y, uint8_t data)
{
OLED_Set_Pos(x, y);
OLED_WR_DATA(data);
}
/* 写全屏屏幕 */
void OLED_FILL(uint8_t *data)
{
for(int i = 0; i<(OLED_HEIGHT / 8); i++)
{
OLED_Set_Pos(0, i);
HAL_I2C_Mem_Write(&OLED_I2C , 0x78, 0x40, I2C_MEMADD_SIZE_8BIT, data + OLED_WIDTH * i, OLED_WIDTH, 0xFF);
}
}
/* OLED显示一个字符 */
void OLED_ShowChar(uint16_t x, uint16_t y, FontDef_t *Size, uint8_t c)
{
#define ROW Size->FontWidth * Size->FontHeight / 8 + 1
int num = 0;
while(c != Size->data[num])
num += ROW;
for(int b = 0; b < (Size->FontHeight / 8); b++)
for(int a=0; a < Size->FontWidth; a++)
WriteByte(x + a, y + b, Size->data[num + 1 + a + (b * Size->FontWidth)]);
}
/* OLED显示一串字符 */
static char dat[128]; //16*8
void OLED_ShowString(uint16_t x, uint16_t y, FontDef_t *Size, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vsnprintf(dat, sizeof(dat) - 1, fmt, args);
va_end(args);
int i = 0;
while(dat[i] != '\0')
{
OLED_ShowChar(x ,y, Size, dat[i]);
x += Size->FontWidth;
i++;
}
}
/* OLED显示一个中文 */
void OLED_ShowChineseChar(uint16_t x, uint16_t y, CN16FontDef_t *Size, char CN[2])
{
int num = 0;
while (1)
{
if((Size->data[num].Index[0] == *(CN + 0)) && (Size->data[num].Index[1] == *(CN + 1)))
break;
num++;
}
for(int b = 0; b < (Size->FontHeight / 8); b++)
for(int a=0; a < Size->FontWidth; a++)
WriteByte(x + a, y + b, Size->data[num].Msk[a + (b * Size->FontWidth)]);
}
/* OLED显示串中文字符 */
static char Cdat[256]; //16*16
void OLED_ShowChineseString(uint16_t x, uint16_t y, CN16FontDef_t *Size, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vsnprintf(Cdat, sizeof(Cdat) - 1, fmt, args);
va_end(args);
int i = 0;
while(Cdat[2*i] != '\0')
{
OLED_ShowChineseChar(x ,y, Size, (Cdat+2*i));//数组,128行,2列,最多显示128个字符
x += Size->FontWidth;
i++;
}
}
/* 清屏 */
void OLED_Clear(void)
{
for(int i=0;i < (OLED_HEIGHT / 8);i++)
{
OLED_WR_CMD(0xb0 + i);
OLED_WR_CMD (0x00);
OLED_WR_CMD (0x10);
for(int n = 0; n < OLED_WIDTH; n++)
OLED_WR_DATA(0x00);
}
}
/* 初始化oled屏幕 */
void OLED_Init(void)
{
HAL_I2C_Mem_Write(&OLED_I2C , 0x78, 0x00, I2C_MEMADD_SIZE_8BIT, CMD_Data, sizeof(CMD_Data), 0x100);
OLED_Clear();
}
以下为oled.h文件
/* OLED底层驱动 */
#ifndef __OLED_H__
#define __OLED_H__
#include "fonts.h"
#include "i2c.h"
/* 修改对应的I2C句柄和屏幕大小 */
#define OLED_I2C hi2c2
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
#define OLED_WIDTH_HALF OLED_WIDTH / 2
#define OLED_HEIGHT_HALF OLED_HEIGHT / 2
/* 英文字库 */
extern FontDef_t Font_8x16;
/* 中文字库 */
extern CN16FontDef_t CN16Font_16x16;
/* 设置图标 */
extern uint8_t bmp[];
/*笑脸*/
extern uint8_t SmilingFace[];
/*火柴人图标*/
extern uint8_t matchman3_1[];
extern uint8_t matchman3_2[];
extern uint8_t matchman3_3[];
extern uint8_t matchman3_4[];
//OLED初始化