- BSP_QSPI_Init(0, &init);
-
- BSP_QSPI_EnableMemoryMappedMode(0);
- MX_JPEG_Init();
- MX_MDMA_Init();
- BSP_LCD_Init(0, LCD_ORIENTATION_LANDSCAPE);
- UTIL_LCD_SetFuncDriver(&LCD_Driver);
- UTIL_LCD_SetLayer(0);
- BSP_LED_Init(LED_GREEN);
- BSP_LED_Init(LED_RED);
-
- AVI_player_demo();
初始化flash、JPEG、MDMA、LCD
运行AVI DEMO程序
JPEG初始化
- static void MX_JPEG_Init(void)
- {
- /* USER CODE BEGIN JPEG_Init 0 */
- /* USER CODE END JPEG_Init 0 */
- /* USER CODE BEGIN JPEG_Init 1 */
- /* USER CODE END JPEG_Init 1 */
- hjpeg.Instance = JPEG;
- if (HAL_JPEG_Init(&hjpeg) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN JPEG_Init 2 */
- /* USER CODE END JPEG_Init 2 */
- }
MDMA初始化:
- static void MX_MDMA_Init(void)
- {
- /* MDMA controller clock enable */
- __HAL_RCC_MDMA_CLK_ENABLE();
- /* Local variables */
- /* MDMA interrupt initialization */
- /* MDMA_IRQn interrupt configuration */
- HAL_NVIC_SetPriority(MDMA_IRQn, 0x08, 0x0F);
- HAL_NVIC_EnableIRQ(MDMA_IRQn);
- }
MPU_Config
- void MPU_Config(void)
- {
- MPU_Region_InitTypeDef MPU_InitStruct = {0};
- /* Disables the MPU */
- HAL_MPU_Disable();
- /** Initializes and configures the Region and the memory to be protected
- */
- MPU_InitStruct.Enable = MPU_REGION_ENABLE;
- MPU_InitStruct.Number = MPU_REGION_NUMBER0;
- MPU_InitStruct.BaseAddress = 0x0;
- MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
- MPU_InitStruct.SubRegionDisable = 0x87;
- MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
- MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
- MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
- MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
- MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
- MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
- HAL_MPU_ConfigRegion(&MPU_InitStruct);
- /** Initializes and configures the Region and the memory to be protected
- */
- MPU_InitStruct.Number = MPU_REGION_NUMBER1;
- MPU_InitStruct.BaseAddress = 0xD0000000;
- MPU_InitStruct.Size = MPU_REGION_SIZE_32MB;
- MPU_InitStruct.SubRegionDisable = 0x0;
- MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
- MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
- MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
- MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
- HAL_MPU_ConfigRegion(&MPU_InitStruct);
-
-
- /* Configure the MPU QSPI flash */
- MPU_InitStruct.Enable = MPU_REGION_ENABLE;
- MPU_InitStruct.BaseAddress = 0x90000000;
- MPU_InitStruct.Size = MPU_REGION_SIZE_128MB;
- MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
- MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
- MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
- MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
- MPU_InitStruct.Number = MPU_REGION_NUMBER2;
- MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
- MPU_InitStruct.SubRegionDisable = 0x0;
- MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
-
- HAL_MPU_ConfigRegion(&MPU_InitStruct);
-
- /* Enables the MPU */
- HAL_MPU_Enable(MPU_HFNMI_PRIVDEF);
- }
三、AVI_Player.c
1、定义常量
//AVI文件地址 位于flash,首地址0x90000000
#define AVI_FILE_ADDRESS ((uint32_t)(0x90000000)) /*Address of the MJPEG AVI file located on the QSPI */
//LCD显示地址
#define LCD_FRAME_BUFFER 0xD0000000
//JPEG解码双缓冲地址
#define JPEG_OUTPUT_DATA_BUFFER0 0xD0100000
#define JPEG_OUTPUT_DATA_BUFFER1 0xD0200000
2、AVI_player_demo
主要功能是利用AVI_parser解析AVI文件(0x90000000),得到每一帧画面,用硬件JPEG双缓存解码,通过DMA2D将解码后内容显示到LCD上。
- void AVI_player_demo(void)
- {
- uint32_t isfirstFrame =0 , startTime = 0;
- uint32_t jpegOutDataAdreess = JPEG_OUTPUT_DATA_BUFFER0;
- uint32_t FrameType = 0;
-
- BSP_LCD_GetXSize(0, &LCD_X_Size);
- BSP_LCD_GetYSize(0, &LCD_Y_Size);
-
- /*##-3- Initialize the AVI Parser ##########################################*/
- if(AVI_ParserInit(&AVI_Handel, AVI_FILE_ADDRESS) == 0)
- {
- isfirstFrame = 1;
- FrameRate = 0;
-
- startTime = HAL_GetTick();
- do
- {
- /*##-4- Get a Frame from the AVI file ##################################*/
- FrameType = AVI_GetFrame(&AVI_Handel);
-
- if(FrameType == AVI_VIDEO_FRAME)
- {
- AVI_Handel.CurrentImage ++;
-
- /*##-5- Start decoding the current JPEG frame with DMA (Not Blocking ) Method ################*/
- JPEG_Decode_DMA(&hjpeg,(uint32_t) AVI_Handel.pVideoBuffer ,AVI_Handel.FrameSize, jpegOutDataAdreess );
-
-
- /*##-6- Wait till end of JPEG decoding ###############################*/
- while(Jpeg_HWDecodingEnd == 0)
- {
- }
-
- if(isfirstFrame == 1)
- {
- isfirstFrame = 0;
- /*##-7- Get JPEG Info #############################################*/
- HAL_JPEG_GetInfo(&hjpeg, &JPEG_Info);
-
- /*##-8- Initialize the DMA2D #######################################*/
- DMA2D_Init(JPEG_Info.ImageWidth, JPEG_Info.ImageHeight, JPEG_Info.ChromaSubsampling);
- }
- /*##-9- Copy the Decoded frame to the display frame buffer using the DMA2D #*/
- DMA2D_CopyBuffer((uint32_t *)jpegOutDataAdreess, (uint32_t *)LCD_FRAME_BUFFER, JPEG_Info.ImageWidth, JPEG_Info.ImageHeight);
- //DMA2D_CopyBuffer((uint32_t *)jpegOutDataAdreess, (uint32_t*)LCD_FRAME_BUFFER, 0 , 0, JPEG_Info.ImageWidth, JPEG_Info.ImageHeight, JPEG_Info.ChromaSubsampling);
- jpegOutDataAdreess = (jpegOutDataAdreess == JPEG_OUTPUT_DATA_BUFFER0) ? JPEG_OUTPUT_DATA_BUFFER1 : JPEG_OUTPUT_DATA_BUFFER0;
-
- #ifdef USE_FRAMERATE_REGULATION
- /* Regulate the frame rate to the video native frame rate by inserting delays */
- FrameRate = (HAL_GetTick() - startTime) + 1;
- if(FrameRate < ((AVI_Handel.aviInfo.SecPerFrame/1000) * AVI_Handel.CurrentImage))
- {
- HAL_Delay(((AVI_Handel.aviInfo.SecPerFrame /1000) * AVI_Handel.CurrentImage) - FrameRate);
- }
- #endif /* USE_FRAMERATE_REGULATION */
- }
-
- }while(AVI_Handel.CurrentImage < AVI_Handel.aviInfo.TotalFrame);
-
- HAL_DMA2D_PollForTransfer(&DMA2D_Handle, 50); /* wait for the Last DMA2D transfer to ends */
-
- if(AVI_Handel.CurrentImage > 0)
- {
- /*##-10- Calc the average decode frame rate #*/
- FrameRate = (AVI_Handel.CurrentImage * 1000)/(HAL_GetTick() - startTime);
- /* Display decoding info */
- LCD_BriefDisplay();
- }
- }
- else /* Can't Open avi file*/
- {
- printf("Can't Open avi file\r\n");
- }
- }
3、DMA2D_CopyBuffer
用DMA2D显示在LCD上
- static void DMA2D_CopyBuffer(uint32_t *pSrc, uint32_t *pDst, uint16_t ImageWidth, uint16_t ImageHeight)
- {
- //uint16_t timeout=0;
- uint32_t xPos, yPos, destination;
-
- /*##-1- calculate the destination transfer address ############*/
- xPos = (LCD_X_Size - JPEG_Info.ImageWidth)/2;
- yPos = (LCD_Y_Size - JPEG_Info.ImageHeight)/2;
-
- destination = (uint32_t)pDst + ((yPos * LCD_Y_Size) + xPos) * 4;
-
- HAL_DMA2D_PollForTransfer(&DMA2D_Handle, 25); /* wait for the previous DMA2D transfer to ends */
- /* copy the new decoded frame to the LCD Frame buffer*/
- HAL_DMA2D_Start(&DMA2D_Handle, (uint32_t)pSrc, destination, ImageWidth, ImageHeight);
- }
4、DMA2D_Init
DMA2D初始化
- static void DMA2D_Init(uint16_t xsize, uint16_t ysize, uint32_t ChromaSampling)
- {
- uint32_t cssMode = JPEG_420_SUBSAMPLING, inputLineOffset = 0;
-
- if(ChromaSampling == JPEG_420_SUBSAMPLING)
- {
- cssMode = DMA2D_CSS_420;
-
- inputLineOffset = xsize % 16;
- if(inputLineOffset != 0)
- {
- inputLineOffset = 16 - inputLineOffset;
- }
- }
- else if(ChromaSampling == JPEG_444_SUBSAMPLING)
- {
- cssMode = DMA2D_NO_CSS;
-
- inputLineOffset = xsize % 8;
- if(inputLineOffset != 0)
- {
- inputLineOffset = 8 - inputLineOffset;
- }
- }
- else if(ChromaSampling == JPEG_422_SUBSAMPLING)
- {
- cssMode = DMA2D_CSS_422;
-
- inputLineOffset = xsize % 16;
- if(inputLineOffset != 0)
- {
- inputLineOffset = 16 - inputLineOffset;
- }
- }
-
- /*##-1- Configure the DMA2D Mode, Color Mode and output offset #############*/
- DMA2D_Handle.Init.Mode = DMA2D_M2M_PFC;
- DMA2D_Handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
- DMA2D_Handle.Init.OutputOffset = LCD_X_Size - xsize;
- DMA2D_Handle.Init.AlphaInverted = DMA2D_REGULAR_ALPHA; /* No Output Alpha Inversion*/
- DMA2D_Handle.Init.RedBlueSwap = DMA2D_RB_REGULAR; /* No Output Red & Blue swap */
-
- /*##-2- DMA2D Callbacks Configuration ######################################*/
- DMA2D_Handle.XferCpltCallback = NULL;
-
- /*##-3- Foreground Configuration ###########################################*/
- DMA2D_Handle.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA;
- DMA2D_Handle.LayerCfg[1].InputAlpha = 0xFF;
- DMA2D_Handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_YCBCR;
- DMA2D_Handle.LayerCfg[1].ChromaSubSampling = cssMode;
- DMA2D_Handle.LayerCfg[1].InputOffset = inputLineOffset;
- DMA2D_Handle.LayerCfg[1].RedBlueSwap = DMA2D_RB_REGULAR; /* No ForeGround Red/Blue swap */
- DMA2D_Handle.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA; /* No ForeGround Alpha inversion */
-
- DMA2D_Handle.Instance = DMA2D;
-
- /*##-4- DMA2D Initialization ###########################################*/
- HAL_DMA2D_Init(&DMA2D_Handle);
- HAL_DMA2D_ConfigLayer(&DMA2D_Handle, 1);
- }
四、stm32h7xx_hal_msp.c
- extern MDMA_HandleTypeDef hmdma_jpeg_infifo_th;
- extern MDMA_HandleTypeDef hmdma_jpeg_outfifo_th;
- void HAL_JPEG_MspInit(JPEG_HandleTypeDef* hjpeg)
- {
- if(hjpeg->Instance==JPEG)
- {
- /* USER CODE BEGIN JPEG_MspInit 0 */
- /* USER CODE END JPEG_MspInit 0 */
- /* Peripheral clock enable */
- __HAL_RCC_JPEG_CLK_ENABLE();
- /* JPEG MDMA Init */
- /* JPEG_INFIFO_TH Init */
- hmdma_jpeg_infifo_th.Instance = MDMA_Channel7;
- hmdma_jpeg_infifo_th.Init.Request = MDMA_REQUEST_JPEG_INFIFO_TH;
- hmdma_jpeg_infifo_th.Init.TransferTriggerMode = MDMA_BUFFER_TRANSFER;
- hmdma_jpeg_infifo_th.Init.Priority = MDMA_PRIORITY_HIGH;
- hmdma_jpeg_infifo_th.Init.Endianness = MDMA_LITTLE_ENDIANNESS_PRESERVE;
- hmdma_jpeg_infifo_th.Init.SourceInc = MDMA_SRC_INC_BYTE;
- hmdma_jpeg_infifo_th.Init.DestinationInc = MDMA_DEST_INC_DISABLE;
- hmdma_jpeg_infifo_th.Init.SourceDataSize = MDMA_SRC_DATASIZE_BYTE;
- hmdma_jpeg_infifo_th.Init.DestDataSize = MDMA_DEST_DATASIZE_WORD;
- hmdma_jpeg_infifo_th.Init.DataAlignment = MDMA_DATAALIGN_PACKENABLE;
- hmdma_jpeg_infifo_th.Init.BufferTransferLength = 32;
- hmdma_jpeg_infifo_th.Init.SourceBurst = MDMA_SOURCE_BURST_32BEATS;
- hmdma_jpeg_infifo_th.Init.DestBurst = MDMA_DEST_BURST_16BEATS;
- hmdma_jpeg_infifo_th.Init.SourceBlockAddressOffset = 0;
- hmdma_jpeg_infifo_th.Init.DestBlockAddressOffset = 0;
- if (HAL_MDMA_Init(&hmdma_jpeg_infifo_th) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_MDMA_ConfigPostRequestMask(&hmdma_jpeg_infifo_th, 0, 0) != HAL_OK)
- {
- Error_Handler();
- }
- __HAL_LINKDMA(hjpeg,hdmain,hmdma_jpeg_infifo_th);
- /* JPEG_OUTFIFO_TH Init */
- hmdma_jpeg_outfifo_th.Instance = MDMA_Channel6;
- hmdma_jpeg_outfifo_th.Init.Request = MDMA_REQUEST_JPEG_OUTFIFO_TH;
- hmdma_jpeg_outfifo_th.Init.TransferTriggerMode = MDMA_BUFFER_TRANSFER;
- hmdma_jpeg_outfifo_th.Init.Priority = MDMA_PRIORITY_VERY_HIGH;
- hmdma_jpeg_outfifo_th.Init.Endianness = MDMA_LITTLE_ENDIANNESS_PRESERVE;
- hmdma_jpeg_outfifo_th.Init.SourceInc = MDMA_SRC_INC_DISABLE;
- hmdma_jpeg_outfifo_th.Init.DestinationInc = MDMA_DEST_INC_BYTE;
- hmdma_jpeg_outfifo_th.Init.SourceDataSize = MDMA_SRC_DATASIZE_WORD;
- hmdma_jpeg_outfifo_th.Init.DestDataSize = MDMA_DEST_DATASIZE_BYTE;
- hmdma_jpeg_outfifo_th.Init.DataAlignment = MDMA_DATAALIGN_PACKENABLE;
- hmdma_jpeg_outfifo_th.Init.BufferTransferLength = 32;
- hmdma_jpeg_outfifo_th.Init.SourceBurst = MDMA_SOURCE_BURST_32BEATS;
- hmdma_jpeg_outfifo_th.Init.DestBurst = MDMA_DEST_BURST_32BEATS;
- hmdma_jpeg_outfifo_th.Init.SourceBlockAddressOffset = 0;
- hmdma_jpeg_outfifo_th.Init.DestBlockAddressOffset = 0;
- if (HAL_MDMA_Init(&hmdma_jpeg_outfifo_th) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_MDMA_ConfigPostRequestMask(&hmdma_jpeg_outfifo_th, 0, 0) != HAL_OK)
- {
- Error_Handler();
- }
- __HAL_LINKDMA(hjpeg,hdmaout,hmdma_jpeg_outfifo_th);
- /* JPEG interrupt Init */
- HAL_NVIC_SetPriority(JPEG_IRQn, 0x07, 0x0F);
- HAL_NVIC_EnableIRQ(JPEG_IRQn);
- /* USER CODE BEGIN JPEG_MspInit 1 */
- /* USER CODE END JPEG_MspInit 1 */
- }
- }
- void HAL_JPEG_MspDeInit(JPEG_HandleTypeDef* hjpeg)
- {
- if(hjpeg->Instance==JPEG)
- {
- /* USER CODE BEGIN JPEG_MspDeInit 0 */
- /* USER CODE END JPEG_MspDeInit 0 */
- /* Peripheral clock disable */
- __HAL_RCC_JPEG_CLK_DISABLE();
- /* JPEG MDMA DeInit */
- HAL_MDMA_DeInit(hjpeg->hdmain);
- HAL_MDMA_DeInit(hjpeg->hdmaout);
- /* JPEG interrupt DeInit */
- HAL_NVIC_DisableIRQ(JPEG_IRQn);
- /* USER CODE BEGIN JPEG_MspDeInit 1 */
-
- /* USER CODE END JPEG_MspDeInit 1 */
- }
- }
五、中断处理
- extern JPEG_HandleTypeDef hjpeg;
- extern DMA2D_HandleTypeDef DMA2D_Handle;
- void JPEG_IRQHandler(void)
- {
- /* USER CODE BEGIN JPEG_IRQn 0 */
- /* USER CODE END JPEG_IRQn 0 */
- HAL_JPEG_IRQHandler(&hjpeg);
- /* USER CODE BEGIN JPEG_IRQn 1 */
- /* USER CODE END JPEG_IRQn 1 */
- }
- void MDMA_IRQHandler(void)
- {
- /* USER CODE BEGIN MDMA_IRQn 0 */
- HAL_MDMA_IRQHandler(hjpeg.hdmain);
- HAL_MDMA_IRQHandler(hjpeg.hdmaout);
- /* USER CODE END MDMA_IRQn 0 */
- /* HAL_MDMA_IRQHandler(&hmdma_jpeg_outfifo_th);
- HAL_MDMA_IRQHandler(&hmdma_jpeg_infifo_th);*/
- /* USER CODE BEGIN MDMA_IRQn 1 */
- /* USER CODE END MDMA_IRQn 1 */
- }
- void DMA2D_IRQHandler(void)
- {
- /* USER CODE BEGIN DMA2D_IRQn 0 */
- HAL_DMA2D_IRQHandler(&DMA2D_Handle);
- /* USER CODE END DMA2D_IRQn 0 */
- /* USER CODE BEGIN DMA2D_IRQn 1 */
- /* USER CODE END DMA2D_IRQn 1 */
- }
六、将AVI文件烧录到0x90000000
打开STM32 ST-LINK Utility
External Loader->add External Loader 增加外部FLASH:
擦除flash内容:
将AVI(改名.bin)文件烧录到0x90000000
这样视频文件就准备好了。
C:\Users\自己的用户名\STM32Cube\Repository\STM32Cube_FW_H7_V1.12.0\Utilities\Media\Video下有一些AVI文件
七、源码
AVI_TEST.part01.rar
(10 MB, 下载次数: 13)
AVI_TEST.part02.rar
(10 MB, 下载次数: 13)
AVI_TEST.part03.rar
(10 MB, 下载次数: 13)
AVI_TEST.part04.rar
(10 MB, 下载次数: 15)
AVI_TEST.part05.rar
(7.32 MB, 下载次数: 2)