- void ADC_Init(void)
- {
- // 1. 使能GPIO和ADC时钟
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1 | RCM_APB2_PERIPH_ADC2);
- // 2. 配置模拟输入引脚
- GPIO_Config_T GPIO_ConfigStruct;
- GPIO_ConfigStructInit(&GPIO_ConfigStruct);
- GPIO_ConfigStruct.mode = GPIO_MODE_ANALOG;
- GPIO_ConfigStruct.pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4;
- GPIO_Config(GPIOA, &GPIO_ConfigStruct);
- // 3. 配置ADC1
- ADC_Config_T ADC_ConfigStruct;
- ADC_Reset(ADC1);
- ADC_ConfigStructInit(&ADC_ConfigStruct);
- ADC_ConfigStruct.mode = ADC_MODE_INJEC_SIMULT; // 注入同步模式
- ADC_ConfigStruct.scanConvMode = ENABLE; // 扫描模式
- ADC_ConfigStruct.continuousConvMode = DISABLE; // 单次转换模式
- ADC_ConfigStruct.externalTrigConv = ADC_EXT_TRIG_CONV_NONE;
- ADC_ConfigStruct.dataAlign = ADC_DATA_ALIGN_RIGHT;
- ADC_ConfigStruct.nbrOfChannel = 3;
- RCM_ConfigADCCLK(RCM_PCLK2_DIV_6); // ADCCLK = 120MHz/6 = 20MHz
-
- // 4. 配置ADC1注入通道
- ADC_ConfigInjectedSequencerLength(ADC1, 1);
- ADC_ConfigInjectedChannel(ADC1, ADC_CHANNEL_2, 1, ADC_SAMPLETIME_13CYCLES5);
- ADC_ConfigExternalTrigInjectedConv(ADC1, ADC_EXT_TRIG_INJEC_CONV_TMR1_TRGO);
-
- // 5. 配置ADC2注入通道
- ADC_Reset(ADC2);
- ADC_Config(ADC2, &ADC_ConfigStruct);
- ADC_ConfigInjectedSequencerLength(ADC2, 2);
- ADC_ConfigInjectedChannel(ADC2, ADC_CHANNEL_3, 1, ADC_SAMPLETIME_13CYCLES5);
- ADC_ConfigInjectedChannel(ADC2, ADC_CHANNEL_4, 2, ADC_SAMPLETIME_13CYCLES5);
- ADC_ConfigExternalTrigInjectedConv(ADC2, ADC_EXT_TRIG_INJEC_CONV_TMR1_TRGO);
- // 6. 使能中断并启动ADC
- ADC_EnableInterrupt(ADC1, ADC_INT_INJEOC);
- ADC_EnableInterrupt(ADC2, ADC_INT_INJEOC);
- NVIC_EnableIRQRequest(ADC1_2_IRQn, 0, 0);
-
- // 7. ADC校准与启动
- ADC_Enable(ADC1);
- ADC_ResetCalibration(ADC1);
- while (ADC_ReadResetCalibrationStatus(ADC1));
- ADC_StartCalibration(ADC1);
- while (ADC_ReadCalibrationStartFlag(ADC1));
-
- ADC_Enable(ADC2);
- ADC_ResetCalibration(ADC2);
- while (ADC_ReadResetCalibrationStatus(ADC2));
- ADC_StartCalibration(ADC2);
- while (ADC_ReadCalibrationStartFlag(ADC2));
-
- // 8. 启动注入转换
- ADC_EnableSoftwareStartInjectedConv(ADC1);
- ADC_EnableSoftwareStartInjectedConv(ADC2);
- }
3.2 定时器触发配置
定时器 TMR1 配置为中心对齐模式,生成周期性触发信号:
- void TMR_Init(void)
- {
- // 1. 使能定时器和GPIO时钟
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR1);
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA | RCM_APB2_PERIPH_GPIOB);
- // 2. 配置PWM输出引脚(可用于电机控制等应用)
- GPIO_Config_T gpioConfig;
- gpioConfig.speed = GPIO_SPEED_50MHz;
- gpioConfig.mode = GPIO_MODE_AF_PP;
- gpioConfig.pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10; // PWM输出引脚
- GPIO_Config(GPIOA, &gpioConfig);
- // 3. 配置定时器基本参数
- TMR_BaseConfig_T tmrBaseConfig;
- tmrBaseConfig.countMode = TMR_COUNTER_MODE_CENTERALIGNED1; // 中心对齐模式
- tmrBaseConfig.clockDivision = TMR_CLOCK_DIV_1;
- tmrBaseConfig.period = 999; // 周期值
- tmrBaseConfig.division = 11999; // 预分频值
- tmrBaseConfig.repetitionCounter = 1; // 重复计数器
- TMR_ConfigTimeBase(TMR1, &tmrBaseConfig);
- // 4. 配置PWM输出模式(示例)
- TMR_OCConfig_T tmrOCConfig;
- tmrOCConfig.mode = TMR_OC_MODE_PWM2;
- tmrOCConfig.outputState = TMR_OC_STATE_ENABLE;
- tmrOCConfig.outputNState = TMR_OC_NSTATE_ENABLE;
- tmrOCConfig.pulse = 500; // 占空比50%
- TMR_ConfigOC1(TMR1, &tmrOCConfig);
- TMR_ConfigOC2(TMR1, &tmrOCConfig);
- TMR_ConfigOC3(TMR1, &tmrOCConfig);
- // 5. 配置触发输出(关键步骤)
- TMR_SelectOutputTrigger(TMR1, TMR_TRGO_SOURCE_UPDATE); // 使用更新事件作为触发源
- // 6. 配置死区时间(用于互补PWM输出)
- TMR_BDTConfig_T TIM_BDTRStruct;
- TIM_BDTRStruct.deadTime = 0x1D; // 约2μs死区时间
- TIM_BDTRStruct.BRKState = TMR_BRK_STATE_DISABLE;
- TMR_ConfigBDT(TMR1, &TIM_BDTRStruct);
- // 7. 使能定时器和PWM输出
- TMR_EnablePWMOutputs(TMR1);
- TMR_Enable(TMR1);
- }
3.3 中断处理机制
ADC 转换完成后触发中断,在中断服务函数中读取采样值并进行处理:
- void ADC1_2_IRQHandler(void)
- {
- // 1. 标记中断进入(用于调试)
- GPIO_SetBit(GPIOC, GPIO_PIN_13);
- // 2. 处理ADC1注入通道转换完成事件
- if (ADC_ReadIntFlag(ADC1, ADC_INT_INJEOC) == SET)
- {
- uint16_t adc1_value = ADC_ReadInjectedConversionValue(ADC1, ADC_INJEC_CHANNEL_1);
- float voltage = (float)adc1_value / 4095 * 3.3; // 转换为电压值
- printf("ADC1 (PA2) Data: %d, Voltage: %.3f V\r\n", adc1_value, voltage);
- ADC_ClearIntFlag(ADC1, ADC_INT_INJEOC); // 清除中断标志
- }
- // 3. 处理ADC2注入通道转换完成事件
- if (ADC_ReadIntFlag(ADC2, ADC_INT_INJEOC) == SET)
- {
- uint16_t adc2_ch3 = ADC_ReadInjectedConversionValue(ADC2, ADC_INJEC_CHANNEL_1);
- uint16_t adc2_ch4 = ADC_ReadInjectedConversionValue(ADC2, ADC_INJEC_CHANNEL_2);
- printf("ADC2 (PA3) Data: %d, Voltage: %.3f V\r\n", adc2_ch3, adc2_ch3*3.3/4095);
- printf("ADC2 (PA4) Data: %d, Voltage: %.3f V\r\n", adc2_ch4, adc2_ch4*3.3/4095);
- ADC_ClearIntFlag(ADC2, ADC_INT_INJEOC); // 清除中断标志
- }
- // 4. 标记中断处理完成
- GPIO_ResetBit(GPIOC, GPIO_PIN_13);
- }
四、测试结果
定时器 TMR1 的计数频率:120MHz / (11999+1) = 10kHz
实际采样频率:10kHz × 2 = 20kHz
每个 ADC 通道的采样时间:1/20kHz = 50μs
#申请原创#
@21小跑堂