STM32F4 LCD显存+DMA数据传输详解及代码示例

本文将详细介绍如何在STM32F4系列芯片上使用显存+DMA的方式传输数据到LCD,并提供一个完整的代码示例,包括LCD和DMA的初始化以及数据传输过程。

一、概述

使用显存+DMA传输数据到LCD是一种高效的方式,可以显著提高数据传输速度,从而实现更流畅的画面显示。

二、配置步骤

  1. 打开LCD控制器: 使用STM32CubeMX软件,选择对应的STM32F4系列芯片,在'Pinout & Configuration'选项卡中找到LCD控制器对应的引脚,并将其分配给LCD控制器。

  2. 配置时钟: 在'Clock Configuration'选项卡中,配置LCD控制器时钟源和频率。

  3. 配置显存和DMA通道: 在'Configuration'选项卡中,打开LCD控制器,并配置显存基地址、显存大小和DMA通道。

  4. 生成代码: 生成代码,并在工程中添加LCD标准库文件。

三、代码示例

以下是一个完整的代码示例,演示了如何使用显存+DMA传输数据到LCD。

#include "stm32f4xx.h"
#include "stm32f4xx_dma.h"
#include "stm32f4xx_lcd.h"

#define LCD_FRAME_BUFFER ((uint32_t)0x60000000)

void LCD_DMA_Init(void)
{
    DMA_InitTypeDef DMA_InitStruct;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
    DMA_StructInit(&DMA_InitStruct);
    DMA_InitStruct.DMA_Channel = DMA_Channel_0;
    DMA_InitStruct.DMA_PeripheralBaseAddr = LCD_FRAME_BUFFER;
    DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)LCD_FRAME_BUFFER;
    DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory;
    DMA_InitStruct.DMA_BufferSize = LCD_PIXEL_WIDTH * LCD_PIXEL_HEIGHT / 2;
    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
    DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStruct.DMA_Priority = DMA_Priority_High;
    DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Enable;
    DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream0, &DMA_InitStruct);
    DMA_Cmd(DMA2_Stream0, ENABLE);
}

void LCD_Init(void)
{
    LCD_InitTypeDef LCD_InitStruct;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOG, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_LCD, ENABLE);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource4, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource10, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource9, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource8, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource7, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource6, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource5, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource4, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource12, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource13, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource10, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource7, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource6, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource5, GPIO_AF_LTDC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource4, GPIO_AF_LTDC);

    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOE, &GPIO_InitStruct);

    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOF, &GPIO_InitStruct);

    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOG, &GPIO_InitStruct);

    LCD_StructInit(&LCD_InitStruct);
    LCD_InitStruct.LCD_HSPolarity = LCD_HSPolarity_AL;
    LCD_InitStruct.LCD_VSPolarity = LCD_VSPolarity_AL;
    LCD_InitStruct.LCD_DEPolarity = LCD_DEPolarity_AL;
    LCD_InitStruct.LCD_PCPolarity = LCD_PCPolarity_IPC;
    LCD_InitStruct.LCD_HorizontalSync = LCD_HSYNC;
    LCD_InitStruct.LCD_VerticalSync = LCD_VSYNC;
    LCD_InitStruct.LCD_AccumulatedHBP = LCD_HSYNC + LCD_HBP;
    LCD_InitStruct.LCD_AccumulatedVBP = LCD_VSYNC + LCD_VBP;
    LCD_InitStruct.LCD_AccumulatedActiveW = LCD_HSYNC + LCD_HBP + LCD_PIXEL_WIDTH;
    LCD_InitStruct.LCD_AccumulatedActiveH = LCD_VSYNC + LCD_VBP + LCD_PIXEL_HEIGHT;
    LCD_InitStruct.LCD_TotalWidth = LCD_HSYNC + LCD_HBP + LCD_PIXEL_WIDTH + LCD_HFP;
    LCD_InitStruct.LCD_TotalHeigh = LCD_VSYNC + LCD_VBP + LCD_PIXEL_HEIGHT + LCD_VFP;
    LCD_InitStruct.LCD_BackgroundColor = 0;
    LCD_Init(&LCD_InitStruct);

    LCD_LayerInitTypeDef layer;
    layer.LCD_HorizontalStart = LCD_HSYNC + LCD_HBP;
    layer.LCD_HorizontalStop = LCD_HSYNC + LCD_HBP + LCD_PIXEL_WIDTH - 1;
    layer.LCD_VerticallStart = LCD_VSYNC + LCD_VBP;
    layer.LCD_VerticalStop = LCD_VSYNC + LCD_VBP + LCD_PIXEL_HEIGHT - 1;
    layer.LCD_PixelFormat = LCD_Pixelformat_RGB565;
    layer.LCD_ConstantAlpha = 255;
    layer.LCD_DefaultColor = 0;
    layer.LCD_BlendingFactor1 = LCD_BlendingFactor1_CA;
    layer.LCD_BlendingFactor2 = LCD_BlendingFactor2_CA;
    layer.LCD_CFBStartAdress = (uint32_t)LCD_FRAME_BUFFER;
    layer.LCD_CFBLineLength = LCD_PIXEL_WIDTH * 2;
    layer.LCD_CFBPitch = LCD_PIXEL_WIDTH * 2;
    layer.LCD_CFBLineNumber = LCD_PIXEL_HEIGHT;
    LCD_LayerInit(LCD_BACKGROUND_LAYER, &layer);
    LCD_SetLayerVisible(LCD_BACKGROUND_LAYER, ENABLE);
    LCD_SetLayerAlpha(LCD_BACKGROUND_LAYER, 255, 0);
    LCD_SetTextColor(0xFFFFFF);
    LCD_SetBackColor(0);
    LCD_Clear(0);
}

int main(void)
{
    LCD_Init();
    LCD_DMA_Init();
    while(1)
    {
        uint16_t* pData = (uint16_t*)LCD_FRAME_BUFFER;
        for(int i = 0; i < LCD_PIXEL_WIDTH * LCD_PIXEL_HEIGHT / 2; i++)
        {
            *pData++ = 0xFFFF;
        }
        DMA_Cmd(DMA2_Stream0, DISABLE);
        DMA_SetCurrDataCounter(DMA2_Stream0, LCD_PIXEL_WIDTH * LCD_PIXEL_HEIGHT / 2);
        DMA_Cmd(DMA2_Stream0, ENABLE);
        while(DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF0) == RESET);
        DMA_ClearFlag(DMA2_Stream0, DMA_FLAG_TCIF0);
    }
}

四、解释

  1. LCD_DMA_Init()函数: 初始化DMA通道,设置DMA传输方向、数据大小、数据地址等参数。

  2. LCD_Init()函数: 初始化LCD控制器,配置LCD参数,如时钟、颜色格式、显示区域等。

  3. main()函数:

    • 在循环中,首先将显存中的数据设置为白色。
    • 然后禁用DMA通道,设置DMA数据长度,最后重新启用DMA通道,将数据传输到LCD。
    • 使用DMA_GetFlagStatus()函数判断DMA传输是否完成,并使用DMA_ClearFlag()函数清除中断标志。

五、注意事项

  1. 确保LCD_FRAME_BUFFER地址正确,它对应显存的起始地址。

  2. 根据实际需求修改LCD参数和DMA设置。

  3. 数据传输完成后,记得清除DMA中断标志。

六、总结

本文详细介绍了如何在STM32F4系列芯片上使用显存+DMA的方式传输数据到LCD,并提供了一个完整的代码示例,希望能帮助大家更好地理解和运用这种高效的数据传输方式。

STM32F4 LCD显存+DMA数据传输详解及代码示例

原文地址: https://www.cveoy.top/t/topic/mypW 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录