电子说
在嵌入式开发中,电流检测是一个常见需求。本文详细介绍如何使用 STM32F103C8T6 驱动 ACS712 霍尔效应电流传感器 ,并完成1-5A电流的实测验证。
ACS712 是一款基于霍尔效应的电流传感芯片,用来测量直流或交流电流。它通过内部导体感应电流产生的磁场,再由霍尔元件转换成与电流成比例的模拟电压输出(一般以 Vcc/2 为零点)。该芯片具有电气隔离、安全性高、响应速度快的特点,常见量程有 ±5A、±20A、±30A,广泛用于电源监测、电机控制和过流检测等场景。


| 引脚 | 功能 | 连接 |
|---|---|---|
| VCC | 电源正极 | 接 5V |
| OUT | 模拟输出 | 接 STM32 PA0(ADC 输入) |
| GND | 电源负极 | 共地 |
| IP+ | 电流输入 | 检测电路电流输入 |
| IP- | 电流输出 | 检测电路电流输出 |
| ACS712 | STM32F103C8T6 | OLED |
|---|---|---|
| VCC(外部电源接5V) | -- | -- |
| OUT | 分压后接到PA0 | -- |
| GND(外部电源接地) | GND | GND |
| -- | 3.3V | VCC |
| -- | PB8 | SCL |
| -- | PB9 | SDA |

①这里检测电路和板子供电的5V建议分开供电。
②在PA0对地之间可以加个0.1uF的独石电容,增加稳定性。
③加分压电路的原因:5A电流时,OUT输出电压理论值3.425V已经超过STM32的采样电压3.3V了,因此需要加分压电路。

STM32F103C8T6驱动ACS712电流检测(标准库代码)。
#include "stm32f10x.h" // Device header
/**
* 函 数:AD初始化
* 参 数:无
* 返 回 值:无
*/
void AD_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //开启ADC1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*设置ADC时钟*/
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA0引脚初始化为模拟输入
/*规则组通道配置*/
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); //规则组序列1的位置,配置为通道0
/*ADC初始化*/
ADC_InitTypeDef ADC_InitStructure; //定义结构体变量
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //模式,选择独立模式,即单独使用ADC1
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据对齐,选择右对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //外部触发,使用软件触发,不需要外部触发
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //连续转换,失能,每转换一次规则组序列后停止
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //扫描模式,失能,只转换规则组的序列1这一个位置
ADC_InitStructure.ADC_NbrOfChannel = 1; //通道数,为1,仅在扫描模式下,才需要指定大于1的数,在非扫描模式下,只能是1
ADC_Init(ADC1, &ADC_InitStructure); //将结构体变量交给ADC_Init,配置ADC1
/*ADC使能*/
ADC_Cmd(ADC1, ENABLE); //使能ADC1,ADC开始运行
/*ADC校准*/
ADC_ResetCalibration(ADC1); //固定流程,内部有电路会自动执行校准
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
/*开始校准*/
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
}
/**
* 函 数:获取AD转换的值
* 参 数:无
* 返 回 值:AD转换的值,范围:0~4095
*/
uint16_t AD_GetValue(void)
{
/*开始转换*/
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //软件触发AD转换一次
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); //等待EOC标志位,即等待AD转换结束
return ADC_GetConversionValue(ADC1); //读数据寄存器,得到AD转换的结果
}
/**********************************************
***基于STM32F103C8T6单片机驱动ACS712模块进行电流检测***
注意:启动时电流必须是0A电流,程序会在启动时获取0电流下的零点值带入后面的计算;
如果启动不是零点值,需要在重新启动读取0电流值计算才可以读数正确(或者自己更换后面计算的V_zero数值)
| ACS712 |STM32F103C8T6 | OLED|
| VCC(外部电源接5V) | -- | -- |
| OUT | 分压后接到PA0 | -- |
| GND(外部电源接地) | GND | GND |
| -- | 3.3V | VCC |
| -- | PB8 | SCL |
| -- | PB9 | SDA |
**********************************************/
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"
uint16_t ADValue; //定义AD值变量
float Voltage,Vsensor,Current; //定义电压,电流变量
float sum = 0;
float V_zero; //定义零点电压变量
int main(void)
{
/*模块初始化*/
OLED_Init(); //OLED初始化
AD_Init(); //AD初始化
/*显示静态字符串*/
OLED_ShowString(1, 1, "ADValue:"); //ad采样值
OLED_ShowString(2, 1, "Voltage:0.00V"); //读取电压值
OLED_ShowString(3, 1, "Vsensor:0.00V"); //OUT输出实际电压值
OLED_ShowString(4, 1, "Current:0.00A"); //转换出来的电流值
for(int i=0;i< 20;i++)
{
sum += AD_GetValue();
}
ADValue = sum / 20;
sum = 0;
V_zero = (float)ADValue / 4095 * 3.3 * 2.0f;//获取无电流下的零点电压值
while (1)
{
/*滤波处理*/
for(int i=0;i< 20;i++)
{
sum += AD_GetValue();
}
ADValue = sum / 20; //获取AD转换的平均值
sum = 0;
// ADValue = AD_GetValue(); //获取AD转换的值
Voltage = (float)ADValue / 4095 * 3.3; //将AD值线性变换到0~3.3的范围,表示电压
Vsensor = Voltage * 2.0f;
Current = (Vsensor - V_zero) / 0.185f; //获取读出的电压,换算成电流
OLED_ShowNum(1, 9, ADValue, 4); //显示AD值
OLED_ShowNum(2, 9, Voltage, 1); //显示读取电压值的整数部分
OLED_ShowNum(2, 11, (uint16_t)(Voltage * 100) % 100, 2); //显示读取电压值的小数部分
OLED_ShowNum(3, 9, Vsensor, 1); //显示OUT电压值的整数部分
OLED_ShowNum(3, 11, (uint16_t)(Vsensor * 100) % 100, 2); //显示OUT电压值的小数部分
OLED_ShowNum(4, 9, Current, 1); //显示电流值的整数部分
OLED_ShowNum(4, 11, (uint16_t)(Current * 100) % 100, 2); //显示电流值的小数部分
Delay_ms(300); //延时300ms,手动增加一些转换的间隔时间
}
}


如果觉得有帮助,欢迎点赞
全部0条评论
快来发表一下你的评论吧 !