Basado en STM32F4xx, use el puerto serie para reproducir video (OLED)

Vídeo de efectos:  pantalla OLED de 1,3 pulgadas basada en el chip STM32F11_driver SH1106_哔哩哔哩_bilibili

La pantalla es impulsada por hardware SPI. Al comprar una pantalla, el comerciante proporcionará el código fuente del controlador y no debería haber ningún problema para mostrar texto, números, etc. Esta vez hablaré principalmente sobre cómo mostrar el video. La visualización de mi imagen y la visualización de texto y número están escritas por mí mismo (también puedes enviarme un mensaje privado para obtenerlo, pero la velocidad de visualización no es tan rápida como el código fuente).

La memoria de la microcomputadora de un solo chip stm32 no es lo suficientemente grande, y un video puede tener solo unos pocos M, y no cabe en absoluto. El video es en realidad una combinación de cuadro por cuadro de fotos. Podemos mostrar una imagen y luego reproducir el video (enviar información de la imagen en un bucle y luego actualizar la pantalla).

A continuación, hablaré sobre los pasos de reproducción de video (la herramienta se puede descargar desde el siguiente enlace del disco de red)

Paso 1: Captura de imágenes para video

        Simplemente descargue un gif más largo, cambie su sufijo a .mp4 y ábralo con KMPlayer.exe

        Después de abrir, haga clic derecho en la pantalla de la siguiente manera para la captura avanzada

 

Pausa el video primero, luego haz clic en el botón de inicio de arriba y luego haz clic para reproducir el video. Encontrará un montón de imágenes bmp que aparecen en su carpeta anterior.

 El segundo paso: convertir la imagen bmp al formato requerido por el microcontrolador

        Abra esta herramienta de configuración Img2Lcd.exe en la siguiente figura

        

 Abre el primer bmp de nuevo

conversión por lotes

Elija Sí y luego produzca muchos archivos .ebm

Este paso es generar el contenido de cada imagen en formato ebm, puede enviar directamente este archivo a través del puerto serie y la imagen que se muestra en la pantalla cambiará. Por supuesto, la premisa es que ya ha escrito la recepción del puerto serie. Usé dma para recibir un mensaje de imagen (alrededor de 1000 bytes) y luego interrumpirlo.

Entonces, el microcontrolador DMA se interrumpe y luego se puede mostrar una imagen.

Para enviar todos los archivos ebm de forma continua, utilicé python para combinar los archivos. La imagen de end.ebm de arriba es el archivo generado por python. El siguiente es el código de python, necesita descargar el compilador de python o no funcionará.

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()

Después de que se genera, se completa y luego se puede enviar directamente a través del puerto serie.El siguiente es el puerto serie y el código DMA de la microcomputadora de un solo chip. Desarrollo de funciones de biblioteca estándar

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

En la función principal necesitas la siguiente función

carácter sin firmar UsartData[1056];

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //Configuración de prioridad de interrupción

Usart1_Init(115200); //Inicialización del puerto serie
Dma2Init((uint32_t)&UsartData[0],(uint32_t)&(USART1->DR),1056); //Uso de DMA para el puerto serie   

Dentro del bucle while es el siguiente

if(UsartFlagAchieve) //La recepción de datos del puerto serie está completa                                
    {         Dis_Piture_Serial(UsartData); //         UsartFlagAchieve de una imagen mostrada en la pantalla = 0; //Posición de bandera recibida 0      }         


Ahora es posible utilizar la memoria fuera del chip para el desarrollo posterior utilizando la computadora para almacenar datos.

Finalmente, una última cosa para asegurarse es que el archivo ebm debe mostrarse como una imagen completa cuando se envía a través del puerto serie; de ​​lo contrario, el formato de datos en ebm es incorrecto y el formato de datos que conectó tampoco es aceptable.

Como todos usan las pantallas OLED de manera diferente, yo uso un chip OLED screen_driver SH1106 de 1,3 pulgadas 

Si usa las mismas fotos de visualización, puede enviarme un mensaje privado.

Enlace: https://pan.baidu.com/s/1WH4T9Tgl1tpDGHDmD5QDBw 
Código de extracción: 0225 
--Compartir de Baidu Netdisk supermember V2

Supongo que te gusta

Origin blog.csdn.net/longjintao1/article/details/126213451
Recomendado
Clasificación