本文使用芯片:STM32 F103 C8T6 最小系统板
从这个笔记开始,学习一下OLED的一些显示动画效果的实现,尝试自己能够做出一些接近实际产品的界面切换,动画效果设计~
文章提供源码,测试效果图,原理介绍,测试工程下载。
目录
OLED 基础知识学习:
滚动显示硬件支持:
初步设计思路:
构想与瑕疵:
下载测试:
横向滚动字幕程序设计:
滚动控制的OLED命令:
下载测试与注意点:
引脚接线:
测试工程下载:
对于OLED的显示基础以及基础代码,本文不讲,不了解的可以看以下文章:
STM32 F103C8T6学习笔记8:0.96寸单色OLED显示屏显示字符_NULL指向我的博客-CSDN博客
STM32 F103C8T6学习笔记9:0.96寸单色OLED显示屏—自由取模显示—显示汉字与图片_NULL指向我的博客-CSDN博客
有时OLED屏幕大小有限制,我们需要显示的句子长度可能超过了屏幕的长度,此时就需要滚动显示来解决,这样我们的句子显示长度在一定程度上会增长,但滚动显示字幕又有几个设计方案,不同的方案对应不同的使用场景,我们将会逐个学习。
我们可以从器件手册的FEATURES小节可以知道支不支持硬件滚动。SSD1306器件手册中FEATURES描述说明了它是支持滚动显示的,现在市面上许多0.96寸等OLED显示屏都是使用SSD1306驱动,支持滚动显示的。
我们先初步构想实现一下字幕滚动,本质是打印起点X或者Y坐标的增加,通过这个方式可以使打印起点不断变化,结合SSD1306支持的滚动显示以及合适时长的延时,从而实现滚动字幕,但实际是否如我们构想的那样呢,现在实践测试一下:
首先编写适当的字符串打印代码,如下:
//显示一个字符号串
void OLED_ShowString_2(u8 x,u8 y,u8 *chr,u8 Char_Size)
{
unsigned char j=0;
while (chr[j]!='\0') //循环打印直到字符串结尾
{
OLED_ShowChar(x,y,chr[j],Char_Size);//打印一个字符
x+=8;j++; //下标下移,打印下个字符
if(x>120){x=0;} //X不能超过120,否则会印在下一行
}
}
然后在主函数写上对应打印逻辑:
char buf[20]; //用于暂存oled数据
uint16_t choice,x,y;
int main(void)
{
init_ALL(); //初始化所有函数
while(1)
{
sprintf(buf,"Hello World");
OLED_ShowString_2(x,2,(u8 *)buf,16);
delay_ms(55); //延时55ms
x++; //X坐标增加
if(x>=128) {x=0;} //x坐标不超过128
}
}
下载测试发现基本的效果实现了,但文字刷新有拖尾现象,这是因为之前刷新过的区域没有被清除显示的原因。
其次我们将其改为长字符串,会发现显示更不正常了,因为长字符串本身显示占用就长于屏幕总长了,(此处将Hello World 改为 Welcome to my world),而我们选择滚动显示的原因就是想要在有限的长度显示更多的信息,这样编程显然达不到我们的需求~
其实SSD1306中有关于滚动控制的OLED命令如下:
它的一个重要配置是需要我们配置0~7页,哪些页需要滚动,这个只要设置起始与终止页即可,这样这俩页之间打印的内容就会滚动播放了,(注意:有些字符字母只占一页,但大部分汉字占俩页,一定要界定好!)
另一个配置就是设置滚动速度,这个填的越长,时间间隔就越大。
OLED_WR_Byte(0x2E,OLED_CMD); //关闭滚动
OLED_WR_Byte(0x26,OLED_CMD); //向右滚动,27则向左
OLED_WR_Byte(0x00,OLED_CMD); //虚拟字节 发送空字节 设置为0x00即可
OLED_WR_Byte(0x02,OLED_CMD); //起始页 这里为2
OLED_WR_Byte(0x07,OLED_CMD); //滚动速度 设置滚动步长的时间间隔, 帧为单位
OLED_WR_Byte(0x04,OLED_CMD); //终止页 这里为4(表示从页这开始不用滚动)
OLED_WR_Byte(0x00,OLED_CMD); //虚拟字节
OLED_WR_Byte(0xFF,OLED_CMD); //虚拟字节
OLED_WR_Byte(0x2F,OLED_CMD); //开启滚动
我们将其添加入程序:
这个滚动显示就是命令,一般只要设置好就行
char buf[20]; //用于暂存oled数据
uint16_t choice,x,y;
int main(void)
{
init_ALL(); //初始化所有函数
sprintf(buf,"Hello World ");
OLED_ShowString(0,2,(u8 *)buf,16);
delay_ms(5); //延时等显示稳定
OLED_WR_Byte(0x2E,OLED_CMD); //关闭滚动
OLED_WR_Byte(0x26,OLED_CMD); //向右滚动,27则向左
OLED_WR_Byte(0x00,OLED_CMD); //虚拟字节 发送空字节 设置为0x00即可
OLED_WR_Byte(0x02,OLED_CMD); //起始页 这里为2
OLED_WR_Byte(0x07,OLED_CMD); //滚动速度 设置滚动步长的时间间隔, 帧为单位
OLED_WR_Byte(0x04,OLED_CMD); //终止页 这里为4(表示从页这开始不用滚动)
OLED_WR_Byte(0x00,OLED_CMD); //虚拟字节
OLED_WR_Byte(0xFF,OLED_CMD); //虚拟字节
OLED_WR_Byte(0x2F,OLED_CMD); //开启滚动
while(1)
{
}
}
现在的效果正是我们需要的,并且不需要MCU一直刷新了,配置一次即可自动滚动,但经过我的测试,这种滚动显示,有以下注意点:
1.还是不能显示过长的字符串
2.起点横向的X坐标只能是0,过大会有显示错误
3.配置滚动之前,建议延时5ms先等显示稳定
因此这个SSD1306命令式的写法虽然方便好用,但也有限制,它的横向滚动设置,只能是0~~128这 个区间,不能设置成别的区间,比如我只想他在屏幕一半区域滚动~
SCL 接 PB6
SDA 接 PB7
//-----------------OLED IIC端口定义----------------
#define OLED_SCLK_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_6)//SCL
#define OLED_SCLK_Set() GPIO_SetBits(GPIOB,GPIO_Pin_6)
#define OLED_SDIN_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_7)//SDA
#define OLED_SDIN_Set() GPIO_SetBits(GPIOB,GPIO_Pin_7)
https://download.csdn.net/download/qq_64257614/88251719?spm=1001.2014.3001.5503