本文主要是介绍基于STM32F4xx利用串口播放视频(OLED),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
效果视频 : 基于STM32F11的1.3寸OLED屏_驱动芯片SH1106_哔哩哔哩_bilibili
该屏幕用硬件SPI进行驱动的。买屏幕时商家都会提供驱动源码,显示文字,数字等的应该都没问题。我这次主要讲如何显示视频,我的图片显示和文字数字显示是自己写的(也可以私信我获取,但是显示速度没源码快)。
stm32单片机内存不够大,一个视频可能就几M了,完全放不下。视频其实也就一帧一帧照片组合而成,我们会了一张图片的显示也就会了视频的播放了(循环发送图片信息再刷新屏幕显示)。
接下来 我会把视频播放的步骤说一遍 (工具可以到下面网盘链接下载)
第一步骤:视频的图片捕获
随便下载一个比较长时间的gif 把它后缀改成.mp4用KMPlayer.exe打开
打开后如下右键屏幕 高级捕获
先暂停视频,再点击上图开始按钮,然后点击播放视频。你会发现在你上面的文件夹下面出现一堆bmp图片。
第二步骤:把bmp图片转换成单片机需要的格式
打开这个工具Img2Lcd.exe 配置弄成下图
再打开第一张bmp
批量转换
选择是 随后就生产很多.ebm文件
这一步就是生成每个图片的ebm格式的内容了,你可以直接用串口发送这个文件 此时屏幕显示的图片就发生变化了。当然前提是你已经把串口接收写好,我用了dma 接收一张图片信息(大概1000多个字节)到了再中断。
所以单片机DMA中断然后就可以显示一张图片了。
为了连续发送所有的ebm文件我用了python 把文件结合一起,上图end.ebm就是python生成的文件。 下面是python的代码 需要下载python编译器不然运行不起来。
import time
import serial
import osdef gain_datas_true():meragefiledir = "C:/KMPlayer/Capture/1/batch" #文件路径docList = os.listdir(meragefiledir) # 将文件下的 文件名存入到 list 中docList.sort() # 对文件名进行排序print(docList)fname = open("C:/KMPlayer/Capture/1/batch/end.ebm", "wb") # 打开end.ebm文件 没有自动创建for i in docList:x = open('C:/KMPlayer/Capture/1/batch/' + i, "rb") # 打开列表中的文件,读取文件内容fname.write(x.read()) # 写入新建的fname文件中x.close()fname.close()def main():gain_datas_true()if __name__ == '__main__':main()
生成后就完成了,然后直接串口发送就好了,下面是单片机的串口与DMA代码。标准库函数开发
usart.c
#include "usart.h"
#include <stdio.h>//------------------------------------------------修改以下宏定义可以配置相应的串口初始化----------------------------------------------------
#define USART_TX GPIO_Pin_9 //串口GPIO发送端口
#define USART_RX GPIO_Pin_10 //串口GPIO接收端口#define USART_GPIO_TypeDef GPIOA //串口对应的GPIO位置#define USART_Pin_TX GPIO_PinSource9 //串口映射发送的GPIO
#define USART_Pin_RX GPIO_PinSource10 //串口映射读取的GPIO#define USART_RCC RCC_APB2Periph_USART1 // 注意串口1/6 是APB2总线 其它是APB1总线
#define USART_GPIO_RCC RCC_AHB1Periph_GPIOA //串口对应的GPIO总线#define USART_IRQ USART1_IRQn //串口 中断号
#define USART USART1 //串口号
//------------------------------------------------修改以上宏定义可以配置相应的串口初始化----------------------------------------------------
/*
函数功能:初始化串口1
函数参数:uint32_t USART_BaudRate
函数返回值:无
函数描述:无
*/
void Usart1_Init(uint32_t USART_BaudRate)
{GPIO_InitTypeDef GPIO_InitStruct; //串口GPIO结构体定义USART_InitTypeDef USART_InitStruct; //串口结构体定义RCC_APB2PeriphClockCmd(USART_RCC,ENABLE); //使能串口外设的线 注意串口1/6 是APB2总线 其它是APB1总线RCC_AHB1PeriphClockCmd(USART_GPIO_RCC,ENABLE); //使能串口对应的GPIO线GPIO_PinAFConfig(USART_GPIO_TypeDef,USART_Pin_TX,GPIO_AF_USART1); //串口发送复用映射GPIO_PinAFConfig(USART_GPIO_TypeDef,USART_Pin_RX,GPIO_AF_USART1); //串口接收复用映射GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;GPIO_InitStruct.GPIO_Pin = USART_TX | USART_RX;GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;GPIO_Init(USART_GPIO_TypeDef,&GPIO_InitStruct); //串口 发送/接受端口初始化USART_InitStruct.USART_BaudRate = USART_BaudRate;USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_InitStruct.USART_Parity = USART_Parity_No;USART_InitStruct.USART_StopBits = USART_StopBits_1;USART_InitStruct.USART_WordLength = USART_WordLength_8b;USART_Init(USART,&USART_InitStruct); //串口初始化USART_ReceiveData(USART); //初始化时候读取一次避免 一开始就有中断USART_DMACmd(USART,USART_DMAReq_Rx,ENABLE); //读取中断配置USART_Cmd(USART,ENABLE);
}/*
函数功能:printf函数重定向
函数参数:无
函数返回值:无
函数描述:无
*/
int fputc(int ch, FILE * f)
{USART->DR = (unsigned char)ch; //USART是上面宏定义的 哪个串口初始化就打印那个串口while((USART->SR & 0x80) == 0); return ch;
}
//------------------------------------------------某个串口初始化和打印完成----------------------------------------------------
usart.h
#ifndef _USART_H_
#define _USART_H_#include "stm32f4xx.h"void Usart1_Init(uint32_t USART_BaudRate);#endif
dma.c
#include "dma.h"/*
函数功能:DMA2初始化
函数参数:无
函数返回值:无
函数描述:DMA2 通道4 不用缓冲FIFO
*/
void Dma2Init(uint32_t DMA_Memory0BaseAddr,uint32_t DMA_PeripheralBaseAddr,uint32_t DMA_BufferSize)
{NVIC_InitTypeDef NVIC_InitStruct; //总中断结构体定义DMA_InitTypeDef DMA_InitStruct;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);DMA_InitStruct.DMA_BufferSize = DMA_BufferSize;DMA_InitStruct.DMA_Channel = DMA_Channel_4;DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory;DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;DMA_InitStruct.DMA_Memory0BaseAddr = DMA_Memory0BaseAddr;DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;DMA_InitStruct.DMA_PeripheralBaseAddr = DMA_PeripheralBaseAddr;DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStruct.DMA_Priority = DMA_Priority_VeryHigh;DMA_Init(DMA2_Stream2,&DMA_InitStruct);DMA_ITConfig(DMA2_Stream2,DMA_IT_TC,ENABLE);NVIC_InitStruct.NVIC_IRQChannel = DMA2_Stream2_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStruct); //DMA总中断初始化DMA_Cmd(DMA2_Stream2,ENABLE);
}
dma.h
#ifndef _DMA_H_
#define _DMA_H_#include "stm32f4xx.h"void Dma2Init(uint32_t DMA_Memory0BaseAddr,uint32_t DMA_PeripheralBaseAddr,uint32_t DMA_BufferSize);#endif
主函数中你需要 以下函数
unsigned char UsartData[1056];
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级配置
Usart1_Init(115200); //串口初始化
Dma2Init((uint32_t)&UsartData[0],(uint32_t)&(USART1->DR),1056); //串口使用DMA
while循环里面如下
if(UsartFlagAchieve) //串口数据接收完成
{
Dis_Piture_Serial(UsartData); //屏幕显示一张图片的
UsartFlagAchieve = 0; //接收完标志位置0
}
现在是利用电脑端存数据 后续开发可以利用片外存储器。
最后最后确保一点 ,就是ebm文件通过串口发送过去必须要显示到完整的图片,不然ebm里面的数据格式不对,你连起来的数据格式也是不可以的。
由于每个人用到OLED屏幕不一样 我用的是1.3寸OLED屏_驱动芯片SH1106
如果你用的是也是这种显示照片可以私信我哟。
链接:https://pan.baidu.com/s/1WH4T9Tgl1tpDGHDmD5QDBw
提取码:0225
--来自百度网盘超级会员V2的分享
这篇关于基于STM32F4xx利用串口播放视频(OLED)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!