我使用的芯片为STM32F103C8T6,所以他的ADC有2组。可以从STM32的引脚表中得知,只有ADC的1和2。
其次,手册中有表格来说明接入ADC引脚的电压与电流以及频率的范围
我所测试的是12V的锂电池,所以需要电阻来分压。我设锂电池充满电的时候为13V(以防万一出现电压过高,损坏电路)。所以,分压出来的电压为:13/36*10= 3.61V。因为到不了13V,所以不会出现高于3.6V的情况。
V-BAT所接的地方为单片机的PA5的引脚。
话不多说,直接上代码。
ADC.h
#ifndef _ADCPOWER_H_
#define _ADCPOWER_H_
#include "stm32f10x.h"
#define ADCPWOER GPIO_Pin_5
void ADC_Config(void); //配置ADC1
u16 ADC1_Read(void); //得到ADC1测到的值
u16 ADC1_ReadAverage(u8 count); //得到ADC1测到的平均值
#endif
ADC.c
#include "ADCPower.h"
void ADC_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct; //设置GPIO口结构体名称
ADC_InitTypeDef ADC_InitStruct; //设置ADC结构体名称
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能GPIOA的外设时钟
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN; //设置GPIO_Mode为模拟输入
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5; //设置GPIO_Pin为GPIO_Pin_5
//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //因为是输入,则不需要设置GPIO_Speed
GPIO_Init(GPIOA,&GPIO_InitStruct); //以上面的设置初始化GPIOA口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); //使能ADC1的外设时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC1的时钟为PCLK/6 72M/6=14M 最大为14M
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE; //设置ADC模数转换为单次工作模式
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; //设置ADC数据为右对齐
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //设置ADC转换由软件而不是外部触发启动
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent; //设置ADC工作模式为ADC1 和 ADC2 工作在独立模式
ADC_InitStruct.ADC_NbrOfChannel = 1; //设置顺序进行规则转换的 ADC 通道的数目为1
ADC_InitStruct.ADC_ScanConvMode = DISABLE; //设置ADC模数转换单次工作 /ENABLE为扫描模式,多次
ADC_Init(ADC1,&ADC_InitStruct); //以上面的设置初始化ADC1
ADC_Cmd(ADC1,ENABLE); //使能ADC1
ADC_ResetCalibration(ADC1); //重置ADC1的校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
ADC_StartCalibration(ADC1); //开启ADC1校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
}
u16 ADC1_Read(void)
{
u16 value; //定义一个无符号的16位变量
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_239Cycles5);
//设置ADC1的通道5,设置它的转化顺序为1个和采样时间为239.5 周期。
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能ADC1软件启动注入组转换功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); //转换结束
value = ADC_GetConversionValue(ADC1); //返回得到的值
return value;
}
u16 ADC1_ReadAverage(u8 count)
{
u32 Value_Sum = 0;
u8 i;
//累加读取到的数值
for(i = 0; i < count; i++)
{
Value_Sum += ADC1_Read();
}
//求出平均值并返回
return Value_Sum/count;
}
因为1lsb为VREF/4096,所以,得到的 ADC1_Read()需要乘以VREF再除以4096,所以main函数中,得到的值需要进行运算。
又因为VREF和VDD是接一起的,所以,VREF=VDD=3.3V
= ADC1_Read() * 3.3 / 4096/10 * 36