目录
硬件配置
- 主控:STM32F401Nucleo-64(STM32F401RET6)
- 从控:SSD1306驱动控制的0.96OLED
软件配置
- STM32CUBEMX
- keil
- 一个字库
const unsigned char asc2_1206[95][12]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x3F,0x40,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x40,0x00,0x00,0x00},/*""",2*/
{0x09,0x00,0x0B,0xC0,0x3D,0x00,0x0B,0xC0,0x3D,0x00,0x09,0x00},/*"#",3*/
{0x18,0xC0,0x24,0x40,0x7F,0xE0,0x22,0x40,0x31,0x80,0x00,0x00},/*"$",4*/
{0x18,0x00,0x24,0xC0,0x1B,0x00,0x0D,0x80,0x32,0x40,0x01,0x80},/*"%",5*/
{0x03,0x80,0x1C,0x40,0x27,0x40,0x1C,0x80,0x07,0x40,0x00,0x40},/*"&",6*/
{0x10,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x20,0x40,0x40,0x20},/*"(",8*/
{0x00,0x00,0x40,0x20,0x20,0x40,0x1F,0x80,0x00,0x00,0x00,0x00},/*")",9*/
{0x09,0x00,0x06,0x00,0x1F,0x80,0x06,0x00,0x09,0x00,0x00,0x00},/*"*",10*/
{0x04,0x00,0x04,0x00,0x3F,0x80,0x04,0x00,0x04,0x00,0x00,0x00},/*"+",11*/
{0x00,0x10,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
{0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00},/*"-",13*/
{0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
{0x00,0x20,0x01,0xC0,0x06,0x00,0x38,0x00,0x40,0x00,0x00,0x00},/*"/",15*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"0",16*/
{0x00,0x00,0x10,0x40,0x3F,0xC0,0x00,0x40,0x00,0x00,0x00,0x00},/*"1",17*/
{0x18,0xC0,0x21,0x40,0x22,0x40,0x24,0x40,0x18,0x40,0x00,0x00},/*"2",18*/
{0x10,0x80,0x20,0x40,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"3",19*/
{0x02,0x00,0x0D,0x00,0x11,0x00,0x3F,0xC0,0x01,0x40,0x00,0x00},/*"4",20*/
{0x3C,0x80,0x24,0x40,0x24,0x40,0x24,0x40,0x23,0x80,0x00,0x00},/*"5",21*/
{0x1F,0x80,0x24,0x40,0x24,0x40,0x34,0x40,0x03,0x80,0x00,0x00},/*"6",22*/
{0x30,0x00,0x20,0x00,0x27,0xC0,0x38,0x00,0x20,0x00,0x00,0x00},/*"7",23*/
{0x1B,0x80,0x24,0x40,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"8",24*/
{0x1C,0x00,0x22,0xC0,0x22,0x40,0x22,0x40,0x1F,0x80,0x00,0x00},/*"9",25*/
{0x00,0x00,0x00,0x00,0x08,0x40,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
{0x00,0x00,0x00,0x00,0x04,0x60,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
{0x00,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0x40,0x40},/*"<",28*/
{0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x00,0x00},/*"=",29*/
{0x00,0x00,0x40,0x40,0x20,0x80,0x11,0x00,0x0A,0x00,0x04,0x00},/*">",30*/
{0x18,0x00,0x20,0x00,0x23,0x40,0x24,0x00,0x18,0x00,0x00,0x00},/*"?",31*/
{0x1F,0x80,0x20,0x40,0x27,0x40,0x29,0x40,0x1F,0x40,0x00,0x00},/*"@",32*/
{0x00,0x40,0x07,0xC0,0x39,0x00,0x0F,0x00,0x01,0xC0,0x00,0x40},/*"A",33*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"B",34*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x30,0x80,0x00,0x00},/*"C",35*/
{0x20,0x40,0x3F,0xC0,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"D",36*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x2E,0x40,0x30,0xC0,0x00,0x00},/*"E",37*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x2E,0x00,0x30,0x00,0x00,0x00},/*"F",38*/
{0x0F,0x00,0x10,0x80,0x20,0x40,0x22,0x40,0x33,0x80,0x02,0x00},/*"G",39*/
{0x20,0x40,0x3F,0xC0,0x04,0x00,0x04,0x00,0x3F,0xC0,0x20,0x40},/*"H",40*/
{0x20,0x40,0x20,0x40,0x3F,0xC0,0x20,0x40,0x20,0x40,0x00,0x00},/*"I",41*/
{0x00,0x60,0x20,0x20,0x20,0x20,0x3F,0xC0,0x20,0x00,0x20,0x00},/*"J",42*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x0B,0x00,0x30,0xC0,0x20,0x40},/*"K",43*/
{0x20,0x40,0x3F,0xC0,0x20,0x40,0x00,0x40,0x00,0x40,0x00,0xC0},/*"L",44*/
{0x3F,0xC0,0x3C,0x00,0x03,0xC0,0x3C,0x00,0x3F,0xC0,0x00,0x00},/*"M",45*/
{0x20,0x40,0x3F,0xC0,0x0C,0x40,0x23,0x00,0x3F,0xC0,0x20,0x00},/*"N",46*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"O",47*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x24,0x00,0x18,0x00,0x00,0x00},/*"P",48*/
{0x1F,0x80,0x21,0x40,0x21,0x40,0x20,0xE0,0x1F,0xA0,0x00,0x00},/*"Q",49*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x26,0x00,0x19,0xC0,0x00,0x40},/*"R",50*/
{0x18,0xC0,0x24,0x40,0x24,0x40,0x22,0x40,0x31,0x80,0x00,0x00},/*"S",51*/
{0x30,0x00,0x20,0x40,0x3F,0xC0,0x20,0x40,0x30,0x00,0x00,0x00},/*"T",52*/
{0x20,0x00,0x3F,0x80,0x00,0x40,0x00,0x40,0x3F,0x80,0x20,0x00},/*"U",53*/
{0x20,0x00,0x3E,0x00,0x01,0xC0,0x07,0x00,0x38,0x00,0x20,0x00},/*"V",54*/
{0x38,0x00,0x07,0xC0,0x3C,0x00,0x07,0xC0,0x38,0x00,0x00,0x00},/*"W",55*/
{0x20,0x40,0x39,0xC0,0x06,0x00,0x39,0xC0,0x20,0x40,0x00,0x00},/*"X",56*/
{0x20,0x00,0x38,0x40,0x07,0xC0,0x38,0x40,0x20,0x00,0x00,0x00},/*"Y",57*/
{0x30,0x40,0x21,0xC0,0x26,0x40,0x38,0x40,0x20,0xC0,0x00,0x00},/*"Z",58*/
{0x00,0x00,0x00,0x00,0x7F,0xE0,0x40,0x20,0x40,0x20,0x00,0x00},/*"[",59*/
{0x00,0x00,0x70,0x00,0x0C,0x00,0x03,0x80,0x00,0x40,0x00,0x00},/*"\",60*/
{0x00,0x00,0x40,0x20,0x40,0x20,0x7F,0xE0,0x00,0x00,0x00,0x00},/*"]",61*/
{0x00,0x00,0x20,0x00,0x40,0x00,0x20,0x00,0x00,0x00,0x00,0x00},/*"^",62*/
{0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10},/*"_",63*/
{0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
{0x00,0x00,0x02,0x80,0x05,0x40,0x05,0x40,0x03,0xC0,0x00,0x40},/*"a",65*/
{0x20,0x00,0x3F,0xC0,0x04,0x40,0x04,0x40,0x03,0x80,0x00,0x00},/*"b",66*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x40,0x06,0x40,0x00,0x00},/*"c",67*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x24,0x40,0x3F,0xC0,0x00,0x40},/*"d",68*/
{0x00,0x00,0x03,0x80,0x05,0x40,0x05,0x40,0x03,0x40,0x00,0x00},/*"e",69*/
{0x00,0x00,0x04,0x40,0x1F,0xC0,0x24,0x40,0x24,0x40,0x20,0x00},/*"f",70*/
{0x00,0x00,0x02,0xE0,0x05,0x50,0x05,0x50,0x06,0x50,0x04,0x20},/*"g",71*/
{0x20,0x40,0x3F,0xC0,0x04,0x40,0x04,0x00,0x03,0xC0,0x00,0x40},/*"h",72*/
{0x00,0x00,0x04,0x40,0x27,0xC0,0x00,0x40,0x00,0x00,0x00,0x00},/*"i",73*/
{0x00,0x10,0x00,0x10,0x04,0x10,0x27,0xE0,0x00,0x00,0x00,0x00},/*"j",74*/
{0x20,0x40,0x3F,0xC0,0x01,0x40,0x07,0x00,0x04,0xC0,0x04,0x40},/*"k",75*/
{0x20,0x40,0x20,0x40,0x3F,0xC0,0x00,0x40,0x00,0x40,0x00,0x00},/*"l",76*/
{0x07,0xC0,0x04,0x00,0x07,0xC0,0x04,0x00,0x03,0xC0,0x00,0x00},/*"m",77*/
{0x04,0x40,0x07,0xC0,0x04,0x40,0x04,0x00,0x03,0xC0,0x00,0x40},/*"n",78*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x40,0x03,0x80,0x00,0x00},/*"o",79*/
{0x04,0x10,0x07,0xF0,0x04,0x50,0x04,0x40,0x03,0x80,0x00,0x00},/*"p",80*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x50,0x07,0xF0,0x00,0x10},/*"q",81*/
{0x04,0x40,0x07,0xC0,0x02,0x40,0x04,0x00,0x04,0x00,0x00,0x00},/*"r",82*/
{0x00,0x00,0x06,0x40,0x05,0x40,0x05,0x40,0x04,0xC0,0x00,0x00},/*"s",83*/
{0x00,0x00,0x04,0x00,0x1F,0x80,0x04,0x40,0x00,0x40,0x00,0x00},/*"t",84*/
{0x04,0x00,0x07,0x80,0x00,0x40,0x04,0x40,0x07,0xC0,0x00,0x40},/*"u",85*/
{0x04,0x00,0x07,0x00,0x04,0xC0,0x01,0x80,0x06,0x00,0x04,0x00},/*"v",86*/
{0x06,0x00,0x01,0xC0,0x07,0x00,0x01,0xC0,0x06,0x00,0x00,0x00},/*"w",87*/
{0x04,0x40,0x06,0xC0,0x01,0x00,0x06,0xC0,0x04,0x40,0x00,0x00},/*"x",88*/
{0x04,0x10,0x07,0x10,0x04,0xE0,0x01,0x80,0x06,0x00,0x04,0x00},/*"y",89*/
{0x00,0x00,0x04,0x40,0x05,0xC0,0x06,0x40,0x04,0x40,0x00,0x00},/*"z",90*/
{0x00,0x00,0x00,0x00,0x04,0x00,0x7B,0xE0,0x40,0x20,0x00,0x00},/*"{",91*/
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0x00},/*"|",92*/
{0x00,0x00,0x40,0x20,0x7B,0xE0,0x04,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
{0x40,0x00,0x80,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x40,0x00},/*"~",94*/
};
准备第一阶段:配置模拟I2C
搭配最好的程序,往往需要最朴素的方法,搭积木是我认为最好的方法,在搭积木之前,需要将积木造好,下面就是一个造积木的过程
- 用STM32CubeMX生成一个基本的程序,什么都不用配置,这个就不多说了,之前好像有写过
- 生成的是一个空白的程序,什么功能都没有,编译一下,确定不会报错再往下进行,第一步就是初始化需要模拟I2C的端口,我这里用的是HAL库对端口进行初始化的,如果有用大佬用寄存器操作,还请指导指导,对端口进行初始化是输出的必要操作,不论是简单的GPIO输出还是SPI、UART、I2C,都需要对端口进行初始化,这是最重要的一个积木
GPIO_InitTypeDef GPIO_InitStructure;
__HAL_RCC_GPIOB_CLK_ENABLE();
//GPIO初始化设置
GPIO_InitStructure.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;/*一般为开漏输出,推挽输出好像区别不大,不知道什么原因*/
GPIO_InitStructure.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
- 这里讲一下基本的I2C:Inter-Integrated Circuit是一个简单的通信总线,由时钟线SCL和数据线SDA,2根线组成,其中发送数据的步骤是主机先发送要通信的设备地址,后发送数据,时钟线一般由主机控制。
- 低电平从机发送数据,高电平主机接收数据,记住这个就可以编写程序了
- 从设备的地址一般使用7位的,每字节传输完成会有一个应答,也就是说每字节传输完成要做一个延时的操作,有需要的话需要做一个读取应答位的操作
主机给从机发送数据
- 主机发送I2C总线停止信号,防止总线忙写数据失败
- 主机发送I2C总线复位信号,确保写数据之前总线处于空闲状态
- 主机发送I2C总线开始信号,启动一次数据的写入
- 主机发送I2C丛机地址和写模式(W/R=0)信号,并且等待一个丛机的应答信号
- 主机接收到ACK的应答信号后,开始多个字节的写入,每写完一个字节需要等待一个丛机的应答信号
- 主机接收到ACK的应答信号后,发送I2C总线停止信号,确保总线处于空闲状态
主机接收从机数据
- 主机发送I2C总线停止信号,防止总线忙写数据失败
- 主机发送I2C总线复位信号,确保读数据之前总线处于空闲状态
- 主机发送I2C总线开始信号,启动一次数据读取
- 主机发送I2C丛机地址和读模式(W/R=1)信号,并且等待一个丛机的应答信号
- 主机接收到ACK的应答信号后,开始多个字节的读取,每读完一个字节需要给丛机发送一个ACK应答信号
- 主机接收到ACK的应答信号后,发送I2C总线停止信号,确保总线处于空闲状态
- 需要注意的是,总线上每增加一个设备就相当于扩大了总电容值
I2C起始条件
- 总线空闲状态时,SCL和SDA都保持着高电平
- SCL为高电平,SDA由高到低跳变,开始传输
I2C停止条件
- 总线忙碌状态时,SCL为高电平,SDA由低到高跳变,结束传输
I2C通讯
- 主设备往从设备中写入数据:起始条件 -> 从机地址 -> 0 -> 从机应答 -> 主机发数据 -> 从机应答 /不应答-> 停止条件
- 主设备从从设备中读取数据:起始条件 -> 从机地址 -> 1 -> 从机应答 -> 从机发数据 -> 主机应答 /不应答-> 停止条件
- 重启起始条件:起始条件 -> 从机地址 -> 读/写 -> 从机应答 -> 主/从机发数据 -> 从机应答 /不应答-> 重启起始条件 -> 从机地址 -> 读/写 -> 从机应答 /不应答 -> 停止条件
数据有效性
- 时钟为高电平时,数据传输,不能修改
- 时钟为低电平,数据修改,不能传输
- 为了方便操作,做以下的宏定义
#define OLED_CMD 0 //写命令
#define OLED_DATA 1 //写数据
typedef unsigned char u8;
typedef unsigned int u32;
#define OLED_SCLK_Clr() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET)//SCL
#define OLED_SCLK_Set() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET)
#define OLED_SDIN_Clr() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET)//DIN
#define OLED_SDIN_Set() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET)
I2C起始信号
//延时函数,HAL_Delay延时好慢,自己写个延时
void delay(UINT32 t)
{
while(t--);
}
//起始信号
void I2C_Start(void)
{
OLED_SDIN_Set();delay(1);
OLED_SCLK_Set();delay(1);
OLED_SDIN_Clr();delay(1);
OLED_SCLK_Clr();delay(1);
}
配置向端口中写入1字节数据
//端口写入一个字节
void Send_Byte(u8 dat)
{
u8 i;
for(i=0;i<8;i++)
{
OLED_SCLK_Clr();//将时钟信号设置为低电平
delay(1);
if(dat&0x80)//将dat的8位从最高位依次写入
{
OLED_SDIN_Set();delay(1);
}
else
{
OLED_SDIN_Clr();delay(1);
}
OLED_SCLK_Set();//将时钟信号设置为高电平
delay(1);
OLED_SCLK_Clr();//将时钟信号设置为低电平
delay(1);
dat<<=1;
}
}
模拟接受应答
- 既然是模拟的,就是假的,自己写成应答状态
//等待信号响应
void I2C_WaitAck(void) //测数据信号的电平
{
OLED_SCLK_Set();delay(1);
OLED_SCLK_Clr();delay(1);
}
I2C结束信号
//结束信号
void I2C_Stop(void)
{
OLED_SCLK_Set();delay(1);
OLED_SDIN_Clr();delay(1);
OLED_SDIN_Set();delay(1);
}
准备第二阶段:配置OLED操作
定义一个oled显存空间
//定义显示缓存,用数据
u8 OLED_GRAM[128][64];
向OLED发送命令:控制指令或者数据指令
//发送一个字节
//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 mode)
{
I2C_Start();
Send_Byte(0x78); //地址
I2C_WaitAck();
if(mode)
{
Send_Byte(0x40); //控制指令
}
else
{
Send_Byte(0x00);
}
I2C_WaitAck();
Send_Byte(dat);
I2C_WaitAck();
I2C_Stop();
}
更新缓存
//更新显存到OLED
void OLED_Refresh(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
OLED_WR_Byte(0x00,OLED_CMD); //设置低列起始地址
OLED_WR_Byte(0x10,OLED_CMD); //设置高列起始地址
for(n=0;n<128;n++)
OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
}
}
清屏
//清屏函数
void OLED_Clear(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
for(n=0;n<128;n++)
{
OLED_GRAM[n][i]=0;//清除所有数据
}
}
OLED_Refresh();//更新显示
}
画像素点
//画点
//x:0~127
//y:0~63
void OLED_DrawPoint(u8 x,u8 y)
{
u8 i,m,n;
i=y/8;
m=y%8;
n=1<<m;
OLED_GRAM[x][i]|=n;
}
清除像素点
//清除一个点
//x:0~127
//y:0~63
void OLED_ClearPoint(u8 x,u8 y)
{
u8 i,m,n;
i=y/8;
m=y%8;
n=1<<m;
OLED_GRAM[x][i]=~OLED_GRAM[x][i];
OLED_GRAM[x][i]|=n;
OLED_GRAM[x][i]=~OLED_GRAM[x][i];
}
显示一个字符
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//size:选择字体 12/16/24
//取模方式 逐列式
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1)
{
u8 i,m,temp,size2,chr1;
u8 y0=y;
size2=(size1/8+((size1%8)?1:0))*(size1/2); //得到字体一个字符对应点阵集所占的字节数
chr1=chr-' '; //计算偏移后的值
for(i=0;i<size2;i++)
{
if(size1==12)
{
temp = asc2_1206[chr1][i];
} //调用1206字体
else
return;
for(m=0;m<8;m++) //写入数据
{
if(temp&0x80)
{
OLED_DrawPoint(x,y);
}
else
{
OLED_ClearPoint(x,y);
}
temp<<=1;
y++;
if((y-y0)==size1)
{
y=y0;
x++;
break;
}
}
}
}
初始化oled
//OLED的初始化
void OLED_Init(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);
OLED_Clear();
}
搭积木
- 积木都创建好了,开始搭积木
包含头文件
#include "XXX.h"
这里的XXX.h就是上面所说的库文件,将上面的内容放到一个源文件中,并创建相应的库文件,这就好比将小积木组成一个大积木
初始化串口
//包含HAL库,
#include "stm32f401xe.h"
int main(void)
{
HAL_Init();
SystemClock_Config();
GPIO_InitTypeDef GPIO_InitStructure;
__HAL_RCC_GPIOB_CLK_ENABLE();
//GPIO初始化设置
GPIO_InitStructure.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;//OD;
GPIO_InitStructure.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
delay(200);
while(1)
{
}
}
初始化oled
int main(void)
{
HAL_Init();
SystemClock_Config();
GPIO_InitTypeDef GPIO_InitStructure;
__HAL_RCC_GPIOB_CLK_ENABLE();
//GPIO初始化设置
GPIO_InitStructure.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;//OD;
GPIO_InitStructure.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
delay(200);
OLED_Init();
while(1)
{
}
}
让oled显示字符
int main(void)
{
HAL_Init();
SystemClock_Config();
GPIO_InitTypeDef GPIO_InitStructure;
__HAL_RCC_GPIOB_CLK_ENABLE();
//GPIO初始化设置
GPIO_InitStructure.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;//OD;
GPIO_InitStructure.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
delay(200);
OLED_Init();
while(1)
{
OLED_ShowChar(0, 0, 'A' , 12);//显示ASCII字符
OLED_ShowChar(16, 16, 'B', 12);//显示ASCII字符
OLED_Refresh();
HAL_Delay(5000);
}
}
结语
写的很啰嗦,为了保持我这婴幼儿般的智商,也只能这么写,以后回过头来看,才不会忘记当初那年,我曾用过GOIO口模拟I2C驱动OLED了