本篇博文最后修改时间:2016年10月27日,12:16。
一、简介
本文介绍如何在STM32上使用ADC1的第9通道,对电池电量进行采集。
二、实验平台
库版本:STM32F10x_StdPeriph_Lib_V3.5.0
编译软件:MDK4.53
硬件平台:STM32开发板(主芯片stm32f103c8t6)
仿真器:JLINK
三、版权声明
博主:甜甜的大香瓜
声明:喝水不忘挖井人,转载请注明出处。
原文地址:http://blog.csdn.NET/feilusia
联系方式:[email protected]
香瓜BLE之CC2541群:127442605
香瓜BLE之CC2640群:557278427
香瓜BLE之Android群:541462902
四、硬件原理
1)硬件原理图
由上图可知通过PB1口采集电压,其中采集的电压为锂电池经过分压后的电压。
锂电池电压范围为3V~4.2V。
2)采集电压引脚的通道
其中ADC12_IN9,是指可以是ADC1的第9通道,也可以是ADC2的第9通道。
五、基础知识
1、stm32f103c8t6的ADC是如何的?
答:
stm32f103c8t6这款芯片一共有2个ADC,每个ADC有18个通道,每个通道有12bit。
1、编写ADC的驱动
1)编写驱动GUA_ADC1.c(存放在“……\HARDWARE”)
//******************************************************************************
//name: GUA_ADC1.c
//introduce: ADC1驱动
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.29
//******************************************************************************
#include "stm32f10x.h"
#include "GUA_ADC1.h"
/*********************内部函数声明************************/
static GUA_U16 GUA_ADC1_Read(GUA_U8 nGUA_Channel);
//******************************************************************************
//name: GUA_ADC1_Read
//introduce: ADC1的通道数值读取
//parameter: nGUA_Channel:ADC1的采集通道
//return: 该通道采集的数值
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.29
//******************************************************************************
static GUA_U16 GUA_ADC1_Read(GUA_U8 nGUA_Channel)
{
//规则采样顺序值为1,采样时间为 239.5 周期
ADC_RegularChannelConfig(ADC1, nGUA_Channel, 1, ADC_SampleTime_239Cycles5);
//开始转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
//等待转换结束
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
//返回转换结果
return ADC_GetConversionValue(ADC1);
}
//******************************************************************************
//name: GUA_ADC1_ReadAverage
//introduce: ADC1的通道数值读取
//parameter: nGUA_Channel:ADC1的采集通道
// nGUA_times:求平均值的次数
//return: 该通道采集的数值
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.29
//******************************************************************************
GUA_U16 GUA_ADC1_ReadAverage(GUA_U8 nGUA_Channel, GUA_U8 nGUA_times)
{
GUA_U32 nGUA_Value_Sum = 0;
GUA_U8 i;
//累加读取到的数值
for(i = 0; i < nGUA_times; i++)
{
nGUA_Value_Sum += GUA_ADC1_Read(nGUA_Channel);
}
//求出平均值并返回
return nGUA_Value_Sum/nGUA_times;
}
//******************************************************************************
//name: GUA_ADC1_Init
//introduce: ADC1初始化
//parameter: none
//return: none
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.29
//******************************************************************************
void GUA_ADC1_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//开GPIOB、ADC1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_ADC1, ENABLE);
//ADC最大频率不能超过14M,否则不准,因此使用72M/6=12M
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
//IO初始化
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//ADC1配置复位
ADC_DeInit(ADC1);
//ADC1配置
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //初始化配置
//使能
ADC_Cmd(ADC1, ENABLE);
//校准
ADC_ResetCalibration(ADC1); //开启复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
ADC_StartCalibration(ADC1); //开启AD校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
}
//******************************************************************************
//name: GUA_ADC1.h
//introduce: ADC1驱动的头文件
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.29
//******************************************************************************
#ifndef _GUA_ADC1_H_
#define _GUA_ADC1_H_
/*********************宏定义************************/
#ifndef GUA_U8
typedef unsigned char GUA_U8;
#endif
#ifndef GUA_8
typedef signed char GUA_8;
#endif
#ifndef GUA_U16
typedef unsigned short GUA_U16;
#endif
#ifndef GUA_16
typedef signed short GUA_16;
#endif
#ifndef GUA_U32
typedef unsigned long GUA_U32;
#endif
#ifndef GUA_32
typedef signed long GUA_32;
#endif
#ifndef GUA_U64
typedef unsigned long long GUA_U64;
#endif
#ifndef GUA_64
typedef signed long long GUA_64;
#endif
/*********************外部函数************************/
extern GUA_U16 GUA_ADC1_ReadAverage(GUA_U8 nGUA_Channel, GUA_U8 nGUA_times);
extern void GUA_ADC1_Init(void);
#endif
2、编写电量采集的驱动
1)编写驱动GUA_Battery_Check.c(存放在“……\HARDWARE”)
//******************************************************************************
//name: GUA_Battery_Check.c
//introduce: 电量检测驱动
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.28
//******************************************************************************
#include "stm32f10x.h"
#include "GUA_ADC1.h"
#include "GUA_Battery_Check.h"
/*********************宏定义************************/
#define GUA_BATTERY_CHECK_COUNT_PER_COLLECT 5 //每次采集的次数
//******************************************************************************
//name: GUA_Battery_Check_Read
//introduce: 读电量
//parameter: none
//return: 返回16bit的电量,右对齐
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.28
//******************************************************************************
GUA_U16 GUA_Battery_Check_Read(void)
{
GUA_U16 nGUA_Battery_Check_Value = 0;
GUA_U16 nGUA_Num = 0;
//采集BATTERY_CHECK_COUNT_PER_COLLECT次,累加采集的电量值
for(nGUA_Num = 0; nGUA_Num < GUA_BATTERY_CHECK_COUNT_PER_COLLECT; nGUA_Num++)
{
//累加读取adc的转换值
nGUA_Battery_Check_Value += GUA_ADC1_ReadAverage(ADC_Channel_9, 1);
}
//求出电量平均值
nGUA_Battery_Check_Value /= GUA_BATTERY_CHECK_COUNT_PER_COLLECT;
//返回
return nGUA_Battery_Check_Value;
}
//******************************************************************************
//name: GUA_Battery_Check_Init
//introduce: 电量检测初始化
//parameter: none
//return: none
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.28
//******************************************************************************
void GUA_Battery_Check_Init(void)
{
//ADC1初始化
GUA_ADC1_Init();
}
//******************************************************************************
//name: GUA_Battery_Check.h
//introduce: 电量检测的头文件
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.28
//******************************************************************************
#ifndef _GUA_BATTERY_CHECK_H_
#define _GUA_BATTERY_CHECK_H_
/*********************宏定义************************/
#ifndef GUA_U8
typedef unsigned char GUA_U8;
#endif
#ifndef GUA_8
typedef signed char GUA_8;
#endif
#ifndef GUA_U16
typedef unsigned short GUA_U16;
#endif
#ifndef GUA_16
typedef signed short GUA_16;
#endif
#ifndef GUA_U32
typedef unsigned long GUA_U32;
#endif
#ifndef GUA_32
typedef signed long GUA_32;
#endif
#ifndef GUA_U64
typedef unsigned long long GUA_U64;
#endif
#ifndef GUA_64
typedef signed long long GUA_64;
#endif
/*********************外部函数声明************************/
GUA_U16 GUA_Battery_Check_Read(void);
void GUA_Battery_Check_Init(void);
#endif
1)工程中添加GUA_ADC1.c和GUA_Battery_Check.c
2)在MDK设置中添加驱动源文件路径
4、添加库的驱动
1)添加库的驱动文件
2)添加库的驱动头文件(stm32f10x_conf.h 中)
#include "stm32f10x_adc.h"
1)添加驱动头文件(main.c中)
#include "GUA_Battery_Check.h"
//电源电量采集
GUA_Battery_Check_Init();
3)添加测试代码
①写测试代码(main.c中)
//******************************************************************************
//name: GUA_Test
//introduce: 测试代码
//parameter: none
//return: none
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.29
//******************************************************************************
static void GUA_Test(void)
{
U16 nGUA_Battery_Check_Value = 0;
while(1)
{
//读取电量
nGUA_Battery_Check_Value = GUA_Battery_Check_Read();
}
}
//测试代码
GUA_Test();
仿真并查看测试代码中电量读取情况,如下图
上图可知读取到的电量数值为2760,由于adc的精度是12bit(4096)、参考电压为3.3V,因此实际读出的电量值为2760*3.3/4096=2.2236328125V
由于该采集电压是经过分压后的,代入公式“Vbat*75/(51+75)=2.2236328125”后,可计算出Vbat=3.735703125V。
用万用表实测锂电池电压为3.7V(200V档)。
因此实验成功。