本帖最后由 Peixu 于 2024-12-4 15:21 编辑
1. VGA信号的基本概念 VGA信号包括三个主要部分: **RGB信号**:分别代表红色、绿色和蓝色的模拟信号,这些信号的电平决定了显示图像的颜色。 **水平同步信号(HSYNC)**:在每行像素结束时,提供一个短脉冲信号,指示显示设备开始新的一行。 **垂直同步信号(VSYNC)**:在一帧结束时提供脉冲信号,指示显示设备开始新的一帧。 对于1920x1080分辨率的60Hz显示,VGA信号的有效采样时间和采样率计算如下: 每行有效像素时间为12.92微秒。 每行采集的像素为40个,因此每个像素的采样时间为323纳秒。 所以在我们在这12.82us的时间尽可能用ADC去多采集信号。这样才能达到更好的效果。
2. 设计思路 要实现VGA信号的ADC采集,主要步骤如下: **信号处理**:通过电路设计,将VGA信号的RGB信号和同步信号连接到APM32F4的ADC引脚,并进行必要的电平转换。 **ADC配置**:设置APM32F4的ADC参数,以便进行高速采样。 **DMA配置**:为了提高数据传输的效率,将ADC采集的数据通过DMA(直接存储器访问)方式传送至内存。 **外部中断处理**:使用外部中断来触发ADC采集,以确保在每个HSYNC信号到来时进行采样。 **数据处理**:在主循环中处理采集的数据,进行显示或存储。
3. 硬件连接 3.1 信号连接 将VGA信号的RGB信号和同步信号连接至APM32F4的ADC引脚和外部中断引脚: **R信号**:连接至ADC通道0(PA3)。 **G信号**:连接至ADC通道1(PA4)。 **B信号**:连接至ADC通道2(PA5)。 **HSYNC信号**:连接至外部中断(PC10)。 **VSYNC信号**:连接至另一个外部中断(PC11)。
3.2 电路设计 在连接VGA信号和APM32F4之间,建议使用以下电路设计: **低通滤波器**:在ADC输入引脚前添加低通滤波器,以减少高频干扰。 **电平转换电路**:确保输入信号在APM32F4的ADC输入范围内(通常是0-3.3V)。
4. 软件实现 4.1 ADC初始化 配置ADC以采集RGB信号: - void ADC_Init(void) {
- GPIO_Config_T gpioConfig;
- ADC_Config_T adcConfig;
- ADC_CommonConfig_T adcCommonConfig;
- RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA);
- // GPIO配置
- GPIO_ConfigStructInit(&gpioConfig);
- gpioConfig.mode = GPIO_MODE_AN;
- gpioConfig.pupd = GPIO_PUPD_NOPULL;
- gpioConfig.pin = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
- GPIO_Config(GPIOA, &gpioConfig);
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
- ADC_Reset();
- // ADC通用配置
- adcCommonConfig.mode = ADC_MODE_INDEPENDENT;
- adcCommonConfig.prescaler = ADC_PRESCALER_DIV2;
- ADC_CommonConfig(&adcCommonConfig);
- // ADC配置
- adcConfig.resolution = ADC_RESOLUTION_12BIT;
- adcConfig.scanConvMode = DISABLE; // 单通道
- adcConfig.continuousConvMode = ENABLE; // 连续模式
- adcConfig.dataAlign = ADC_DATA_ALIGN_RIGHT;
- adcConfig.extTrigEdge = ADC_EXT_TRIG_EDGE_FALLING;
- adcConfig.extTrigConv = ADC_EXT_TRIG_CONV_EINT_11; // 触发方式为外部中断
- adcConfig.nbrOfChannel = 1;
- ADC_Config(ADC1, &adcConfig);
-
- // 配置ADC通道
- ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_3, 1, ADC_SAMPLETIME_3CYCLES); // R
- ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_4, 1, ADC_SAMPLETIME_3CYCLES); // G
- ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_5, 1, ADC_SAMPLETIME_3CYCLES); // B
- }
4.2 DMA初始化为ADC配置DMA:
- void DMA_Init(void)
- {
- DMA_Config_T dmaConfig;
- RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_DMA2);
- dmaConfig.peripheralBaseAddr = ADC_DR_ADDR;
- dmaConfig.memoryBaseAddr = (uint32_t)R[0]; // 初始地址指向第一行
- dmaConfig.dir = DMA_DIR_PERIPHERALTOMEMORY;
- dmaConfig.bufferSize = SAMPLES_PER_CHANNEL; // 每次传输的数据量
- dmaConfig.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;
- dmaConfig.memoryInc = DMA_MEMORY_INC_ENABLE;
- dmaConfig.peripheralDataSize = DMA_PERIPHERAL_DATA_SIZE_HALFWORD;
- dmaConfig.memoryDataSize = DMA_MEMORY_DATA_SIZE_HALFWORD;
- dmaConfig.loopMode = DMA_MODE_CIRCULAR; // 使用普通模式
- dmaConfig.priority = DMA_PRIORITY_HIGH;
- dmaConfig.fifoMode = DMA_FIFOMODE_DISABLE;
- dmaConfig.fifoThreshold = DMA_FIFOTHRESHOLD_HALFFULL;
- dmaConfig.memoryBurst = DMA_MEMORYBURST_SINGLE;
- dmaConfig.peripheralBurst = DMA_PERIPHERALBURST_SINGLE;
- dmaConfig.channel = DMA_CHANNEL_0;
-
- DMA_Config(DMA2_Stream0, &dmaConfig);
- DMA_EnableInterrupt(DMA2_Stream0, DMA_INT_TCI**); // 开启传输完成中断
- DMA_Enable(DMA2_Stream0); // 启用 DMA
- }
4.3 外部中断处理使用外部中断处理HSYNC信号:
- void EINT15_10_IRQHandler(void) {
- if (EINT_ReadIntFlag(EINT_LINE_10)) {
- /* 启动 ADC DMA 采集 */
- ADC1->STS = ~(uint32_t)ADC_FLAG_OVR;
- ADC1->CTRL2_B.REGSWSC = BIT_SET;
- while(RESET == DMA_ReadStatusFlag(DMA2_Stream0, DMA_FLAG_TCI**0));
- DMA_ClearStatusFlag(DMA2_Stream0, DMA_FLAG_TCI**0);
- DMA2_Stream0->SCFG_B.EN = DISABLE;
-
- dmaCompleteFlag = 1;
- HSync_cnt ++;
-
- currentRow++; // 切换到下一行 //
- if (currentRow >= HSync_MAX)
- {
- currentRow = 0; // 重置行号
- }
- DMA_ClearIntFlag(DMA2_Stream0, DMA_INT_TCI**0);
- DMA_Switch(currentChannel,currentRow);
- EINT_ClearIntFlag(EINT_LINE_10);
- }
- if (EINT_ReadIntFlag(EINT_LINE_11)) {
- currentChannel++;
- if (currentChannel >= 3) currentChannel = 0; // 切换通道
- ADC_SwitchChannel(currentChannel);
- EINT_ClearIntFlag(EINT_LINE_11);
- }
- }


4.4 数据处理在主循环中,处理采集到的数据:
- int main(void) {
- // 初始化相关模块
- USART_Init();
- ADC_Init();
- DMA_Init();
- APM_PBInit(BUTTON_KEY2, BUTTON_MODE_EINT); //中断行 PC10
- APM_PBInit(BUTTON_KEY1, BUTTON_MODE_EINT); //中断场 PC11
- while (1) {
- if (dmaCompleteFlag)
- {
- dmaCompleteFlag = 0;
- /* 处理采集到的数据 */
- if (currentChannel == 0){
- for (uint16_t row = 0; row < HSync_MAX; row++)
- {
- for (uint16_t i = 0; i < SAMPLES_PER_CHANNEL; i++)
- {
- printf("R[%d][%d] %d\r\n", row,i, R[row][i]);
- }
- }
- }
-
- if (currentChannel == 1){
- }
-
- if (currentChannel == 2){
- }
- printf("\r\n");
- }
- }
- }
通过上述步骤,可以成功地使用APM32F4微控制器采集VGA信号。具体的使用可能需要根据特定需求对代码进行适当的修改和优化,以实现更好的性能和数据处理能力。通过采集VGA信号,可以为后续的图像处理、显示和分析提供数据支持。希望本方案能为您的项目提供参考和借鉴。
|