基于51单片机的简易“视频播放器”

原创 电子工程世界 2022-07-05 07:30

前言

大概10年前,我在咱们EEWORLD论坛看到有人分享了用单片机在液晶屏上播放bad apple视频,当时觉得很有趣,但是奈何当时刚入门单片机,很多都不太懂,自己想做却不会做,只能作罢。如今,工作也好几年了,也不做嵌入式这一行。前段时间,趁着周末,工作也不太忙,突然想起这个事情了,于是从网上买了元器件,自己动手再实现这个功能,以弥补自己当年的遗憾,哈哈。


介绍

本文介绍在51单片机上,使用OLED12864(SSD1306)播放视频,并且使用蜂鸣器播放音乐。因为是gif的原因,看着会比较卡,实际上是不会有卡顿的,实际效果可以点击阅读原文看视频

最终的效果如下:

播放bad apple视频:



播放数码宝贝的视频:


 

使用到的主要元器件如下:

  • 国产51单片机:STC15F2K60S2

  • OLED显示屏:SSD1306,分辨率为128*64

  • 无源蜂鸣器,8550三极管等

 

原理图如下:

 

 


具体方案

由于视频文件比较大(MB级别),而51单片机的flash一般都比较小(KB级别),因此把视频文件直接存储在单片机内部显然是不行的。可以把视频文件存储在SD卡里面,然后单片机读取SD卡里面的内容;或者视频文件直接存储在电脑上,然后电脑通过串口实时发送视频数据给单片机,单片机实时显示视频画面。文本采用后者的方案。

 

OLED12864绘图

我们购买OLED12864(SSD1306)显示屏时,一般卖家都会提供51单片机的示例代码,或者网上也能找到很多相关的代码。


使用这些代码在整个屏幕上绘图时,发现刷新率比较低,在11.0592M时钟频率的情况下,实测大概只有8.6fps。测试方法如下:


  • void main()

  • {

  • for(;;)

  • {

  • p27 = ~p27;

  • oled_drawbmp(pic);

  • }

  • }



oled_drawbmp为卖家提供的绘图的函数,每次屏幕刷新一次,p27 IO口翻转一次。使用逻辑分析仪测试p27的电平变化如下,可以看到频率约为4.3Hz,那么屏幕的刷新率大概为8.6Hz(fps)。


  

 

因为我们的目的是使用单片机在这款显示屏上播放视频,而一般视频的帧率需要大于25fps,帧率过低就会有卡顿的感觉。显然,上面提到屏幕8.6Hz的刷新率是比较低的,因此我们需要做一些优化。


比较直观且容易的优化方式之一,就是提高时钟频率,把11.0592M提高到24M或者27M的时钟频率。


第二个优化方法就是优化绘图函数。先来看看iic的开始信号和结束信号的代码:


  • void iic_start() //开始iic

  • {

  • scl = 1;

  • sda = 1;

  • delay_5us();

  • sda = 0;

  • delay_5us();

  • scl = 0;

  • }

  • void iic_stop() //停止iic

  • {

  • scl = 0;

  • sda = 0;

  • scl = 1;

  • delay_5us();

  • sda = 1;

  • delay_5us();

  • }



可以看到,里面有一些延时5微妙(delay_5us),其实这个不是必须的,去掉这个延时,iic同样可以正常通信。因此,去掉这个延时,可以加快显示屏的刷新速率。

 

其次,我们再看看卖家提供绘图部分的函数:


  • /***********功能描述:显示显示BMP图片128×64起始点坐标(x,y)*****************/

  • void oled_drawbmp(unsigned char bmp[]) //画图

  • {

  • unsigned int j = 0;

  • unsigned char x, y;

  • for (y = 0; y < 8; y++)

  • {

  • oled_set_pos(0, y);

  • for (x = 0; x < 128; x++)

  • {

  • iic_writedata(bmp[j++]);

  • }

  • }

  • }



而iic_writedata的实现如下:


  • void iic_writedata(unsigned char iic_data) //写数据

  • {

  • iic_start();

  • write_byte(0x78);

  • write_byte(0x40);

  • write_byte(iic_data);

  • iic_stop();

  • }



可以看到,每写一次图像数据bmp[j],都会有一次iic开始与结束动作,也都会先发送两个控制指令(0x78, 0x40),这其实没有必要,优化后的函数如下:


  • // 快速绘制图像

  • void oled_drawbmp_fast(unsigned char BMP[])

  • {

  • unsigned int j = 0;

  • unsigned char x, y;

  • for (y = 0; y < 8; y++)

  • {

  • oled_set_pos(0, y);

  • iic_start();

  • write_byte(0x78);

  • write_byte(0x40);

  • for (x = 0; x < 128; x++)

  • {

  • write_byte(BMP[j++]);

  • }

  • iic_stop();

  • }

  • }



可以看到,上面的函数减少了启动iic、结束iic,减少了写控制命令(0x78, 0x40)。使用跟之前同样的测试方法,经过上述的优化,最终屏幕的刷新率如下:


 

上述的结果为,使用27M时钟频率,加上上面提到的几点优化,可以看出最终屏幕的刷新率约为34.5*2=69Hz(fps),这已经满足我们播放视频所需的屏幕刷新率了。

 

另外,再提一点,其实还可以进一步优化,使得屏幕刷新率达到100fps以上,测试结果如下。


 

视频转码成十六进制格式

单片机播放视频,我们需要将视频转码为单片机可以读取的十六进制数据。

首先我们需要将视频分解为一帧一帧的图像,然后可以用如下的取模软件获得图像的十六进制字模。

 

 

但是,由于视频的帧数比较多,我们一帧一帧手动的使用取模软件获取字模,显然是一个比较累的活。因此,我们可以写个python代码,批量生成每帧画面的十六进制数据。python代码如下:


  • import cv2


  • def bit2num(pixcels):

  •    output_val = 0

  •    for i, pix in enumerate(pixcels):

  •       if pix > 128: # 白色

  •          output_val += pow(2, i)

  •    return output_val


  • def main():

  •    video_path = 'BadApple.flv'

  •    cap = cv2.VideoCapture(video_path) # 打开视频

  •    cnt = 0

  •    fout = open('bad_apple_data.txt', 'w') #

  •    while True:

  •       ret, frame = cap.read()       # 一帧一帧的读取

  •       if not ret:

  •          break

  •       cnt += 1

  •       frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 转换为灰度的画面

  •       frame = cv2.resize(frame, (128, 64))  # 图像尺寸调整到128*64大小

  •       convert_val = []

  •       for row in range(0, 8):   # page0 ~ page7

  •          for col in range(0, 128): # seg0 ~ seg127

  •             cur_data = frame[row*8: row*8+8, col] # 取出对应的8个像素点

  •             convert_val.append(str(bit2num(cur_data))) # 转换成8位的数据

  •      

  •       fout.write("%s\n"%(','.join(convert_val)))


  •       # cv2.imshow("capture", frame)  #显示画面

  •       # if cv2.waitKey(30) & 0xff == ord('q'): #按q退出

  •       #    break


  • main()



代码比较简单,其中会调用OpenCV的库,用来读取视频以及视频画面对应的像素值。

 

串口发送

视频数据准备好之后,我们需要把视频数据通过串口发送给单片机,单片机接收到完整的一帧数据(一帧画面)之后,就可以开始显示画面。我们同样可以写个python代码来将视频数据发送给单片机,代码如下:


  • import serial  # 导入串口相关的库

  • from time import sleep


  • def get_bmp_data():

  •     filepath = 'bad_apple_data.txt'

  •     f = open(filepath)

  •     bmp_data = []

  •     for line in f:

  •         val = line.strip().split(',')

  •         if len(val) == 0:

  •             continue

  •         bmp_data.append([int(x) for x in val])

  •     f.close()

  •     return bmp_data


  • def main():

  •     com = serial.Serial('com10', 345600, timeout=10) # 设置端口号,波特率,超时时间

  •     if not com.isOpen():  # 判断端口是否打开成功

  •         raise "端口打开失败"


  •     bmp_data = get_bmp_data() # 读取刚刚生成的TXT文件

  •     for frame in bmp_data: # 一帧一帧的发送数据

  •         ret = com.write(bytes(frame)) # 将数据转换成二进制后发送

  •         sleep(0.03) # 延时适当时间


  • main()


代码比较简单,其中会调用串口相关的serial库,然后每次循环发送一帧数据,直至全部发送完成。

 

小结

最后,总结一下 在51单片机播放视频的大致流程:

  1. 视频解码成一帧帧的图像,然后再转码成显示屏可以显示的十六进制格式(这一步可以提前完成)

  2. 电脑通过串口把十六进制格式的视频数据发送给单片机

  3. 单片机接收到完整的一帧数据(一幅图像)后,显示屏开始显示画面

  4. 同时,蜂鸣器播放音乐(可选)。

推荐阅读

盘点特斯拉、大众、小鹏……的电子电气架构
手把手带你魔改一个带击杀音效的电蚊拍
拆一辆十万元的比亚迪“元”,看看里面都有哪些元器件
揭秘三星 3纳米 GAA 技术

添加微信回复“进群”

拉你进技术交流群!

国产芯|汽车电子|物联网|新能源|电源|工业|嵌入式…..  

众号内回复您想搜索的任意内容,如问题关键字、技术名词、bug代码等,就能轻松获得与之相关的专业技术内容反馈。快去试试吧!


如果您想经常看到我们的文章,可以进入我们的主页,点击屏幕右上角「三个小点」,点击「设为星标」。

欢迎扫码关注

电子工程世界 关注EEWORLD电子工程世界,即时参与讨论电子工程世界最火话题,抢先知晓电子工程业界资讯。
评论
  • 在智能化技术快速发展当下,图像数据的采集与处理逐渐成为自动驾驶、工业等领域的一项关键技术。高质量的图像数据采集与算法集成测试都是确保系统性能和可靠性的关键。随着技术的不断进步,对于图像数据的采集、处理和分析的需求日益增长,这不仅要求我们拥有高性能的相机硬件,还要求我们能够高效地集成和测试各种算法。我们探索了一种多源相机数据采集与算法集成测试方案,能够满足不同应用场景下对图像采集和算法测试的多样化需求,确保数据的准确性和算法的有效性。一、相机组成相机一般由镜头(Lens),图像传感器(Image
    康谋 2024-12-12 09:45 83浏览
  • 习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-12 10:13 50浏览
  • 应用环境与极具挑战性的测试需求在服务器制造领域里,系统整合测试(System Integration Test;SIT)是确保产品质量和性能的关键步骤。随着服务器系统的复杂性不断提升,包括:多种硬件组件、操作系统、虚拟化平台以及各种应用程序和服务的整合,服务器制造商面临着更有挑战性的测试需求。这些挑战主要体现在以下五个方面:1. 硬件和软件的高度整合:现代服务器通常包括多个处理器、内存模块、储存设备和网络接口。这些硬件组件必须与操作系统及应用软件无缝整合。SIT测试可以帮助制造商确保这些不同组件
    百佳泰测试实验室 2024-12-12 17:45 74浏览
  • 时源芯微——RE超标整机定位与解决详细流程一、 初步测量与问题确认使用专业的电磁辐射测量设备,对整机的辐射发射进行精确测量。确认是否存在RE超标问题,并记录超标频段和幅度。二、电缆检查与处理若存在信号电缆:步骤一:拔掉所有信号电缆,仅保留电源线,再次测量整机的辐射发射。若测量合格:判定问题出在信号电缆上,可能是电缆的共模电流导致。逐一连接信号电缆,每次连接后测量,定位具体哪根电缆或接口导致超标。对问题电缆进行处理,如加共模扼流圈、滤波器,或优化电缆布局和屏蔽。重新连接所有电缆,再次测量
    时源芯微 2024-12-11 17:11 115浏览
  • 习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-11 17:58 88浏览
  • RK3506 是瑞芯微推出的MPU产品,芯片制程为22nm,定位于轻量级、低成本解决方案。该MPU具有低功耗、外设接口丰富、实时性高的特点,适合用多种工商业场景。本文将基于RK3506的设计特点,为大家分析其应用场景。RK3506核心板主要分为三个型号,各型号间的区别如下图:​图 1  RK3506核心板处理器型号场景1:显示HMIRK3506核心板显示接口支持RGB、MIPI、QSPI输出,且支持2D图形加速,轻松运行QT、LVGL等GUI,最快3S内开
    万象奥科 2024-12-11 15:42 88浏览
  • 一、SAE J1939协议概述SAE J1939协议是由美国汽车工程师协会(SAE,Society of Automotive Engineers)定义的一种用于重型车辆和工业设备中的通信协议,主要应用于车辆和设备之间的实时数据交换。J1939基于CAN(Controller Area Network)总线技术,使用29bit的扩展标识符和扩展数据帧,CAN通信速率为250Kbps,用于车载电子控制单元(ECU)之间的通信和控制。小北同学在之前也对J1939协议做过扫盲科普【科普系列】SAE J
    北汇信息 2024-12-11 15:45 115浏览
  • 本文介绍瑞芯微RK3588主板/开发板Android12系统下,APK签名文件生成方法。触觉智能EVB3588开发板演示,搭载了瑞芯微RK3588芯片,该开发板是核心板加底板设计,音视频接口、通信接口等各类接口一应俱全,可帮助企业提高产品开发效率,缩短上市时间,降低成本和设计风险。工具准备下载Keytool-ImportKeyPair工具在源码:build/target/product/security/系统初始签名文件目录中,将以下三个文件拷贝出来:platform.pem;platform.
    Industio_触觉智能 2024-12-12 10:27 81浏览
  • 全球智能电视时代来临这年头若是消费者想随意地从各个通路中选购电视时,不难发现目前市场上的产品都已是具有智能联网功能的智能电视了,可以宣告智能电视的普及时代已到临!Google从2021年开始大力推广Google TV(即原Android TV的升级版),其他各大品牌商也都跟进推出搭载Google TV操作系统的机种,除了Google TV外,LG、Samsung、Panasonic等大厂牌也开发出自家的智能电视平台,可以看出各家业者都一致地看好这块大饼。智能电视的Wi-Fi连线怎么消失了?智能电
    百佳泰测试实验室 2024-12-12 17:33 66浏览
  • 天问Block和Mixly是两个不同的编程工具,分别在单片机开发和教育编程领域有各自的应用。以下是对它们的详细比较: 基本定义 天问Block:天问Block是一个基于区块链技术的数字身份验证和数据交换平台。它的目标是为用户提供一个安全、去中心化、可信任的数字身份验证和数据交换解决方案。 Mixly:Mixly是一款由北京师范大学教育学部创客教育实验室开发的图形化编程软件,旨在为初学者提供一个易于学习和使用的Arduino编程环境。 主要功能 天问Block:支持STC全系列8位单片机,32位
    丙丁先生 2024-12-11 13:15 71浏览
  • 铁氧体芯片是一种基于铁氧体磁性材料制成的芯片,在通信、传感器、储能等领域有着广泛的应用。铁氧体磁性材料能够通过外加磁场调控其导电性质和反射性质,因此在信号处理和传感器技术方面有着独特的优势。以下是对半导体划片机在铁氧体划切领域应用的详细阐述: 一、半导体划片机的工作原理与特点半导体划片机是一种使用刀片或通过激光等方式高精度切割被加工物的装置,是半导体后道封测中晶圆切割和WLP切割环节的关键设备。它结合了水气电、空气静压高速主轴、精密机械传动、传感器及自动化控制等先进技术,具有高精度、高
    博捷芯划片机 2024-12-12 09:16 87浏览
  • 首先在gitee上打个广告:ad5d2f3b647444a88b6f7f9555fd681f.mp4 · 丙丁先生/香河英茂工作室中国 - Gitee.com丙丁先生 (mr-bingding) - Gitee.com2024年对我来说是充满挑战和机遇的一年。在这一年里,我不仅进行了多个开发板的测评,还尝试了多种不同的项目和技术。今天,我想分享一下这一年的故事,希望能给大家带来一些启发和乐趣。 年初的时候,我开始对各种开发板进行测评。从STM32WBA55CG到瑞萨、平头哥和平海的开发板,我都
    丙丁先生 2024-12-11 20:14 78浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦