【STM32标准库】【自制库】0.96寸OLED显示屏(SSD1306)(2)全屏动画显示
使用STM32F4系列驱动OLED显示屏的自制库
文章基于适用于STM32F4系列,作者使用STM32F401CCU6开发板。
本文章基于此系列和开发板展开讨论。
本系列以SSD1306为主控芯片的I2C接口的0.96寸OLED屏幕为例介绍
内容较多,分节进行
链接
需求分析
在这一节中我们制作一个动画
动画的本质是一张张的图片间隔指定的时间投放到屏幕上,利用视觉暂留效应即可看到流畅的动画了
- 取模
- 显示图片
- 定时刷新
取模
因为网上没有找到可以批量取模的软件(一个几秒的动画就有几十上百张图片),因此我使用python写了个程序用于批量取模
没有python基础的可以直接使用
import cv2 as cv
import numpy as np
sl=50#数量
h=64#行数
l=128#列数
yz=140#阈值
sl=sl+1
def threshold_image(image,a):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
#cv.imshow('origin', gray)
ret, binary = cv.threshold(gray, yz, 255, cv.THRESH_BINARY)# 自定义阈值为150,大于150的是白色 小于的是黑色
#cv.imwrite("./1/"+str(a)+".bmp",binary)#输出
#cv.imshow('origin',binary)#调试用
#cv.waitKey(0)
return binary
for a in range(1,sl):
src = cv.imread(r"C:\Users\HZ1213825\Desktop\1\ ("+str(a)+").jpg")
zj=threshold_image(src,str(a))
tst=np.asarray(zj)
np.set_printoptions(threshold=np.inf)
js=0
txt="\nconst uint8_t t"+str(a)+"[128][8]=\n{"
# 取反用
# for i in range(h):
# for j in range(l):
# if tst[i][j] == 255:
# tst[i][j]=0
# elif tst[i][j]==0:
# tst[i][j]=1
# 不取反用
for i in range(h):
for j in range(l):
if tst[i][j] == 255:
tst[i][j]=1
elif tst[i][j]==0:
tst[i][j]=0
t=0
for i in range(0,h,8):
for j in range(l):
js=0
for z in range(0,8):
js=js*2+tst[i+7-z][j]
txt+=str(hex(js))+","
t+=1
if t==16:
txt+="\n"
t=0
txt=txt.rstrip(",")
txt+="};"
#print(tst)
with open("1.txt","a") as fp:
fp.write(txt)
print("t"+str(a)+',',end="")
需要做一些前期准备,请使用pr将视频剪裁为128 * 64像素,并导出为JPG格式
pr操作
修改大小
导入媒体,双击或拖入都行
拖入工作区创建序列
进入序列设置
更改视频大小
更改视频位置和缩放
加入黑白效果(在效果的视频效果的图形设置里)(将这个黑白拖到视频上就行了)
导出
设置为导出Jpe序列
python操作
将导出的图片批量重命名(全选,重命名)
然后把名字删除,之后回车即可(别删后缀名)
打开python,将代码复制进去
设置图片序列的地址和名字
修改数量和阈值
可以将这两行代码前的#删除(取消注释),来观察阈值是否正确
这是测试(调阈值)的效果
在控制台将取模的数组名打印了出来,方便后续操作
在程序的同级目录有输出文件(1.txt)
已经将前缀和后缀写入了,直接复制到Keil工程中即可
这是软件链接:
CSDN
链接:百度网盘
提取码:c95i
显示动画
上文说过,动画就是一帧帧的图片间隔一段时间播放做成的
前期准备
为了更方便的将动画刷新,我建立一个结构体
其内部的参数是二维数组指针
头文件(OLED.H)
typedef struct
{
uc8 (*TDArray)[128];
} OLED_Animation_Array;
在后面可以申请一个结构体数组
uc8 t1[8][128]={};
uc8 t2[8][128]={};
uc8 t3[8][128]={};
OLED_Animation_Array a[3]={t1,t2,t3};
调用时就可以将其作为数组调用,可以进入循环中使用了,就像这样
for(int i=0;i<3;i++)
a[i].TDArray[2][2]=0;
动画帧发送
发送一张图片的函数只需要稍作修改即可移植过来
C文件(OLED.C)
//动画实现函数 Array:含每帧数据的结构体
void OLED_Animation_Ation(OLED_Animation_Array Array)
{
//使用水平寻址模式模式
OLED_Write_Ctrl_Start();
I2C_SendByte(0x20); //设置寻址模式 (0x00水平/0x01垂直/0x02页)
I2C_SendByte(0x00); //水平寻址模式
I2C_SendByte(0x21); //设置列地址
I2C_SendByte(0x00);
I2C_SendByte(0x7f);
I2C_SendByte(0x22); //设置页地址
I2C_SendByte(0x00);
I2C_SendByte(0x07);
I2C_End();
OLED_Write_Data_Start();
for (int i = 0; i < 8; i++) //扫描页
{
for (int j = 0; j < 128; j++) //扫描列
I2C_SendByte(Array.TDArray[i][j]);
}
I2C_End();
}
动画实现
只需要间隔时间调用上文提到的动画帧发送函数即可,封装为函数
C文件(OLED.C)
//动画刷新函数(有需要修改的值) Time:间隔时间单位ms Num:帧的数量
void OLED_Animation(int Time, int Num)
{
//这个需要修改,修改数组大小和内部值 将uc8 [128][8]的名字按顺序放入
OLED_Animation_Array ac[50] = {t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22, t23, t24, t25, t26, t27, t28, t29, t30, t31, t32, t33, t34, t35, t36, t37, t38, t39, t40, t41, t42, t43, t44, t45, t46, t47, t48, t49, t50};
OLED_Clear();
for (int i = 1; i <= Num; i++)
{
OLED_Animation_Ation(ac[i - 1]);
Delay_ms(Time);
}
}
输入间隔时间和帧数量即可
成品
stm32控制OLED屏幕显示动画演示
链接:百度网盘
提取码:ierk
更多推荐
所有评论(0)