STM32 firmware library based study notes (13) ADC voltage reading

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/weixin_43993734/article/details/101515218

About ADC

  • STM32f103 series three ADC (STM32F101 / 102 Series only one ADC), the accuracy is 12 bits, each ADC has a maximum of 16 external channels. Wherein ADC1 and ADC2 are 16 external channels, depending on the number of channels ADC3 pin CPU is different, generally having eight external channels.
  • ADC can be used independently, can also use dual mode (increasing the sampling rate). The STM32 ADC 12 is a successive approximation analog to digital converter. It has 18 channels, measure 16 and two internal external source. Each channel A / D converter can be a single, continuous, or intermittent scan mode execution. ADC can result left or right-aligned 16-bit data stored in the register. Analog watchdog feature allows application detects whether the input voltage exceeds a user-defined high / low threshold.
  • STM32F103 series have at least two ADC, we chose STM32F103ZET contains three ADC.
  • ADC maximum conversion rate of STM32 is 1Mhz, that is, conversion time of 1us (in ADCCLK = 14M, get the next sampling period is 1.5 ADC clock), do not let the ADC clock over 14M, otherwise it will lead to decline in the accuracy of the results.
  • STM32 ADC converting the two channels into groups: rules injection channel group and the channel group.

1. The input voltage range of
   the ADC input range: V REF- ≤ V IN ≤ V REF +. A V REF-, V REF +, V DDA, V SSA, four external pins determined. In the design diagram of the general ground V SSA and V REF-, V REF + and the ground V DDA 3V3, to give the ADC input voltage range: 0 ~ 3.3V.
2. input channel
STM32F103ZET6 ADC channel
3. sequentially converted
   are SQR3, SQR2, SQR1. SQR3 control rules in the first sequence to a sixth conversion, the corresponding bit is: SQ1 [4: 0] ~ SQ6 [4: 0], the first conversion bit 4: 0 SQ1 [4: 0 ], if you want to channel 16 first conversion, then SQ1 [4: 0] 16 to write. SQR2 control rules in the sequence of 7 to 12 conversion, a corresponding bit is: SQ7 [4: 0] ~ SQ12 [4: 0], if the channel one wants eighth converted, SQ8 [4: 0] 1 can write. SQR1 control rules in the sequence of the 13th to 16 conversion, a corresponding bit is: SQ13 [4: 0] ~ SQ16 [4: 0], if the channel 6 think the first 10 translated, SQ10 [4: 0] Write 6 can be. How many channels are used specifically, L SQR1 by bits [3: 0] determined, up to 16 channels.
Here Insert Picture Description
4. Trigger source
  ADC conversion can be controlled by the ADC register 2: ADON ADC_CR2 This bit is controlled, the time to start writing a conversion, the conversion is stopped when writing 0.
  ADC also supports conversion trigger, the trigger includes a trigger internal timer and external IO trigger. There are many trigger source, which specifically trigger source selection by the ADC Control Register 2: ADC_CR2 of EXTSEL [2: 0] and JEXTSEL [2: 0] bits to control. EXTSEL [2: 0] is used to select the rule trigger source channel, JEXTSEL [2: 0] for selecting a trigger source injection channel. After selecting a good trigger source, trigger source whether to activate, by the ADC Control Register 2: ADC_CR2 of EXTTRIG and JEXTTRIG two activated.
The conversion time of
   the ADC input clock generated by PCLK2 ADC_CLK after division, is the maximum 14M, frequency division factor of the configuration bit register RCC_CFGR 15:14 ADCPRE [1: 0] from the RCC clock settings, may be 2/4/6/8 frequency, 1 Note that no division. General Settings PCLK2 = HCLK = 72M. After ADC prescaler can divide only the maximum clock 12M, the sampling period is set to 1.5 cycles, converting the calculated shortest time 1.17us, this is the most common
  ADC uses a plurality of input periods ADC_CLK number of cycles voltage is sampled, the sampling time register may ADC_SMPR1 ADC sample and the SMP by ADC_SMPR2 [2: 0] bits are set, the channel control ADC_SMPR2 0 ~ 9, ADC_SMPR1 control channel is 10 to 17. Each channel can be sampled at a different time, respectively. Where the minimum sampling period is 1.5, that is, if we are to achieve the fastest sampling, the sampling period should be set to 1.5 cycles here that the cycle is 1 / ADC_CLK.
  ADC conversion time with the input clock and the ADC sampling time related formula: Tconv = +12.5 sampling time periods. When ADCLK = 14MHZ (highest), the sampling time period is set to 1.5 (the fastest), then the total conversion time (min) = 1.5 period Tconv period + 12.5 = 14 cycles = 1us.
6. Data register
  Data register ADC_DR set of rules on the data set in the injection JDRx.
7. Interrupt
   Interrupt divided into three types: regular channel switching end interrupt, the injection channel conversion conversion complete interrupt, a watchdog interrupt simulation.
8. The voltage converting
  analog voltage through the ADC, is a 12-bit numeric value, a hexadecimal print out the words, relatively poor readability through the serial port, so sometimes we need to be converted into digital voltage analog voltage, may also compare the analog voltage with the actual (measured with a multimeter), to see whether the conversion accuracy.

General configuration steps ADC work properly

1. Open GPIO clock and counter clock ADC ADC1 used, the initial ADC GPIO used.

//挂载时钟  
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1|RCC_APB2Periph_AFIO,ENABLE);
//GPIO初始化
  GPIO_InitTypeDef GPIO_InitTypeDef_PA;
  GPIO_InitTypeDef_PA.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitTypeDef_PA.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
  GPIO_Init(GPIOA,&GPIO_InitTypeDef_PA);

Note: ADC1 used herein, PA0, other specific GPIO clock clock line
2. Reset the ADC, the ADC is configured while division factor.

//复位ADC时钟
   ADC_DeInit(ADC1);
//设置 ADC1 分频因子
   RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72/6=12MHz

3. Set the operating parameters of the ADC and initialized.

//初始化ADC1参数
   ADC_InitTypeDef ADC1_InitTypeDef_PA;
   ADC1_InitTypeDef_PA.ADC_Mode = ADC_Mode_Independent;  
   ADC1_InitTypeDef_PA.ADC_ScanConvMode = DISABLE; //AD 单通道模式
   ADC1_InitTypeDef_PA.ADC_ContinuousConvMode = DISABLE;//单次模式
   ADC1_InitTypeDef_PA.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//转换由软件而不是外部触发启动
   ADC1_InitTypeDef_PA.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
   ADC1_InitTypeDef_PA.ADC_NbrOfChannel = 1;//顺序进行规则转换的 ADC 通道的数目 1
   ADC_Init(ADC1, &ADC1_InitTypeDef_PA); //根据指定的参数初始化外设 ADCx

ADC_InitTypeDef structure

typedef struct
{
u32 ADC_Mode;//设置 ADC 工作在独立或者双 ADC 模式
/*
ADC_Mode_Independent           ADC1 和 ADC2 工作在独立模式
ADC_Mode_RegInjecSimult         ADC1 和 ADC2 工作在同步规则和同步注入模式
ADC_Mode_RegSimult_AlterTrig    ADC1和ADC2工作在同步规则模式和交替触发模式
ADC_Mode_InjecSimult_FastInterl ADC1和ADC2工作在同步规则模式和快速交替模式
ADC_Mode_InjecSimult_SlowInterl ADC1和ADC2工作在同步注入模式和慢速交替模式
ADC_Mode_InjecSimult            ADC1 和 ADC2 工作在同步注入模式
ADC_Mode_RegSimult              ADC1 和 ADC2 工作在同步规则模式
ADC_Mode_FastInterl             ADC1 和 ADC2 工作在快速交替模式
ADC_Mode_SlowInterl             ADC1 和 ADC2 工作在慢速交替模式
ADC_Mode_AlterTrig              ADC1 和 ADC2 工作在交替触发模式
*/
FunctionalState ADC_ScanConvMode;//模数转换工作在扫描模式(多通道)还是单次(单通道)模式
/*
参数为 ENABLE 或者 DISABLE。
*/
FunctionalState ADC_ContinuousConvMode;//模数转换工作在连续还是单次模式
/*
参数为 ENABLE 或者 DISABLE。
*/
u32 ADC_ExternalTrigConv;//使用外部触发来启动规则通道的模数转换
/*
ADC_ExternalTrigConv_T1_CC1   选择定时器 1 的捕获比较 1 作为转换外部触发
ADC_ExternalTrigConv_T1_CC2   选择定时器 1 的捕获比较 2 作为转换外部触发
ADC_ExternalTrigConv_T1_CC3   选择定时器 1 的捕获比较 3 作为转换外部触发
ADC_ExternalTrigConv_T2_CC2   选择定时器 2 的捕获比较 2 作为转换外部触发
ADC_ExternalTrigConv_T3_TRGO  选择定时器 3 的 TRGO 作为转换外部触发
ADC_ExternalTrigConv_T4_CC4   选择定时器 4 的捕获比较 4 作为转换外部触发
ADC_ExternalTrigConv_Ext_IT11 选择外部中断线 11 事件作为转换外部触发
ADC_ExternalTrigConv_None     转换由软件而不是外部触发启动
*/
u32 ADC_DataAlign;//ADC 数据向左边对齐还是向右边对齐
/*
ADC_DataAlign_Right ADC 数据右对齐
ADC_DataAlign_Left ADC 数据左对齐
*/
u8 ADC_NbrOfChannel;//顺序进行规则转换的 ADC 通道的数目
/*
取值范围是 1 到 16
*/
} ADC_InitTypeDef

4. Enable and calibrate the ADC.

//使能ADC   
   ADC_Cmd(ADC1, ENABLE); //使能指定的 ADC1
//复位校准   
   ADC_ResetCalibration(ADC1);
//ADC 校准的
   ADC_StartCalibration(ADC1); //开始指定 ADC1 的校准状态

5. Remove the ADC value is read.

 //设置指定 ADC 的规则组通道,设置它们的转化顺序和采样时间
  ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5 ); //通道1
  //规则采样顺序值为 1,采样时间为 239.5 周期
  ADC_SoftwareStartConvCmd(ADC1,ENABLE); //使能指定的 ADC1 的软件转换功能
  while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC ));//等待转换结束
  return ADC_GetConversionValue(ADC1); //返回最近一次 ADC1 规则组的转换结果

The complete code

#include "stm32f10x.h"          
/*
  使用 ADC1 的通道 1 进行 AD 转换
   PA0 模拟输入,测量电池电压
*/
#include "stdio.h"
int fputc(int ch, FILE *f)
{
  while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
  USART_SendData(USART1,(uint8_t)ch);
  return ch;
}
void Usart_Init()
{ 
  GPIO_InitTypeDef GPIO_ITDef1;
  GPIO_InitTypeDef GPIO_ITDef;
  USART_InitTypeDef  USART_ITDef;
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
//挂载时钟(复用PA) 串口时钟使能,GPIO 时钟使能,复用时钟使能
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
//PA9 TXD初始化
  GPIO_ITDef.GPIO_Pin = GPIO_Pin_9;//PA9 TXD
  GPIO_ITDef.GPIO_Mode = GPIO_Mode_AF_PP;////复用推挽输出
  GPIO_ITDef.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA,&GPIO_ITDef);
//PA10 TXD初始化
  GPIO_ITDef1.GPIO_Pin = GPIO_Pin_10;//PA10 RXD
  GPIO_ITDef1.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA,&GPIO_ITDef1);
  
//USART初始化
  USART_ITDef.USART_BaudRate = 115200;//波特率
  USART_ITDef.USART_WordLength = USART_WordLength_8b;//发送数据长度
  USART_ITDef.USART_StopBits = USART_StopBits_1; //一个停止位   
  USART_ITDef.USART_Parity = USART_Parity_No; //无奇偶校验位     
  USART_ITDef.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  USART_ITDef.USART_Mode = USART_Mode_Tx| USART_Mode_Rx ;//发送模式 
  USART_Init(USART1,&USART_ITDef);
 
  USART_Cmd(USART1, ENABLE);//使能串口
}

void delay_ms(u16 time)
{    
   u16 i = 0;  
   while(time--)
   {
      i = 12000;  
      while(i--);    
   }
}
//这里使用的PA0可以根据情况修改
void ADC1_Init_PA0(void)
{
//挂载时钟  
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1|RCC_APB2Periph_AFIO,ENABLE);
//GPIO初始化
  GPIO_InitTypeDef GPIO_InitTypeDef_PA;
  GPIO_InitTypeDef_PA.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitTypeDef_PA.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
  GPIO_Init(GPIOA,&GPIO_InitTypeDef_PA);
    
//复位ADC时钟
   ADC_DeInit(ADC1);
//设置 ADC1 分频因子
   RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72/6=12MHz
//初始化ADC1参数
   ADC_InitTypeDef ADC1_InitTypeDef_PA;
   ADC1_InitTypeDef_PA.ADC_Mode = ADC_Mode_Independent;  
   ADC1_InitTypeDef_PA.ADC_ScanConvMode = DISABLE; //AD 单通道模式
   ADC1_InitTypeDef_PA.ADC_ContinuousConvMode = DISABLE;//单次模式
   ADC1_InitTypeDef_PA.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//转换由软件而不是外部触发启动
   ADC1_InitTypeDef_PA.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
   ADC1_InitTypeDef_PA.ADC_NbrOfChannel = 1;//顺序进行规则转换的 ADC 通道的数目 1
   ADC_Init(ADC1, &ADC1_InitTypeDef_PA); //根据指定的参数初始化外设 ADCx
//使能ADC   
   ADC_Cmd(ADC1, ENABLE); //使能指定的 ADC1
//复位校准   
   ADC_ResetCalibration(ADC1);
//ADC 校准的
   ADC_StartCalibration(ADC1); //开始指定 ADC1 的校准状态
//必须等待校验结束
  while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
  while(ADC_GetCalibrationStatus(ADC1)); //等待校 AD 准结束 
}
u16 Get_Adc(u8 ch)
{
  //设置指定 ADC 的规则组通道,设置它们的转化顺序和采样时间
  ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5 ); //通道1
  //规则采样顺序值为 1,采样时间为 239.5 周期
  ADC_SoftwareStartConvCmd(ADC1,ENABLE); //使能指定的 ADC1 的软件转换功能
  while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC ));//等待转换结束
  return ADC_GetConversionValue(ADC1); //返回最近一次 ADC1 规则组的转换结果
}
u16 Get_Adc_Average(u8 ch,u8 times)
{
  u32 temp_val=0;
  u8 t;
  for(t=0;t<times;t++)
  {    
    temp_val+=Get_Adc(ch);    
    delay_ms(5);
  }
  return temp_val/times;
}
u16 adcx;
float adcx1=0;
int main(void)
{
  ADC1_Init_PA0();
  Usart_Init();
  delay_ms(1000);
  while(1)
  {
     adcx = Get_Adc_Average(1,100);
     adcx1 = adcx*3.3/4096;
     printf("电压:%3.2f v\n",adcx1);
     delay_ms(500);    
  }     
}
Useful Information
  1. STM32F10x_StdPeriph_Lib_V3.5.0 (official firmware library)
  2. Links: "the STM32 firmware library user manual Chinese translation version of"    extraction code: 4lkx
  3. Links: (keil5 IAR and other commonly assistant)           extraction code: xzgj
  4. Links: "the STM32 Chinese Reference Manual V10"         extraction code: j748

Guess you like

Origin blog.csdn.net/weixin_43993734/article/details/101515218