🍌
🍌🍌
作者简介:大家好啊,我叫DW,每天分享一些我新学到的知识,期待和大家一起进步
🍋
🍋🍋
系列专栏:STM32
🍎
🍎🍎
🍎🍎🍎
🌞小实验目标:在OLED上显示四句古诗🌞
🍊如有写得不好的地方欢迎大家指正🍊
创作时间:🍊🍊🍊2022年4月25日🍊🍊🍊
🍊🍊相关文章:
1 OLED简介
OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。
型号:OLED
点阵:128*64
外型尺寸:0.96寸
驱动芯片:SSD1306
工作电压:3.3V~5.0V
产品规格:PM-OLED
接口类型:SPI(🍌此处只有发送功能,没有接收功能🍌)
产品类别:图形点阵
产品颜色:黄绿膜,蓝屏,灰膜
SPI的定义
SPI(Serial Peripheral Interface)就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚。上升沿发送、下降沿接收、高位先发送。
🍌4 线 SPI 电路连接🍌
GND:电源地
VCC:3.3V
SCL(D0):CLK 时钟
SDA(D1):MOSI 数据端口
RES:RST复位
D/C:数据/命令引脚
CS:片选引脚
OLED液晶显示规则:
128*64点阵:64行,128列
8行128列为一页,既行:0-7,列:0-127为第一页,以此类推共8页
之后利用取模软件可以显示相关汉字。取模软件,取模标准如下:
2 SSD1306芯片
OLED用到的是SSD1306芯片,它包含着许多参数,下面容我一一道来。
2.1 基本指令
SSD1306芯片的指令挺多的,如果大家想进一步了解的话,请查看数据手册,下面我就简单介绍几种指令。
1.设置低列开始地址作为页地址模式(00h~0Fh)
2.设置高列开始地址作为页地址模式(10h~1Fh)
3.设置内存地址模式(20h)
SSD1306 中有三种不同的内存地址模式:页地址模式,水平地址模式,垂直地址模式。这个命令将内存地址模式设置成这三种中的一种。在这里 COL 的意思是图形显示数据 RAM 列。
🎵🎵三种模式的指令:
水平地址模式:0x00;
垂直地址模式:0x01;
页寻址地址模式:0x02(默认);
本例程用到的是页地址模式,我就简单介绍一下这个模式吧
在页地址模式下,在显示 RAM 读写之后,列地址指针自动加一。如果列地址指针达到了列的结束地址,列地址指针重置为列开始地址并且列地址指针不会改变。用户需要设置新的页和列地址来访问下一页 RAM 内从。也就是说,从第一页第一列开始取地址,一直取到第一页最后一列,之后需要用户自行设置下一页和列地址。取到页地址模式下 PAGE 和列地址指针的移动模式参考下图:
在正常显示数据 RAM 读或写和页地址模式,要求使用下面的步骤来定义开始 RAM 访问的位置:
(1)页寻址:通过命令 B0h 到 B7h 来设置目标显示位置的页开始地址
(2)列寻址:通过 00h~ 0Fh 来设置低开始列地址的指针 ;通过命令 10h~1Fh 来设置高开始列地址
本次用到的指令如下:
OLED_Write_Cmd_Data(CMD,0X20); //设置内存地址模式
OLED_Write_Cmd_Data(CMD,0X02); //水平:0x00;垂直:0x01;页寻址:0x02(默认);
OLED_Write_Cmd_Data(CMD,0XB0); //为页寻址模式设置页面开启地址0-7
OLED_Write_Cmd_Data(CMD,0X00); //设置低列地址
OLED_Write_Cmd_Data(CMD,0X10); //设置高列地址
比如说,如果页地址设置为 B2h,低列地址是 03h,高列地址为 00h,这句指令的意思是:设置的位置为第二页的低三列的高一列。那么就意味着开始列是PAGE2 的 SEG3.RAM 访问指针的位置如下图所示。输出数据字节将写到 RAM 列 3 的位置
4.设置显示开始行(40h~7Fh)
这个命令设置显示开始行寄存器来决定显示 RAM 的开始地址,通过选择 0 到 63 的值。当值为 0 时,RAM 行 0 映射到 COM0,当值为 1 时,RAM 行 1 映射到 COM0,以此类推。
OLED_Write_Cmd_Data(CMD,0X40); //设置显示开始行 0-63 0100 0000--0x40(0) 0111 1111--0x7f(63)
5.为 BANK0 设置对比度控制(81h)
这个命令用来设置显示的对比度,该芯片有 256 级对比度,从 00h 到 FFh。屏显输出电流随着对比度增大而增大。
OLED_Write_Cmd_Data(CMD,0XFF); //设置亮度调节,数值越大亮度越大
6.设置显示开、关(Aeh、AFh)
这个单字节命令用来打开或关闭 OLED 面板的显示。当显示是 ON,通过设置主机配置命令选择的电路会打开;
OLED_Write_Cmd_Data(CMD,(0XAF));//开起显示
OLED_Write_Cmd_Data(CMD,(0XAE));//关闭显示 全黑
好了,就说这么多指令吧,下面是这次用到的指令集
OLED_Write_Cmd_Data(CMD,0XA8); //设置分辨率
OLED_Write_Cmd_Data(CMD,0X3F); //默认0X3F:128*64 0x1f:128*32
OLED_Write_Cmd_Data(CMD,0XDA); // 设置硬件引脚配置,适应分辨率
OLED_Write_Cmd_Data(CMD,0X12); //0.96--128*64
OLED_Write_Cmd_Data(CMD,0XD3); //设置显示偏移
OLED_Write_Cmd_Data(CMD,0X00); //默认为0,没有偏移
OLED_Write_Cmd_Data(CMD,0X40); //设置显示开始:0-63
OLED_Write_Cmd_Data(CMD,0XA1); //段重定义设置,bit0:0,0->0;1,0->127;
OLED_Write_Cmd_Data(CMD,0X81); //对比度设置
OLED_Write_Cmd_Data(CMD,0XFF); //设置亮度调节,数值越大亮度越大
OLED_Write_Cmd_Data(CMD,0XA4); //输出遵循RAM内容
OLED_Write_Cmd_Data(CMD,0XA6); //设置显示方式;0xa7:反相显示; 0xa6:正常显示
OLED_Write_Cmd_Data(CMD,0XD5); //设置时钟分频因子,震荡频率
OLED_Write_Cmd_Data(CMD,0XF0); //设置分辨率值
OLED_Write_Cmd_Data(CMD,0X8D); //电荷泵设置
OLED_Write_Cmd_Data(CMD,0X14); // 0x14:允许在显示开启时候使用 0x10: 不允许
OLED_Write_Cmd_Data(CMD,0XAE); //0xAE:关闭显示 0XAF:开启显示
OLED_Write_Cmd_Data(CMD,0X20); //设置内存地址模式
OLED_Write_Cmd_Data(CMD,0X02); //水平:0x00 垂直:0x01 页寻址:0x02(默认)
OLED_Write_Cmd_Data(CMD,0XB0); //为页寻址模式设置页面开启地址0-7
OLED_Write_Cmd_Data(CMD,0XC8); //设置COM扫描方式0xC0上下反置左到右 0xc8:正常左到右
OLED_Write_Cmd_Data(CMD,0X00); //设置低列地址
OLED_Write_Cmd_Data(CMD,0X10); //设置高列地址
OLED_Write_Cmd_Data(CMD,0X40); //设置显示开始行 0-63
OLED_Write_Cmd_Data(CMD,0XD9); //设置预充电周期
OLED_Write_Cmd_Data(CMD,0X22); //充电时间
OLED_Write_Cmd_Data(CMD,0XDB); //设置选择取消级别
OLED_Write_Cmd_Data(CMD,0X20); //默认0x20
OLED_Write_Cmd_Data(CMD,0XAF); //开启显示
2.2 4线SPI写操作时序图
🍌时序图解析🍌
写一个字节操作:
(1)先将片选信号CS拉低
(2)一个字节对应八位数据,需要一位一位传送,一个时钟信号SCLK(D0)可以发送一位(此时需要将D0拉高在拉低),如此循环8次就发送完一个字节。
(3)发送完毕后再将CS拉高,释放总线
//写一个字节的操作
void OLED_Write_Byte(u8 byte)
{
CS_LOW;
for(u8 i=0;i<8;i++)
{
((byte<<i)&0x80) ? D1_HIGH:D1_LOW;// 高位写1,低位写0
D0_LOW;
delay_us(5);
D0_HIGH;
delay_us(5);
}
CS_HIGH;//释放总线
}
2.3 写指令函数
🎵🎵 小提示
🍎DC 引脚(数据指令端口)🍎
0 :写指令
1 :写数据
写位操作函数
GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal)
第一个参数为GPIO
第二个参数为引脚
第三个参数为预处理状态
编写的写指令操作函数如下:
void OLED_Write_Cmd_Data(u8 cmd,u8 data){
GPIO_WriteBit(OLED_PROT,DC,(BitAction)(cmd)); // 0 指令 1 数据
OLED_Write_Byte(data);//调用写一个字节函数函数写数据
}
2.4 清屏函数
由于我们有8页,既64行128列;清屏时需要一页一页清除,每页为8行128列,利用两个for循环编写的清屏函数如下:
void OLED_Clear(void)
{
for(u8 i=0;i<8;i++)
{
OLED_Write_Cmd_Data(CMD,(0x40));//设置显示开始:0-63
OLED_Write_Cmd_Data(CMD,(0xb0|i));//
for(u8 j=0;j<8;j++) {
OLED_Write_Cmd_Data(DAT,(0x00));//0x00:熄灭
}
}
}
2.5 开关显示函数
可以控制OLED的亮和灭
//开启OLED显示
void OLED_Display_On(void)
{
OLED_Write_Cmd_Data(CMD,(0X8D));//电荷泵设置
OLED_Write_Cmd_Data(CMD,(0X24));//使能充电泵
OLED_Write_Cmd_Data(CMD,(0XAF));//显示
}
//关闭OLED显示
void OLED_Display_Off(void)
{
OLED_Write_Cmd_Data(CMD,(0X8D));//电荷泵设置
OLED_Write_Cmd_Data(CMD,(0X24));
OLED_Write_Cmd_Data(CMD,(0XAE));//关闭
}
2.6 汉字显示函数
先利用取模软件,把我们想在oled显示的文字进行字模提取。
第一步打开取模软件,点击参数设置,选择其他选项,之后选择纵向取模。
第二步,点击文字输入区,单击鼠标右键,选择字体,选择宋体,常规,12号大小。(此规格为16*16点阵)
第三步,把我们要显示的文字放入文字输入区,按下Ctrl+Enter键,之后选择C51取模方式。
取模后得到的汉字点阵如下图:
第四步,编写显示中文函数,把取模后的点阵复制进一个新建的.c文件(不要放到头文件里,不然会报错)
由取模后的汉字点阵可以知道,每个字体高为2(high为2),宽度为16(wide为16)
因此我们可以编写如下函数:
//x:哪一行
//y:那一列
//high:多大的字
//wide:宽度
//data:数据
//显示字符函数
void OLED_Write_Chinese(u8 x,u8 y,u8 high,u8 wide,u8*data){
for(u8 i=0;i<high;i++){
//行显示位置
OLED_Write_Cmd_Data(CMD,(0Xb0|i)+x);
OLED_Write_Cmd_Data(CMD,0X10+(y>>4&0x0f));
//列显示
OLED_Write_Cmd_Data(CMD,y&0x0f);
//纵向取模设置
for(u8 j=0;j<wide;j++){
OLED_Write_Cmd_Data(DAT,*data++);
}
}
}
最后在main函数直接调用上面显示文字字符即可。
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "oled.h"
#include "word.c"
int main(void)
{
delay_init();
OLED_UserConfig();
OLED_Init();
OLED_Display_On();
//OLED_Display_Off();
while(1){
for(u8 i=0;i<8;i++){
OLED_Write_Chinese(0,i*16,2,16,(u8*)&word16x16[i]); //云想衣裳花想容,
OLED_Write_Chinese(2,i*16,2,16,(u8*)&word16x16[i+8]);//春风拂槛露华浓。
OLED_Write_Chinese(4,i*16,2,16,(u8*)&word16x16[i+16]);//若非群玉山头见,
OLED_Write_Chinese(6,i*16,2,16,(u8*)&word16x16[i+24]);//会向瑶台月下逢。
}
}
}
解析:
OLED_Write_Chinese(u8 x,u8 y,u8 high,u8 wide,u8*data)
OLED_Write_Chinese(0,i*16,2,16,(u8*)&word16x16[i]); //云想衣裳花想容,
由于一个汉字占用两页,故x的间隔为2,所以第一行,第二行,第三行,第四行的x为:0,2,4,6
一个汉字占用16列,故偏移地址为y=i * 16,则汉字不断往右移动
word16x16[i]:由于OLED有128列,我们取模的点阵问16*16(2行16列),故偏移地址为128/16=8,所以这四行的i就是:i,i+8,i+16,i+24
3.结语
今天的分享就到这里,希望能和大家一起进步,有什么疑问请留言,谢谢大家的耐心阅读,如果觉得有用的话给个👍👍👍
🌜🌜🌜本章结束,我们下一章见🌜🌜🌜
源码已上传,需要自取
这是我今天学习链接:
学习链接1