一、前期准备
单片机:STM32F407VET6
开发环境:MDK5.14
库函数:STM32Cube_FW_F4_V1.16.0
1.3 OLED模块:淘宝有售
二、实验效果
三、驱动原理
IIC配置:
剩余的请参照具体的数据手册,大部分指令都是兼容的,不同驱动器可能会有细微的差别,请对照手册修改。
需要完整工程或者有问题的请加QQ:1002521871,验证:呵呵.
四、驱动代码
oled.h
#ifndef __OLED_H__
#define __OLED_H__
#include "stm32f4xx_hal.h"
#include "i2c.h"
#include "bmp.h"
#include "oledfont.h"
#define OLED 0
#define SIZE 16
#define XLevelL 0x00
#define XLevelH 0x10
#define Max_Column 128
#define Max_Row 64
#define Brightness 0xff
#define X_WIDTH 128
#define Y_WIDTH 64
typedef enum
{
OLED_CMD,
OLED_DATA
}OLED_WR_MODE;
typedef enum
{
Display_ON,
Display_OFF,
Display_Clear,
Display_Test
}DIS_MODE;
extern I2C_HandleTypeDef hi2c1;
//OLED控制用函数
extern void OLED_WR_Byte(uint8_t dat, OLED_WR_MODE cmd);
extern void OLED_Display_Status(DIS_MODE mode);
extern void OLEDConfiguration(void);
extern void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t t);
extern void OLED_Fill(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t dot);
extern void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr);
extern void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size);
extern void OLED_ShowString(uint8_t x,uint8_t y, uint8_t *p);
extern void OLED_Set_Pos(uint8_t x, uint8_t y);
extern void OLED_ShowCHinese(uint8_t x, uint8_t y, uint8_t no);
extern void OLED_DrawBMP(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1, uint8_t BMP[]);
#endif
oled.c
#include "oled.h"
//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127
//向SSD1106写入一个字节。
//dat:要写入的数据/命令
//cmd:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(uint8_t dat, OLED_WR_MODE cmd)
{
uint8_t write[2] = {0};
write[1] = dat;
switch(cmd)
{
case OLED_CMD:
write[0] = 0x00;
break;
case OLED_DATA:
write[0] = 0x40;
break;
}
HAL_I2C_Master_Transmit(&hi2c1, 0x78, write, 2, HAL_MAX_DELAY);
}
//#endif
void OLED_Set_Pos(uint8_t x, uint8_t y)
{
OLED_WR_Byte(0xB0 + y, OLED_CMD);
OLED_WR_Byte(((x & 0xF0) >> 4) | 0x10, OLED_CMD);
OLED_WR_Byte((x & 0x0F) | 0x01, OLED_CMD);
}
void OLED_Display_Status(DIS_MODE mode)
{
uint8_t i,n;
switch(mode)
{
case Display_ON://开启OLED显示
OLED_WR_Byte(0X8D, OLED_CMD); //SET DCDC命令
OLED_WR_Byte(0X14, OLED_CMD); //DCDC ON
OLED_WR_Byte(0XAF, OLED_CMD); //DISPLAY ON
break;
case Display_OFF://关闭OLED显示
OLED_WR_Byte(0X8D, OLED_CMD); //SET DCDC命令
OLED_WR_Byte(0X10, OLED_CMD); //DCDC OFF
OLED_WR_Byte(0XAE, OLED_CMD); //DISPLAY OFF
break;
case Display_Clear://清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
for(i = 0; i < 8; i ++)
{
OLED_WR_Byte(0xB0 + i, OLED_CMD); //设置页地址(0~7)
OLED_WR_Byte(0x02, OLED_CMD); //设置显示位置—列低地址
OLED_WR_Byte(0x10, OLED_CMD); //设置显示位置—列高地址
for(n = 0; n < Max_Column; n ++)
{
OLED_WR_Byte(0, OLED_DATA);
}
} //更新显示
break;
case Display_Test:
for(i = 0; i < 8; i ++)
{
OLED_WR_Byte(0xb0 + i, OLED_CMD); //设置页地址(0~7)
OLED_WR_Byte(0x02, OLED_CMD); //设置显示位置—列低地址
OLED_WR_Byte(0x10, OLED_CMD); //设置显示位置—列高地址
for(n = 0; n < Max_Column; n ++)
{
OLED_WR_Byte(0XFF, OLED_DATA);
HAL_Delay(5);
}
} //更新显示
break;
}
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示
//size:选择字体 16/12
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr)
{
uint8_t c = 0, i = 0;
c = chr - ' ';//得到偏移后的值
if(x > Max_Column - 1)
{
x = 0;
y += 2;
}
if(SIZE == 16)
{
OLED_Set_Pos(x, y);
for(i = 0; i < 8; i ++)
{
OLED_WR_Byte(F8X16[c * 16 + i], OLED_DATA);
}
OLED_Set_Pos(x, y + 1);
for(i = 0; i < 8; i ++)
{
OLED_WR_Byte(F8X16[c * 16 + i + 8], OLED_DATA);
}
}
else
{
OLED_Set_Pos(x, y + 1);
for(i = 0; i < 6; i ++)
{
OLED_WR_Byte(F6x8[c][i],OLED_DATA);
}
}
}
void OLED_ShowChar1(uint8_t x, uint8_t y, uint8_t chr)
{
uint8_t c = 0, i = 0;
c = chr - ' ';//得到偏移后的值
if(x > Max_Column - 1)
{
x = 0;
y += 2;
}
if(SIZE == 16)
{
OLED_Set_Pos(x, y);
for(i = 0; i < 6; i ++)
{
OLED_WR_Byte(F6x8[c][i], OLED_DATA);
}
OLED_Set_Pos(x, y + 1);
for(i = 0; i < 6; i ++)
{
OLED_WR_Byte(F6x8[c][i + 6], OLED_DATA);
}
}
else
{
OLED_Set_Pos(x, y + 1);
for(i = 0; i < 6; i ++)
{
OLED_WR_Byte(F6x8[c][i],OLED_DATA);
}
}
}
//m^n函数
uint32_t oled_pow(uint8_t m,uint8_t n)
{
uint32_t result = 1;
while(n --)
{
result *= m;
}
return result;
}
//显示2个数字
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//mode:模式 0,填充模式;1,叠加模式
//num:数值(0~4294967295);
void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size)
{
uint8_t t,temp;
uint8_t enshow = 0;
for(t = 0; t < len; t ++)
{
temp = (num / oled_pow(10, len - t - 1)) % 10;
if(enshow == 0 && t < (len - 1))
{
if(temp == 0)
{
OLED_ShowChar(x + (size / 2) * t, y, ' ');
continue;
}else enshow = 1;
}
OLED_ShowChar(x + (size / 2) * t, y, temp + '0');
}
}
//显示一个字符号串
void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr)
{
uint8_t j = 0;
while (chr[j] != '\0')
{
OLED_ShowChar(x, y, chr[j]);
x += 8;
if(x > 120)
{
x = 0;
y += 2;
}
j++;
}
}
//显示汉字
void OLED_ShowCHinese(uint8_t x, uint8_t y, uint8_t no)
{
uint8_t t, adder = 0;
OLED_Set_Pos(x, y);
for(t = 0; t < 16; t ++)
{
OLED_WR_Byte(Hzk[2 * no][t], OLED_DATA);
adder += 1;
}
OLED_Set_Pos(x, y + 1);
for(t = 0; t < 16; t ++)
{
OLED_WR_Byte(Hzk[2 * no + 1][t], OLED_DATA);
adder += 1;
}
}
/***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
void OLED_DrawBMP(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1, uint8_t BMP[])
{
uint8_t j = 0;
uint8_t x, y;
if(y1 % 8 == 0)
{
y = y1 / 8;
}
else
{
y = y1 / 8 + 1;
}
for(y = y0; y < y1; y ++)
{
OLED_Set_Pos(x0, y);
for(x = x0; x < x1; x ++)
{
OLED_WR_Byte(BMP[j ++], OLED_DATA);
}
}
}
//初始化SSD1306
void OLEDConfiguration(void)
{
OLED_WR_Byte(0xAE, OLED_CMD);//--turn off oled panel
OLED_WR_Byte(0x00, OLED_CMD);//---set low column address
OLED_WR_Byte(0x10, OLED_CMD);//---set high column address
OLED_WR_Byte(0x40, OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
OLED_WR_Byte(0x81, OLED_CMD);//--set contrast control register
OLED_WR_Byte(0xCF, OLED_CMD); // Set SEG Output Current Brightness
OLED_WR_Byte(0xA1, OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常
OLED_WR_Byte(0xC8, OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常
OLED_WR_Byte(0xA6, OLED_CMD);//--set normal display
OLED_WR_Byte(0xA8, OLED_CMD);//--set multiplex ratio(1 to 64)
OLED_WR_Byte(0x3f, OLED_CMD);//--1/64 duty
OLED_WR_Byte(0xD3, OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
OLED_WR_Byte(0x00, OLED_CMD);//-not offset
OLED_WR_Byte(0xd5, OLED_CMD);//--set display clock divide ratio/oscillator frequency
OLED_WR_Byte(0x80, OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
OLED_WR_Byte(0xD9, OLED_CMD);//--set pre-charge period
OLED_WR_Byte(0xF1, OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_WR_Byte(0xDA, OLED_CMD);//--set com pins hardware configuration
OLED_WR_Byte(0x12, OLED_CMD);
OLED_WR_Byte(0xDB, OLED_CMD);//--set vcomh
OLED_WR_Byte(0x40, OLED_CMD);//Set VCOM Deselect Level
OLED_WR_Byte(0x20, OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
OLED_WR_Byte(0x02, OLED_CMD);//
OLED_WR_Byte(0x8D, OLED_CMD);//--set Charge Pump enable/disable
OLED_WR_Byte(0x14, OLED_CMD);//--set(0x10) disable
OLED_WR_Byte(0xA4, OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
OLED_WR_Byte(0xA6, OLED_CMD);// Disable Inverse Display On (0xa6/a7)
OLED_WR_Byte(0xAF, OLED_CMD);//--turn on oled panel
OLED_WR_Byte(0xAF, OLED_CMD); /*display ON*/
//
// OLED_WR_Byte(0xAE, OLED_CMD);//--display off
// OLED_WR_Byte(0x02, OLED_CMD);//---set low column address
// OLED_WR_Byte(0x10, OLED_CMD);//---set high column address
// OLED_WR_Byte(0x40, OLED_CMD);//--set start line address
// OLED_WR_Byte(0xB0, OLED_CMD);//--set page address
// OLED_WR_Byte(0x81, OLED_CMD); // contract control
// OLED_WR_Byte(0xFF, OLED_CMD);//--128
// OLED_WR_Byte(0xA1, OLED_CMD);//set segment remap
// OLED_WR_Byte(0xA6, OLED_CMD);//--normal / reverse
// OLED_WR_Byte(0xA8, OLED_CMD);//--set multiplex ratio(1 to 64)
// OLED_WR_Byte(0x3F, OLED_CMD);//--1/64 duty
// OLED_WR_Byte(0xAD, OLED_CMD);//set charge pump enable
// OLED_WR_Byte(0x8B, OLED_CMD);//-0x8B 内供 VCC
// OLED_WR_Byte(0x33, OLED_CMD);//-0X30---0X33 set VPP 9V
// OLED_WR_Byte(0xC8, OLED_CMD);//Com scan direction
// OLED_WR_Byte(0xD3, OLED_CMD);//-set display offset
// OLED_WR_Byte(0x00, OLED_CMD);//
//
// OLED_WR_Byte(0xD5, OLED_CMD);//set osc division
// OLED_WR_Byte(0x80, OLED_CMD);//
//
// OLED_WR_Byte(0xD8, OLED_CMD);//set area color mode off
// OLED_WR_Byte(0x05, OLED_CMD);//
//
// OLED_WR_Byte(0xD9, OLED_CMD);//Set Pre-Charge Period
// OLED_WR_Byte(0x1F, OLED_CMD);//
//
// OLED_WR_Byte(0xDA, OLED_CMD);//set com pin configuartion
// OLED_WR_Byte(0x12, OLED_CMD);//
//
// OLED_WR_Byte(0xDB, OLED_CMD);//set Vcomh
// OLED_WR_Byte(0x40, OLED_CMD);//
//
//
// OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
// OLED_Display_Status(Display_Test);
// HAL_Delay(1000);
OLED_Display_Status(Display_Clear);
OLED_Set_Pos(0, 0);
}
由于作者能力有限,有不妥之处欢迎指正,邮箱[email protected]