stm32f103c8t6 VGA显示程序
时间: 2023-08-25 17:07:37 浏览: 186
STM32F103C8T6配套程序源码-LCD1602显示_stm32f103c8t6_c8t6lcd1602
5星 · 资源好评率100%
要在STM32F103C8T6上实现VGA显示,需要用到它的定时器和DMA功能。以下是一个简单的VGA显示程序:
```c
#include "stm32f10x.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_dma.h"
#define HSYNC_TIM TIM2
#define HSYNC_TIM_IRQn TIM2_IRQn
#define HSYNC_GPIO GPIOA
#define HSYNC_PIN GPIO_Pin_1
#define VSYNC_TIM TIM3
#define VSYNC_TIM_IRQn TIM3_IRQn
#define VSYNC_GPIO GPIOA
#define VSYNC_PIN GPIO_Pin_0
#define DMA_CHANNEL DMA1_Channel3
#define VGA_WIDTH 640
#define VGA_HEIGHT 480
uint16_t framebuffer[VGA_HEIGHT][VGA_WIDTH];
void HSYNC_IRQHandler(void)
{
// 水平同步定时器中断处理函数
TIM_ClearITPendingBit(HSYNC_TIM, TIM_IT_Update);
GPIO_WriteBit(HSYNC_GPIO, HSYNC_PIN, Bit_RESET);
}
void VSYNC_IRQHandler(void)
{
// 垂直同步定时器中断处理函数
TIM_ClearITPendingBit(VSYNC_TIM, TIM_IT_Update);
GPIO_WriteBit(VSYNC_GPIO, VSYNC_PIN, Bit_RESET);
// 启动DMA传输
DMA_Cmd(DMA_CHANNEL, ENABLE);
}
void DMA1_Channel3_IRQHandler(void)
{
// DMA传输完成中断处理函数
DMA_ClearITPendingBit(DMA_CHANNEL, DMA_IT_TC);
GPIO_WriteBit(VSYNC_GPIO, VSYNC_PIN, Bit_SET);
}
void VGA_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
DMA_InitTypeDef DMA_InitStruct;
TIM_TimeBaseInitTypeDef TIM_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
// 使能定时器和DMA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// 配置水平同步定时器
TIM_DeInit(HSYNC_TIM);
TIM_InitStruct.TIM_Prescaler = 0;
TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_InitStruct.TIM_Period = 799;
TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(HSYNC_TIM, &TIM_InitStruct);
TIM_ITConfig(HSYNC_TIM, TIM_IT_Update, ENABLE);
TIM_Cmd(HSYNC_TIM, ENABLE);
NVIC_InitStruct.NVIC_IRQChannel = HSYNC_TIM_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
// 配置垂直同步定时器
TIM_DeInit(VSYNC_TIM);
TIM_InitStruct.TIM_Prescaler = 0;
TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_InitStruct.TIM_Period = 524;
TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(VSYNC_TIM, &TIM_InitStruct);
TIM_ITConfig(VSYNC_TIM, TIM_IT_Update, ENABLE);
NVIC_InitStruct.NVIC_IRQChannel = VSYNC_TIM_IRQn;
NVIC_Init(&NVIC_InitStruct);
// 配置DMA
DMA_DeInit(DMA_CHANNEL);
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&GPIOA->ODR;
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&framebuffer[0][0];
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStruct.DMA_BufferSize = VGA_WIDTH * VGA_HEIGHT;
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_VeryHigh;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA_CHANNEL, &DMA_InitStruct);
DMA_ITConfig(DMA_CHANNEL, DMA_IT_TC, ENABLE);
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel3_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
// 配置同步信号GPIO口
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Pin = HSYNC_PIN | VSYNC_PIN;
GPIO_Init(HSYNC_GPIO, &GPIO_InitStruct);
// 初始化帧缓冲区
for (int y = 0; y < VGA_HEIGHT; y++)
{
for (int x = 0; x < VGA_WIDTH; x++)
{
framebuffer[y][x] = 0x0000;
}
}
}
int main(void)
{
VGA_Init();
while (1)
{
// 在帧缓冲区中绘制图像
// 等待DMA传输完成
while (DMA_GetFlagStatus(DMA_CHANNEL, DMA_FLAG_TCIF3) == RESET);
DMA_ClearFlag(DMA_CHANNEL, DMA_FLAG_TCIF3);
}
}
```
这个程序的核心是两个定时器,一个用来产生水平同步信号,一个用来产生垂直同步信号。水平同步信号每行都要产生一次,垂直同步信号每帧都要产生一次。在定时器中断处理函数中,我们将同步信号拉低,以便VGA显示设备知道一行或一帧已经结束。在VSYNC定时器中断处理函数中,我们启动DMA传输,将帧缓冲区中的数据传输到GPIO输出寄存器中,这样就将图像显示在屏幕上了。DMA传输完成后,我们将垂直同步信号拉高,以便VGA显示设备知道新的一帧已经开始。
注意,这个程序只能在分辨率为640x480的VGA显示器上运行,如果你的显示器分辨率不同,需要修改定时器和DMA的参数。此外,由于这个程序没有使用外部SRAM,所以帧缓冲区的大小不能超过STM32F103C8T6的内部SRAM大小(20KB)。
阅读全文