基于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电子工程世界,即时参与讨论电子工程世界最火话题,抢先知晓电子工程业界资讯。
评论
  • 百佳泰特为您整理2025年1月各大Logo的最新规格信息,本月有更新信息的logo有HDMI、Wi-Fi、Bluetooth、DisplayHDR、ClearMR、Intel EVO。HDMI®▶ 2025年1月6日,HDMI Forum, Inc. 宣布即将发布HDMI规范2.2版本。新规范将支持更高的分辨率和刷新率,并提供更多高质量选项。更快的96Gbps 带宽可满足数据密集型沉浸式和虚拟应用对传输的要求,如 AR/VR/MR、空间现实和光场显示,以及各种商业应用,如大型数字标牌、医疗成像和
    百佳泰测试实验室 2025-01-16 15:41 159浏览
  • 80,000人到访的国际大展上,艾迈斯欧司朗有哪些亮点?感未来,光无限。近日,在慕尼黑electronica 2024现场,ams OSRAM通过多款创新DEMO展示,以及数场前瞻洞察分享,全面展示自身融合传感器、发射器及集成电路技术,精准捕捉并呈现环境信息的卓越能力。同时,ams OSRAM通过展会期间与客户、用户等行业人士,以及媒体朋友的深度交流,向业界传达其以光电技术为笔、以创新为墨,书写智能未来的深度思考。electronica 2024electronica 2024构建了一个高度国际
    艾迈斯欧司朗 2025-01-16 20:45 146浏览
  • 故障现象 一辆2007款法拉利599 GTB车,搭载6.0 L V12自然吸气发动机(图1),累计行驶里程约为6万km。该车因发动机故障灯异常点亮进厂检修。 图1 发动机的布置 故障诊断接车后试车,发动机怠速轻微抖动,发动机故障灯长亮。用故障检测仪检测,发现发动机控制单元(NCM)中存储有故障代码“P0300 多缸失火”“P0309 气缸9失火”“P0307 气缸7失火”,初步判断发动机存在失火故障。考虑到该车使用年数较长,决定先使用虹科Pico汽车示波器进行相对压缩测试,以
    虹科Pico汽车示波器 2025-01-15 17:30 95浏览
  • 近期,智能家居领域Matter标准的制定者,全球最具影响力的科技联盟之一,连接标准联盟(Connectivity Standards Alliance,简称CSA)“利好”频出,不仅为智能家居领域的设备制造商们提供了更为快速便捷的Matter认证流程,而且苹果、三星与谷歌等智能家居平台厂商都表示会接纳CSA的Matter认证体系,并计划将其整合至各自的“Works with”项目中。那么,在本轮“利好”背景下,智能家居的设备制造商们该如何捉住机会,“掘金”万亿市场呢?重认证快通道计划,为家居设备
    华普微HOPERF 2025-01-16 10:22 176浏览
  • 随着智慧科技的快速发展,智能显示器的生态圈应用变得越来越丰富多元,智能显示器不仅仅是传统的显示设备,透过结合人工智能(AI)和语音助理,它还可以成为家庭、办公室和商业环境中的核心互动接口。提供多元且个性化的服务,如智能家居控制、影音串流拨放、实时信息显示等,极大提升了使用体验。此外,智能家居系统的整合能力也不容小觑,透过智能装置之间的无缝连接,形成了强大的多元应用生态圈。企业也利用智能显示器进行会议展示和多方远程合作,大大提高效率和互动性。Smart Display Ecosystem示意图,作
    百佳泰测试实验室 2025-01-16 15:37 172浏览
  • 全球领先的光学解决方案供应商艾迈斯欧司朗(SIX:AMS)近日宣布,与汽车技术领先者法雷奥合作,采用创新的开放系统协议(OSP)技术,旨在改变汽车内饰照明方式,革新汽车行业座舱照明理念。结合艾迈斯欧司朗开创性的OSIRE® E3731i智能LED和法雷奥的动态环境照明系统,两家公司将为车辆内饰设计和功能设立一套全新标准。汽车内饰照明的作用日益凸显,座舱设计的主流趋势应满足终端用户的需求:即易于使用、个性化,并能提供符合用户生活方式的清晰信息。因此,动态环境照明带来了众多新机遇。智能LED的应用已
    艾迈斯欧司朗 2025-01-15 19:00 78浏览
  • 电竞鼠标应用环境与客户需求电竞行业近年来发展迅速,「鼠标延迟」已成为决定游戏体验与比赛结果的关键因素。从技术角度来看,传统鼠标的延迟大约为20毫秒,入门级电竞鼠标通常为5毫秒,而高阶电竞鼠标的延迟可降低至仅2毫秒。这些差异看似微小,但在竞技激烈的游戏中,尤其在对反应和速度要求极高的场景中,每一毫秒的优化都可能带来致胜的优势。电竞比赛的普及促使玩家更加渴望降低鼠标延迟以提升竞技表现。他们希望通过精确的测试,了解不同操作系统与设定对延迟的具体影响,并寻求最佳配置方案来获得竞技优势。这样的需求推动市场
    百佳泰测试实验室 2025-01-16 15:45 238浏览
  • 食物浪费已成为全球亟待解决的严峻挑战,并对环境和经济造成了重大影响。最新统计数据显示,全球高达三分之一的粮食在生产过程中损失或被无谓浪费,这不仅导致了资源消耗,还加剧了温室气体排放,并带来了巨大经济损失。全球领先的光学解决方案供应商艾迈斯欧司朗(SIX:AMS)近日宣布,艾迈斯欧司朗基于AS7341多光谱传感器开发的创新应用来解决食物浪费这一全球性难题。其多光谱传感解决方案为农业与食品行业带来深远变革,该技术通过精确判定最佳收获时机,提升质量控制水平,并在整个供应链中有效减少浪费。 在2024
    艾迈斯欧司朗 2025-01-14 18:45 136浏览
  • 一个易用且轻量化的UI可以大大提高用户的使用效率和满意度——通过快速启动、直观操作和及时反馈,帮助用户快速上手并高效完成任务;轻量化设计则可以减少资源占用,提升启动和运行速度,增强产品竞争力。LVGL(Light and Versatile Graphics Library)是一个免费开源的图形库,专为嵌入式系统设计。它以轻量级、高效和易于使用而著称,支持多种屏幕分辨率和硬件配置,并提供了丰富的GUI组件,能够帮助开发者轻松构建出美观且功能强大的用户界面。近期,飞凌嵌入式为基于NXP i.MX9
    飞凌嵌入式 2025-01-16 13:15 199浏览
  • 晶台光耦KL817和KL3053在小家电产品(如微波炉等)辅助电源中的广泛应用。具备小功率、高性能、高度集成以及低待机功耗的特点,同时支持宽输入电压范围。▲光耦在实物应用中的产品图其一次侧集成了交流电压过零检测与信号输出功能,该功能产生的过零信号可用于精确控制继电器、可控硅等器件的过零开关动作,从而有效减小开关应力,显著提升器件的使用寿命。通过高度的集成化和先进的控制技术,该电源大幅减少了所需的外围器件数量,不仅降低了系统成本和体积,还进一步增强了整体的可靠性。▲电路示意图该电路的过零检测信号由
    晶台光耦 2025-01-16 10:12 97浏览
  • 日前,商务部等部门办公厅印发《手机、平板、智能手表(手环)购新补贴实施方案》明确,个人消费者购买手机、平板、智能手表(手环)3类数码产品(单件销售价格不超过6000元),可享受购新补贴。每人每类可补贴1件,每件补贴比例为减去生产、流通环节及移动运营商所有优惠后最终销售价格的15%,每件最高不超过500元。目前,京东已经做好了承接手机、平板等数码产品国补优惠的落地准备工作,未来随着各省市关于手机、平板等品类的国补开启,京东将第一时间率先上线,满足消费者的换新升级需求。为保障国补的真实有效发放,基于
    华尔街科技眼 2025-01-17 10:44 129浏览
  • 随着消费者对汽车驾乘体验的要求不断攀升,汽车照明系统作为确保道路安全、提升驾驶体验以及实现车辆与环境交互的重要组成,日益受到业界的高度重视。近日,2024 DVN(上海)国际汽车照明研讨会圆满落幕。作为照明与传感创新的全球领导者,艾迈斯欧司朗受邀参与主题演讲,并现场展示了其多项前沿技术。本届研讨会汇聚来自全球各地400余名汽车、照明、光源及Tier 2供应商的专业人士及专家共聚一堂。在研讨会第一环节中,艾迈斯欧司朗系统解决方案工程副总裁 Joachim Reill以深厚的专业素养,主持该环节多位
    艾迈斯欧司朗 2025-01-16 20:51 109浏览
  • 实用性高值得收藏!! (时源芯微)时源专注于EMC整改与服务,配备完整器件 TVS全称Transient Voltage Suppre,亦称TVS管、瞬态抑制二极管等,有单向和双向之分。单向TVS 一般应用于直流供电电路,双向TVS 应用于电压交变的电路。在直流电路的应用中,TVS被并联接入电路中。在电路处于正常运行状态时,TVS会保持截止状态,从而不对电路的正常工作产生任何影响。然而,一旦电路中出现异常的过电压,并且这个电压达到TVS的击穿阈值时,TVS的状态就会
    时源芯微 2025-01-16 14:23 152浏览
  • 数字隔离芯片是现代电气工程师在进行电路设计时所必须考虑的一种电子元件,主要用于保护低压控制电路中敏感电子设备的稳定运行与操作人员的人身安全。其不仅能隔离两个或多个高低压回路之间的电气联系,还能防止漏电流、共模噪声与浪涌等干扰信号的传播,有效增强电路间信号传输的抗干扰能力,同时提升电子系统的电磁兼容性与通信稳定性。容耦隔离芯片的典型应用原理图值得一提的是,在电子电路中引入隔离措施会带来传输延迟、功耗增加、成本增加与尺寸增加等问题,而数字隔离芯片的目标就是尽可能消除这些不利影响,同时满足安全法规的要
    华普微HOPERF 2025-01-15 09:48 184浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦