STM32 ADC注入通道使用方法详解
最近要做市电电压波形的THD计算,同学推荐用注入通道来采集,因为对ADC的了解仅限于规则通道和软件触发,并没有接触过定时器触发,注入通道和ADC中断,所以磕磕绊绊配置了很多天,刚刚终于配置好了一路注入通道ADC采集,在这里分享一下
这一段是ADC的配置代码,触发源采用T2_TROG
#include "adc.h"
#include "sys.h"
#include "usart.h"
#include <stdio.h>
volatile uint16_t adcConvertedValue=1;
void adc_init(void)
{
// 初始化ADC1
ADC_InitTypeDef ADC_InitStructure;
NVIC_InitTypeDef NVIC_Initst;
GPIO_InitTypeDef GPIO_Initstruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div8); //ADC时钟
//配置ADC IO模式
GPIO_Initstruct.GPIO_Mode=GPIO_Mode_AIN;
GPIO_Initstruct.GPIO_Pin=GPIO_Pin_2;
GPIO_Initstruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_Initstruct);
//初始化ADC IO
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigInjecConv_T2_TRGO;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
// 使能ADC1
ADC_Cmd(ADC1, ENABLE);
/* 重置ADC校准 */
ADC_ResetCalibration(ADC1);
/* 等待初始化完成 */
while(ADC_GetResetCalibrationStatus(ADC1));
// ADC开始校准
ADC_StartCalibration(ADC1);
// 等待校准完成
while(ADC_GetCalibrationStatus(ADC1));
//注入通道配置//
ADC_InjectedSequencerLengthConfig(ADC1, 1); // 注入通道序列长度为 1
ADC_InjectedChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_55Cycles5); // 配置注入通道 0
//外部触发源设置
ADC_ExternalTrigInjectedConvConfig(ADC1,ADC_ExternalTrigInjecConv_T2_TRGO);//外部触发源设置
ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE); //设置外部触发使能
ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC); // 清除寄存器标志位
ADC_ITConfig(ADC1, ADC_IT_JEOC, ENABLE);// 使能ADC注入中断
NVIC_Initst.NVIC_IRQChannel=ADC1_2_IRQn;
NVIC_Initst.NVIC_IRQChannelCmd=ENABLE;
NVIC_Initst.NVIC_IRQChannelPreemptionPriority=0;
NVIC_Initst.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_Initst);
}
void ADC1_2_IRQHandler(void)
{
if (ADC_GetITStatus(ADC1, ADC_IT_JEOC)== SET) // 检查转换结束中断
{
if (ADC_GetFlagStatus(ADC1, ADC_FLAG_JEOC) == SET)
{
adcConvertedValue = ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_1); // 读取转换结果
printf("%hu\r\n",adcConvertedValue);
ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC); // 清除中断标志位
//ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
}
}
下面是定时器2的代码
#include "timer1.h"
#include "sys.h"
#include <stdio.h>
void TIM2_init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 1000; //设置100ms一次TIM2比较的周期
TIM_TimeBaseStructure.TIM_Prescaler = 71;//系统主频72M,这里分频720,相当于100K的定时器2时钟
TIM_TimeBaseStructure.TIM_ClockDivision = 0x00;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//下面详细说明
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//TIM_OutputState_Disable;
TIM_OCInitStructure.TIM_Pulse = 500;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//如果是PWM1要为Low,PWM2则为High
TIM_OC2Init(TIM2, & TIM_OCInitStructure);
TIM_Cmd(TIM2, ENABLE);
// 使能 TIM2 的 CC1 触发源
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_OC1);
}
下面是main函数的代码
#include "stm32f10x.h"
#include <stdio.h>
#include "delay.h"
#include "usart.h"
#include "adc.h"
#include "timer1.h"
int main(void)
{
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
adc_init();
TIM2_init();
while (1)
{
;
}
}
最后把代码链接贴这里
提取码:1eqb
第一次写博客,各位大佬多多担待
作者:轩轩&婷婷