Analog to Digital Converter
,将模拟信号转换成数字的模数转换器,后面可能还会接触到DAC
,恰恰相反,是将数字信号转换成模拟信号。具体的原理可以自行找搜索引擎,可以得到更好的答案。
参考手册给出ADC的功能十分丰富,具体如下:
12 bit
分辨率,量化到0-4096
的范围;ADC
值,同样ADC
转换成功之后,便会触发ADC
中断,在中断服务子程序中,就可以读取ADC
值;触发源可以是外部信号,也可以是定时器的触发信号;标准库中注入模式的触发信号如下所示;
注入组的外部触发信号
/** @defgroup ADC_external_trigger_sources_for_injected_channels_conversion
* @{
*/
#define ADC_ExternalTrigInjecConv_T2_TRGO ((uint32_t)0x00002000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigInjecConv_T2_CC1 ((uint32_t)0x00003000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigInjecConv_T3_CC4 ((uint32_t)0x00004000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigInjecConv_T4_TRGO ((uint32_t)0x00005000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigInjecConv_Ext_IT15_TIM8_CC4 ((uint32_t)0x00006000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigInjecConv_T1_TRGO ((uint32_t)0x00000000) /*!< For ADC1, ADC2 and ADC3 */
#define ADC_ExternalTrigInjecConv_T1_CC4 ((uint32_t)0x00001000) /*!< For ADC1, ADC2 and ADC3 */
#define ADC_ExternalTrigInjecConv_None ((uint32_t)0x00007000) /*!< For ADC1, ADC2 and ADC3 */
#define ADC_ExternalTrigInjecConv_T4_CC3 ((uint32_t)0x00002000) /*!< For ADC3 only */
#define ADC_ExternalTrigInjecConv_T8_CC2 ((uint32_t)0x00003000) /*!< For ADC3 only */
#define ADC_ExternalTrigInjecConv_T8_CC4 ((uint32_t)0x00004000) /*!< For ADC3 only */
#define ADC_ExternalTrigInjecConv_T5_TRGO ((uint32_t)0x00005000) /*!< For ADC3 only */
#define ADC_ExternalTrigInjecConv_T5_CC4 ((uint32_t)0x00006000) /*!< For ADC3 only */
规则组的外部触发信号
#define ADC_ExternalTrigConv_T1_CC1 ((uint32_t)0x00000000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T1_CC2 ((uint32_t)0x00020000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T2_CC2 ((uint32_t)0x00060000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T3_TRGO ((uint32_t)0x00080000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T4_CC4 ((uint32_t)0x000A0000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO ((uint32_t)0x000C0000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T1_CC3 ((uint32_t)0x00040000) /*!< For ADC1, ADC2 and ADC3 */
#define ADC_ExternalTrigConv_None ((uint32_t)0x000E0000) /*!< For ADC1, ADC2 and ADC3 */
#define ADC_ExternalTrigConv_T3_CC1 ((uint32_t)0x00000000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T2_CC3 ((uint32_t)0x00020000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T8_CC1 ((uint32_t)0x00060000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T8_TRGO ((uint32_t)0x00080000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T5_CC1 ((uint32_t)0x000A0000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T5_CC3 ((uint32_t)0x000C0000) /*!< For ADC3 only */
从参考手册中可以看到ADC
的框架,注入通道转换成功之后,标志位JEOC
使能,然后JEOCIE
中断位被使能,最终触发ADC中断;
标准库中对于采样周期的定义;
#define ADC_SampleTime_1Cycles5 ((uint8_t)0x00)
#define ADC_SampleTime_7Cycles5 ((uint8_t)0x01)
#define ADC_SampleTime_13Cycles5 ((uint8_t)0x02)
#define ADC_SampleTime_28Cycles5 ((uint8_t)0x03)
#define ADC_SampleTime_41Cycles5 ((uint8_t)0x04)
#define ADC_SampleTime_55Cycles5 ((uint8_t)0x05)
#define ADC_SampleTime_71Cycles5 ((uint8_t)0x06)
#define ADC_SampleTime_239Cycles5 ((uint8_t)0x07)
TCONV = 采样时间+ 12.5个周期
ADC_InjectedChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_1Cycles5);
当ADCCLK=14MHz
,采样时间为1.5周期(ADC_SampleTime_1Cycles5
)
采样时间:TCONV = 1.5 + 12.5 = 14周期 = 1μs
基于ST
标准库V3.5
,实现了ADC
规则采样和注入采样两种模式;
current.h
#ifndef CURRENT_H
#define CURRENT_H
#include
#define RES_IA 1024 //采样电阻A
#define RES_IB 1024 //采样电阻B
/**
* Ia--->PA0/ADC0
* |------------>PA2/ADC2
* Ib--->PA1/ADC1
* |------------>PA3/ADC3
*/
void cur_fbk_init(void);
uint16_t cur_fbk_get_Ia(void);
uint16_t cur_fbk_get_Ia_avl(uint8_t sample_times);
uint16_t cur_fbk_get_Ib(void);
uint16_t cur_fbk_get_Ib_avl(uint8_t sample_times);
uint16_t get_inject_ia(void);
uint16_t get_inject_ib(void);
int16_t cur_fbk_get_theta(void);
#endif
current.c
#include "current.h"
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_rcc.h"
#include
#if 1
#define IA_CHANNEL_DRI ADC_Channel_0
#define IB_CHANNEL_DRI ADC_Channel_1
#else
#define IA_CHANNEL_DRI ADC_Channel_2
#define IB_CHANNEL_DRI ADC_Channel_3
#endif
volatile uint16_t Ia_val = 0;
volatile uint16_t Ib_val = 0;
static void cur_fbk_irq_init(void){
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure and enable ADC interrupt */
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
static void cur_fbk_adc_init(void){
ADC_DeInit(ADC1);
ADC_InitTypeDef ADC_InitStructure;
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 2;
/* Set injected sequencer length */
ADC_InjectedSequencerLengthConfig(ADC1, 2);
/* ADC1 injected channel Configuration */
ADC_InjectedChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_71Cycles5);
ADC_InjectedChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_71Cycles5);
//ADC_InjectedChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_71Cycles5);
//ADC_InjectedChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_71Cycles5);
/* ADC1 injected external trigger configuration */
//ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_T1_CC4);
ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_None);
//ADC_SetInjectedOffset(ADC1, ADC_InjectedChannel_1,2048);
//ADC_SetInjectedOffset(ADC1, ADC_InjectedChannel_2,2048);
/* Enable automatic injected conversion start after regular one */
ADC_AutoInjectedConvCmd(ADC1, ENABLE);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 external trigger */
ADC_ExternalTrigConvCmd(ADC1, ENABLE);
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1)){
/**
TODO
timeout_detect
*/
}
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1)){
/**
TODO
timeout_detect
*/
}
ADC_ITConfig(ADC1, ADC_IT_JEOC, ENABLE);
}
static void cur_fbk_rcc_init(void){
/* ADCCLK = PCLK2/6 */
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
/* Enable peripheral clocks ------------------------------------------------*/
/* Enable DMA1 and DMA2 clocks */
//RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 | RCC_AHBPeriph_DMA2, ENABLE);
/* Enable ADC1 and GPIOA clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
}
static void cur_fbk_pin_init(void){
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
static uint16_t cur_fbk_get_ad_val(uint8_t channel){
ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_239Cycles5 );
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能软件转换功能
//等待转换结束
/*
EOC:转换结束位 (End of conversion)
该位由硬件在(规则或注入)通道组转换结束时设置,由软件清除或由读取ADC_DR时清除
0:转换未完成;
1:转换完成。
*/
while((ADC1->SR & ADC_FLAG_EOC) != ADC_FLAG_EOC){}
//while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )){}
return ADC_GetConversionValue(ADC1); //返回最近一次 ADC1 规则组的转换结果
}
void cur_fbk_init(void){
cur_fbk_rcc_init();
cur_fbk_pin_init();
cur_fbk_irq_init();
cur_fbk_adc_init();
}
uint16_t cur_fbk_get_Ia_avl(uint8_t sample_times){
uint32_t Ia_sum = 0;
int8_t i;
for(; i < sample_times; i++){
Ia_sum+=cur_fbk_get_Ia();
}
return (uint16_t)(Ia_sum/sample_times);
}
uint16_t cur_fbk_get_Ib_avl(uint8_t sample_times){
uint32_t Ib_sum = 0;
int8_t i = 0;
for(;i < sample_times; i++){
Ib_sum+=cur_fbk_get_Ib();
}
return (uint16_t)(Ib_sum/sample_times);
}
uint16_t cur_fbk_get_Ia(void){
return cur_fbk_get_ad_val(IA_CHANNEL_DRI);
}
uint16_t cur_fbk_get_Ib(void){
return cur_fbk_get_ad_val(IB_CHANNEL_DRI);
}
int16_t cur_fbk_get_theta(void){
return 0;
}
/******************************************************************************/
/* STM32F10x Peripherals Interrupt Handlers */
/******************************************************************************/
/**
* @brief This function handles ADC1 and ADC2 global interrupts requests.
* @param None
* @retval None
*/
void ADC1_2_IRQHandler(void)
{
Ia_val = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1);
Ib_val = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_2);
/* Clear ADC1 JEOC pending interrupt bit */
ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC);
}
uint16_t get_inject_ia(void){
return Ia_val;
}
uint16_t get_inject_ib(void){
return Ib_val;
}