本帖最后由 咖喱凉 于 2025-4-13 10:10 编辑
一、概述
在APM32项目开发中,我们经常需要进行高速、精确的模拟信号采样。通过使用定时器触发ADC采样,我们可以实现稳定的采样频率,这在各种数据采集应用中非常重要。本文将详细介绍如何使用APM32的定时器来触发ADC进行采样。
二、硬件要求
APM32F103系列高性能系列(如APM32F103RC、APM32F103VC等)
ADC输入信号连接到PC0引脚
三、基本原理
TIM8是APM32F103系列中的高级定时器,具有多种触发功能。我们可以配置TIM8生成TRGO(触发输出)信号,用于触发ADC1开始转换。每当定时器计数到设定值时,就会产生一个触发信号,从而启动一次ADC转换。
四、详细配置步骤1. 时钟配置
首先需要使能相关外设的时钟:
/* Enable peripheral clock */
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR8);
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA1);
2. GPIO配置
配置ADC输入引脚为模拟输入模式:
/* Configure PC0 (ADC Channel0) as analog input */
GPIO_ConfigStructInit(&gpioConfig);
gpioConfig.mode = GPIO_MODE_ANALOG;
gpioConfig.pin = GPIO_PIN_0;
GPIO_Config(GPIOA, &gpioConfig);
3. TIM8配置
配置TIM8为主模式,产生触发信号:
void TMR8_Init(void)
{
TMR_BaseConfig_T TMR_TimeBaseStruct;
/* Enable peripheral clock */
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR8);
/* configure TMR3 */
TMR_ConfigTimeBaseStructInit(&TMR_TimeBaseStruct);
TMR_TimeBaseStruct.clockDivision = TMR_CLOCK_DIV_1;
TMR_TimeBaseStruct.countMode = TMR_COUNTER_MODE_UP;
TMR_TimeBaseStruct.division = 71;
TMR_TimeBaseStruct.period = 2400;
TMR_TimeBaseStruct.repetitionCounter = 0;
TMR_ConfigTimeBase(TMR8, &TMR_TimeBaseStruct);
TMR_ConfigInternalClock(TMR8);
/* Disable TMR8 the Master Slave Mode */
TMR_DisableMasterSlaveMode(TMR8);
TMR_SelectOutputTrigger(TMR8, TMR_TRGO_SOURCE_UPDATE);
/* Enable TMR3 Interrupt */
NVIC_EnableIRQRequest(TMR8_UP_IRQn, 0, 0);
TMR_EnableInterrupt(TMR8, TMR_INT_UPDATE);
/* Enable the specified TMR peripheral */
TMR_Enable(TMR8);
}
4. ADC配置
配置ADC1使用TIM8触发:
void ADC_Init(void)
{
GPIO_Config_T gpioConfig;
ADC_Config_T adcConfig;
/* Enable GPIOA clock */
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);
/* Configure PC0 (ADC Channel0) as analog input */
GPIO_ConfigStructInit(&gpioConfig);
gpioConfig.mode = GPIO_MODE_ANALOG;
gpioConfig.pin = GPIO_PIN_0;
GPIO_Config(GPIOA, &gpioConfig);
/* ADCCLK = PCLK2/4 */
RCM_ConfigADCCLK(RCM_PCLK2_DIV_4);
/* Enable ADC clock */
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
/* ADC configuration */
ADC_Reset(ADC1);
ADC_ConfigStructInit(&adcConfig);
adcConfig.mode = ADC_MODE_INDEPENDENT;
adcConfig.scanConvMode = DISABLE;
adcConfig.continuosConvMode = DISABLE;
adcConfig.externalTrigConv = ADC_EXT_TRIG_CONV_EINT11_T8_TRGO;
adcConfig.dataAlign = ADC_DATA_ALIGN_RIGHT;
/* channel number */
adcConfig.nbrOfChannel = 1;
ADC_Config(ADC1, &adcConfig);
/* ADC channel Convert configuration */
ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_0, 1, ADC_SAMPLETIME_55CYCLES5);
/* Enable ADC DMA */
ADC_EnableDMA(ADC1);
/* Enable ADC */
ADC_Enable(ADC1);
/* Enable ADC1 reset calibration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while (ADC_ReadResetCalibrationStatus(ADC1));
/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while (ADC_ReadCalibrationStartFlag(ADC1));
/* Enable AFIO clock */
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_AFIO);
GPIO_ConfigPinRemap(GPIO_REMAP_ADC1_ETRGREG);
ADC_EnableExternalTrigConv(ADC1);
ADC_EnableInterrupt(ADC1, ADC_INT_EOC);
NVIC_EnableIRQRequest(ADC1_2_IRQn, 0, 0);
}
4. DMA配置void DMA_Init(void)
{
DMA_Config_T dmaConfig;
/* Enable DMA Clock */
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA1);
/* DMA config */
dmaConfig.peripheralBaseAddr = ADC_DR_ADDR;
dmaConfig.memoryBaseAddr = (uint32_t)&DMA_ADCConvertedValue;
dmaConfig.dir = DMA_DIR_PERIPHERAL_SRC;
dmaConfig.bufferSize = 1;
dmaConfig.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;
dmaConfig.memoryInc = DMA_MEMORY_INC_DISABLE;
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.M2M = DMA_M2MEN_DISABLE;
/* Enable DMA channel */
DMA_Config(DMA1_Channel1, &dmaConfig);
DMA_EnableInterrupt(DMA1_Channel1, DMA_INT_TC);
NVIC_EnableIRQRequest(DMA1_Channel1_IRQn, 0, 0);
/* Enable DMA */
DMA_Enable(DMA1_Channel1);
}
六、注意事项
TIM8只在APM32F103的大容量产品中可用
采样频率可用过修改TMR8更改
使用中断方式处理转换结果,避免CPU轮询等待
ADC校准对于提高采样精度很重要,不要省略
七、常见问题解答
Q:如何修改采样频率?A:可以通过调整TIM8的预分频值和周期值来改变触发频率。
Q:为什么选择55.5个采样周期?A:较长的采样时间可以提高采样精度,但会降低最大采样频率,需要权衡。
Q:如果需要采样多个通道怎么办?A:可以将ADC设置为扫描模式,并配置多个通道。
八、总结
使用TIM8触发ADC1是实现精确定时采样的有效方法。通过合理配置定时器和ADC参数,我们可以实现稳定可靠的数据采集。本文提供的代码和配置可以作为基础,根据具体需求进行修改和扩展。 |