STM32F4xxに基づいて、シリアルポートを使用してビデオを再生します(OLED)

エフェクトビデオ:  STM32F11_driver chip SH1106_哔哩哔哩_bilibiliに基づく1.3インチOLEDスクリーン

画面はハードウェア SPI によって駆動されます。画面を購入すると、販売者はドライバーのソース コードを提供します。テキストや数字などを表示することは問題ありません。今回は動画の表示方法を中心にお話ししますが、画像表示とテキストと数値表示は自分で書いています(プライベートメッセージで入手することもできますが、表示速度はソースコードほど速くはありません)。

stm32 シングルチップ マイコンのメモリは十分に大きくなく、ビデオは数 M しかない場合があり、まったく収まりません。ビデオは、実際には写真のフレームごとの組み合わせであり、画像を表示してからビデオを再生できます (画像情報をループで送信し、画面表示を更新します)。

次に、ビデオ再生の手順について説明します (ツールは次のネットワーク ディスク リンクからダウンロードできます)。

ステップ 1: ビデオ用の画像キャプチャ

        より長い gif をダウンロードし、サフィックスを .mp4 に変更して、KMPlayer.exe で開くだけです。

        開いた後、次のように画面を右クリックして高度なキャプチャを実行します

 

最初にビデオを一時停止してから、上の開始ボタンをクリックしてから、クリックしてビデオを再生します。上記のフォルダーの下に大量の bmp 画像が表示されます。

 2 番目のステップ: bmp イメージをマイクロコントローラーが必要とする形式に変換します。

        このツール Img2Lcd.exe 構成を次の図に開きます

        

 最初の bmp をもう一度開きます

一括変換

[はい] を選択し、大量の .ebm ファイルを生成します

このステップでは、各画像のコンテンツを ebm 形式で生成します。このファイルをシリアル ポート経由で直接送信すると、画面に表示される画像が変わります。もちろん、シリアルポートの受信は書いてあることが前提ですが、dmaで画像メッセージ(1000バイト程度)を受信して​​割り込みました。

そのため、マイクロコントローラーの DMA が中断され、画像を表示できるようになります。

ebmファイルを連続して送信するためにpythonでファイルを結合したところ、上のend.ebmの画像がpythonで生成されたファイルです。以下は Python コードです。Python コンパイラをダウンロードしないと動作しません。

import time
import serial
import os

def 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 
--Baidu Netdisk スーパー メンバー V2 からの共有

おすすめ

転載: blog.csdn.net/longjintao1/article/details/126213451