STM32F4 LCD显存+DMA数据传输详解及代码示例
STM32F4 LCD显存+DMA数据传输详解及代码示例
本文将详细介绍如何在STM32F4系列芯片上使用显存+DMA的方式传输数据到LCD,并提供一个完整的代码示例,包括LCD和DMA的初始化以及数据传输过程。
一、概述
使用显存+DMA传输数据到LCD是一种高效的方式,可以显著提高数据传输速度,从而实现更流畅的画面显示。
二、配置步骤
-
打开LCD控制器: 使用STM32CubeMX软件,选择对应的STM32F4系列芯片,在'Pinout & Configuration'选项卡中找到LCD控制器对应的引脚,并将其分配给LCD控制器。
-
配置时钟: 在'Clock Configuration'选项卡中,配置LCD控制器时钟源和频率。
-
配置显存和DMA通道: 在'Configuration'选项卡中,打开LCD控制器,并配置显存基地址、显存大小和DMA通道。
-
生成代码: 生成代码,并在工程中添加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);
}
}
四、解释
-
LCD_DMA_Init()函数: 初始化DMA通道,设置DMA传输方向、数据大小、数据地址等参数。
-
LCD_Init()函数: 初始化LCD控制器,配置LCD参数,如时钟、颜色格式、显示区域等。
-
main()函数:
- 在循环中,首先将显存中的数据设置为白色。
- 然后禁用DMA通道,设置DMA数据长度,最后重新启用DMA通道,将数据传输到LCD。
- 使用DMA_GetFlagStatus()函数判断DMA传输是否完成,并使用DMA_ClearFlag()函数清除中断标志。
五、注意事项
-
确保LCD_FRAME_BUFFER地址正确,它对应显存的起始地址。
-
根据实际需求修改LCD参数和DMA设置。
-
数据传输完成后,记得清除DMA中断标志。
六、总结
本文详细介绍了如何在STM32F4系列芯片上使用显存+DMA的方式传输数据到LCD,并提供了一个完整的代码示例,希望能帮助大家更好地理解和运用这种高效的数据传输方式。
原文地址: https://www.cveoy.top/t/topic/mypW 著作权归作者所有。请勿转载和采集!