文章最后附源代码链接
一、OLED屏
1、各项模式配置
SSD1306单片机接口由8个数据引脚和5个控制引脚组成。不同接口模式下的引脚分配如表所示。在BS[2:0]引脚上通过硬件选择可设置不同的MCU模式。
2、通讯模式
通常我们所用的OLED屏有白色、蓝色、黄蓝双色等几种;屏的大小为0.96寸,像素点为128*64,所以我们也称之为0.96OLED屏或者12864屏。
内部驱动IC为SSD1306;通信方式一般为SPI或者I2C。如下图所示,配置哪种模式主要是根据BS0、BS1和BS2这三个管脚的电平逻辑来的。
①IIC模式:
电阻焊接R1、R4、R6、R7、R8。D1作为SCK时钟线,D0作为SDA数据线。SSD1306作为从机地址为0x78,DC脚作为更改从机地址引脚,DC接VCC,从机地址0x79,什么都不接地址为0x78。
发送数据:起始信号-从机地址-应答-写数据模式(0x40)-应答-数据(8bit)-结束信号
发送命令:起始信号-从机地址-应答-写命令模式(0x00)-应答-命令(8bit)-结束型号
②四线SPI模式:
电阻焊接R3、R4。D1作为SClk时钟线,D0作为MOSI线,CS为片选NSS,DC为数据/命令线、RES复位线。
发送数据:CS拉低-DC拉高-发送数据(8bit)-CS拉高
发送命令:CS拉低-DC拉低-发送命令(8bit)-CS拉高
③三线SPI模式:
电阻焊接R2,R3。D1作为SCLK时钟线,D0作为MOSI线,CS片选NSS,RES复位,DC拉低不用。数据有9位,首位就是数据/命令,因此不用DC线。
发送数据:CS拉低-首位为1再接着发送8位数据-CS拉高
发送命令:CS拉低-首位为0再接着发送8位命令-CS拉高
二、显示原理与取模方式
1、显示原理
OLED的显存分布情况。我们可以理解为:水平方向分布了128个像素点,垂直方向分布了64个像素点。而驱动芯片在点亮像素点的时候,是以8个像素点为单位的。官方的例程推荐的是垂直扫描的方式,也就是先画垂直方向的8个像素点(如下图所示),所以我们在画点的时候Y的取值为0-7,X的取值为0-127。页是芯片设计者为了方便将同一列的8个点阵编成一组,用一个8bit数表示,这样的8行128个数被称为1页。
2、取模方式
选择阴码、行列式(搭配页寻址模式)、逆向
三、OLED命令
1、命令的格式
①单级命令:直接发送一个命令就能设置OLED屏。
OLED_WriteCmd(0xAE); //关闭显示OLED_WriteCmd(0xA4); //设置整个显示打开/关闭OLED_WriteCmd(0xAF); //开启显示OLED_WriteCmd(0xA4); //设置整个显示打开/关闭
②多级命令:先发送一个命令,紧接着发送该命令的参数
OLED_WriteCmd(0x20); //打开寻址模式选择OLED_WriteCmd(0x02); //寻址模式选择页寻址模式
2、寻址模式设置命令
寻址模式命令:0x20
模式 |
命令 |
水平寻址模式 |
0x00 |
垂直寻址模式 |
0x01 |
页寻址模式 |
0x02 |
①页寻址模式(默认模式):
从设定的页和列开始发送数据,列地址自动累加,页地址不会更新,如果超出范围则超出部分无效,可以不用事先指定每页中每列的长度。
地址设置:
y是页地址的编号:
使用或命令将这低四位与固定前缀0xb连接起来(0xb0 | y)
x是列地址的编号:
发送高四位的程序,先使用与命令(&)取得x的高4位(x & 0xf0)之后向右移4位,将高4位数据放到低4位((x & 0xf0) >> 4)之后使用或命令(|)加上固定前缀0x1即可(((x & 0xf0) >> 4) | 0x10)
发送低四位命令因为地址低四位的高四位为0x0,因此只需要使用与命令(&)将高四位置零即可(x & 0x0f)
②水平寻址:
横向编码,列地址自动加,遇到设置范围的页尾时自动跳转到下一页,传输到设置范围的最后一页最后一列时自动复位。
地址设置:
OLED_WriteCmd(0x20) //寻址模式选择:(0x00水平/0x01垂直/0x02页)OLED_WriteCmd(0x00) //水平寻址模式OLED_WriteCmd(0x21) //设置列地址OLED_WriteCmd(0x00) //设置列起始位置OLED_WriteCmd(0x7F) //设置列终止位置OLED_WriteCmd(0x22) //设置页地址OLED_WriteCmd(0x00) //设置页起始位置OLED_WriteCmd(0x07) //设置页终止位置
③垂直寻址:
在垂直寻址模式下,当对显示内存进行读写操作后,页面地址指针自动加1。如果页地址指针到达页结束地址,则页地址指针重置为页开始地址,并且列地址指针加1。垂直寻址模式下页和列地址点的移动顺序如图所示。当列地址和页地址指针都到达结束地址时,指针被重定向到列的开始地址和通道的开始地址。
地址设置:
OLED_WriteCmd(0x20) //寻址模式选择:(0x00水平/0x01垂直/0x02页)OLED_WriteCmd(0x01) //垂直寻址模式OLED_WriteCmd(0x21) //设置列地址OLED_WriteCmd(0x00) //设置列起始位置OLED_WriteCmd(0x7F) //设置列终止位置OLED_WriteCmd(0x22) //设置页地址OLED_WriteCmd(0x00) //设置页起始位置OLED_WriteCmd(0x07) //设置页终止位置
3、基本命令
①对比度设置命令
进入对比度设置模式:0x81
之后输入对比度数值范围是0x00 - 0xFF(对比度实际上在这里就是设置发光部分的亮度,数值越大,亮度越大)
②显示开启/关闭
显示开启:0xA4
显示关闭:0xA5
③显示模式
阳码显示:0xA6
阴码显示:0xA7
④显示控制命令
关闭显示:0xAE
开启显示:0xAF
4、滚动命令
关闭滚动:0x2E(设置滚动参数前要先关闭滚动,防止RAM错乱)
开启滚动:0x2F
向右滚动:0x29
向左滚动:0x2a
A-F滚动参数配置,5个字节配置参数。
5、硬件配置(面板分辨率和布局相关)命令
①设置显示开始行
默认起始行:0x40
②设置列重映射(就是设置是否水平镜像)
将列地址0映射到SEG0:0xA0
将列地址127映射到SEG0:0xA1
设置左右方向,0xA1正常 0xA0左右反置
③设置多路复用率
开启多路复用率:0xA8
参数:A[5:0] 0到63配置参数。
④设置COM输出扫描方向
设置上下方向,0xC8正常 0xC0上下反置
⑤设置显示偏移量
开启显示偏移量:0xD3
参数:A[5:0] 垂直偏移量0-63
⑥设置COM引脚硬件配置
开启COM应交硬件配置;0xDA
参数:
A[4]=0b,顺序COM引脚配置
[4]=1b(RESET),可选COM引脚配置
A[5]=0b(RESET),禁用COM左右重映射
A[5]=1b,启用COM左右重映射
6、定时驱动方案设置命令
①设置显示时钟分频率/振荡器频率
开启命令:0xD5
参数A[7:0]:
A[3:0]:定义显示时钟(DCLK)的分割比(D):除比= A[3:0] + 1, RESET为0000b(除比= 1)
A[7:4]:设置振荡器频率,FOSC。振荡器频率随着A[7:4]的值增加,反之亦然。RESET为1000b范围:0000 ~ 1111 b频率随设定值增加而增加。
②设置预充电周期
开启命令:0xD9
参数A[7:0]:
A[3:0]:阶段1周期最多15个DCLK时钟,0是无效的条目(重置= 2h)
A[7:4]:阶段2周期最多15个DCLK时钟,0是无效的条目(重置= 2h)
③设置VCOMH取消选择级别
开启命令:0xDB
参数A[6:4]
④无操作命令
开启无操作:0xE3
四、代码
-
引脚初始化和OLED初始化配置
/*引脚配置*/
#define OLED_W_D0(x) GPIO_WriteBit(GPIOB, GPIO_Pin_12, (BitAction)(x))
#define OLED_W_D1(x) GPIO_WriteBit(GPIOB, GPIO_Pin_13, (BitAction)(x))
#define OLED_W_RES(x) GPIO_WriteBit(GPIOB, GPIO_Pin_14, (BitAction)(x))
#define OLED_W_DC(x) GPIO_WriteBit(GPIOB, GPIO_Pin_15, (BitAction)(x))
#define OLED_W_CS(x) GPIO_WriteBit(GPIOA, GPIO_Pin_8, (BitAction)(x))
/*引脚初始化*/
void OLED_SPI_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_Init(GPIOA, &GPIO_InitStructure);
OLED_W_D0(1);
OLED_W_D1(1);
OLED_W_RES(1);
OLED_W_DC(1);
OLED_W_CS(1);
}
void OLED_Init(void)
{
HAL_Delay(5);
SPI_Init();
OLED_WriteCmd(0xAE); //关闭显示
OLED_WriteCmd(0xD5); //设置显示时钟分频比/振荡器频率
OLED_WriteCmd(0x80);
OLED_WriteCmd(0xA8); //设置多路复用率
OLED_WriteCmd(0x3F);
OLED_WriteCmd(0xD3); //设置显示偏移
OLED_WriteCmd(0x00);
OLED_WriteCmd(0x40); //设置显示开始行
OLED_WriteCmd(0xA1); //设置左右方向,0xA1正常 0xA0左右反置
OLED_WriteCmd(0xC8); //设置上下方向,0xC8正常 0xC0上下反置
OLED_WriteCmd(0xDA); //设置COM引脚硬件配置
OLED_WriteCmd(0x12);
OLED_WriteCmd(0x81); //设置对比度控制
OLED_WriteCmd(0xCF);
OLED_WriteCmd(0xD9); //设置预充电周期
OLED_WriteCmd(0xF1);
OLED_WriteCmd(0xDB); //设置VCOMH取消选择级别
OLED_WriteCmd(0x30);
OLED_WriteCmd(0xA4); //设置整个显示打开/关闭
OLED_WriteCmd(0xA6); //设置正常/倒转显示
OLED_WriteCmd(0x8D); //设置充电泵
OLED_WriteCmd(0x14);
OLED_WriteCmd(0xAF); //开启显示
OLED_Clear(); //OLED清屏
}
2、显示功能代码(部分)
/**
* @brief SPI发送一个字节
* @param Byte 要发送的一个字节
* @retval 无
*/
void OLED_SPI_SendByte(uint8_t Byte)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
OLED_W_D0(0);
OLED_W_D1(Byte & (0x80 >> i));
OLED_W_D0(1);
}
}
/**
* @brief OLED写命令
* @param Command 要写入的命令
* @retval 无
*/
void OLED_WriteCmd(uint8_t Command)
{
OLED_W_CS(0);
OLED_W_DC(0);
OLED_SPI_SendByte(Command);
OLED_W_CS(1);
}
/**
* @brief OLED写数据
* @param Data 要写入的数据
* @retval 无
*/
void OLED_WriteData(uint8_t Data)
{
OLED_W_CS(0);
OLED_W_DC(1);
OLED_SPI_SendByte(Data);
OLED_W_CS(1);
}
/**
* @brief OLED设置光标位置
* @param Y 以左上角为原点,向下方向的坐标,范围:0~7
* @param X 以左上角为原点,向右方向的坐标,范围:0~127
* @retval 无
*/
void OLED_SetCursor(uint8_t Y, uint8_t X)
{
OLED_WriteCmd(0xB0 | Y); //设置Y位置
OLED_WriteCmd(0x10 | ((X & 0xF0) >> 4)); //设置X位置高4位
OLED_WriteCmd(0x00 | (X & 0x0F)); //设置X位置低4位
}
/**
* @brief OLED清屏
* @param 无
* @retval 无
*/
void OLED_Clear(void)
{
uint8_t i, j;
for (j = 0; j < 8; j++)
{
OLED_SetCursor(j, 0);
for(i = 0; i < 128; i++)
{
OLED_WriteData(0x00);
}
}
}
/**
* @brief OLED显示一个字符
* @param Line 行位置,范围:1~4
* @param Column 列位置,范围:1~16
* @param Char 要显示的一个字符,范围:ASCII可见字符
* @retval 无
*/
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
{
uint8_t i;
OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分
for (i = 0; i < 8; i++)
{
OLED_WriteData(OLED_F8x16[Char - ' '][i]); //显示上半部分内容
}
OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分
for (i = 0; i < 8; i++)
{
OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]); //显示下半部分内容
}
}
/**
* @brief OLED显示字符串
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param String 要显示的字符串,范围:ASCII可见字符
* @retval 无
*/
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i++)
{
OLED_ShowChar(Line, Column + i, String[i]);
}
}
/**
* @brief OLED显示汉字
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param No:要显示汉字的个数
* @param Length 要显示数字的长度,范围:1~16
* @retval 无
*/
void OLED_ShowChinese(uint8_t Line,uint8_t Column,uint8_t No)
{
uint8_t i;
OLED_SetCursor((Line-1)*2,(Column-1)*16);
for(i=0;i<16;i++)
{
OLED_WriteData(Chinese[2*No][i]);
}
OLED_SetCursor((Line-1)*2+1,(Column-1)*16);
for(i=0;i<16;i++)
{
OLED_WriteData(Chinese[2*No+1][i]);
}
}
/**
* @brief OLED显示图像
* @param Row1 起始行位置,范围:0~8
* @param Column1 起始列位置,范围:0~128
* @param Row2 终止行位置,范围:0~8
* @param Column2 终止列位置,范围:0~128
* @param BMP1:要显示gif的数组
* @retval 无
*/
void OLED_ShowBMP(uint8_t Row1, uint8_t Column1,uint8_t Row2, uint8_t Column2,uint8_t BMP1[])
{
unsigned int i=0;
unsigned char x,y;
// if(y1%8==0) y=y1/8;
// else y=y1/8+1;
for(x=Row1;x<Row2;x++)
{
OLED_SetCursor(x,Column1);
for(y=Column1;y<Column2;y++)
{
OLED_WriteData(BMP1[i++]);
}
}
}
3、滚动显示代码
void OLED_CloseRoll(void)
{
//以下添加水平滚动效果
OLED_WriteCmd(0x2e);//关滚动
OLED_WriteCmd(0x2a);//29向右,2a向左
OLED_WriteCmd(0x00);//A:空字节
OLED_WriteCmd(0x00);//B:水平起始页
OLED_WriteCmd(0x07);//C:水平滚动速度
OLED_WriteCmd(0x07);//D:水平结束页
OLED_WriteCmd(0x00);//E:每次垂直滚动位移
// OLED_WriteCmd(0x2f);//开滚动
}
void OLED_OpenRoll(void)
{
//以下添加水平滚动效果
OLED_WriteCmd(0x2f);//开滚动
}
源文件连接:
链接:https://pan.baidu.com/s/1xlNhgYBokVcr8njH9ntNjQ 文章来源:https://www.toymoban.com/news/detail-427742.html
提取码:xiao文章来源地址https://www.toymoban.com/news/detail-427742.html
到了这里,关于0.96寸OLED显示(7针款SPI)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!