DYyanfa 2024-03-25 16:13 采纳率: 31.3%
浏览 15

ADC采集电池电压,转换值不正确

使用STC8G1K08实现ADC采集电池电压,输入电压稳定不变时,使用串口发送的v_bat值始终不正确,使用串口发送adc_res值基本准确,代码如下,在main.c中使用while不停调用函数void ADC_BATTERY()

#define  _ADC_C
#include "ADC.h"
#include "config.h"
#include "Uart.h"

#define ADC_RES_MAX 1024  // ADC采样最大值
#define V_REF (3.3)        // 参考电压为3.3V
#define V_BAT_MAX (2.8)     // 电池最大电压为2.8V
#define V_BAT_MIN (1.8)     // 电池最小电压为1.8V
#define V_BAT_WARN (2.1)    // 电池电量过低警告阈值为2.1V

unsigned int ADC_Value;  // 定义全局变量,用于存储采样结果
void ADC_Init() 
{
    P_SW2 |= 0x80;
    ADCTIM = 0x2A; //设置 ADC 内部时序
    P_SW2 &= 0x7f;
    ADCCFG = 0x20; //设置 ADC 时钟为系统时钟/2,右对齐
    ADC_CONTR = 0x80; //使能 ADC 模块
}

void ADC_ISR() interrupt 5 
{
    ADC_Value = (unsigned int)(ADC_RES << 8) + (unsigned int)ADC_RESL; 
    ADC_CONTR &= ~0x20; //中断标志位清0
}

void ADC_BATTERY() 
{
    unsigned char battery_percent = 0;  // 定义电量百分比变量
    float adc_res;
    float v_bat;
    ADC_CONTR &= 0xf0;    //底四位清零
    ADC_CONTR |= 0x0C;    //置通道12
    ADC_CONTR |= 0x40;  // 启动ADC转换
    adc_res = (float)ADC_Value * V_REF / ADC_RES_MAX ;// 计算ADC被转换通道的输入电压
    v_bat = adc_res * V_BAT_MAX / V_REF;// 计算电池电压值
    battery_percent = (v_bat - V_BAT_MIN)  / (V_BAT_MAX - V_BAT_MIN) * 100;// 计算电池电量百分比
    UartSend(v_bat);

  • 写回答

1条回答 默认 最新

  • 码农阿豪@新空间代码工作室 Java领域优质创作者 2024-03-25 16:14
    关注
    让阿豪来帮你解答,本回答参考chatgpt3.5编写提供,如果还有疑问可以评论或留言
    问题描述:使用STC8G1K08实现ADC采集电池电压,输入电压稳定不变时,使用串口发送的v_bat值始终不正确,使用串口发送adc_res值基本准确。 解决方案:
    1. 检查串口发送函数UartSend()是否正确实现,确保能够正确发送数据;
    2. 考虑ADC采样结果的精度问题,值得注意的是,ADC采样结果只有10位精度,需要进行一定的精度计算和处理;
    3. 确认采样电压和参考电压的值是否正确,这对于电池电压值的计算至关重要。 改进代码如下:
    #define _ADC_C
    #include "ADC.h"
    #include "config.h"
    #include "Uart.h"
    #define ADC_RES_MAX 1024  // ADC采样最大值
    #define V_REF (3.3)        // 参考电压为3.3V
    #define V_BAT_MAX (2.8)     // 电池最大电压为2.8V
    #define V_BAT_MIN (1.8)     // 电池最小电压为1.8V
    #define VOLTAGE_PRECISION (0.01) // 采样电压精度
    unsigned int ADC_Value;  // 定义全局变量,用于存储采样结果
    void ADC_Init() {
        P_SW2 |= 0x80;
        ADCTIM = 0x2A; //设置 ADC 内部时序
        P_SW2 &= ~0x7f;
        ADCCFG = 0x20; //设置 ADC 时钟为系统时钟/2,右对齐
        ADC_CONTR = 0x80; //使能 ADC 模块
    }
    void ADC_ISR() interrupt 5 {
        ADC_Value = (unsigned int)(ADC_RES << 8) + (unsigned int)ADC_RESL;
        ADC_CONTR &= ~0x20; //中断标志位清0
    }
    void ADC_BATTERY() {
        unsigned char battery_percent = 0; // 定义电量百分比变量
        float adc_res, v_bat, voltage; // 定义电压变量
        ADC_CONTR &= ~0x0f; //底四位清零
        ADC_CONTR |= 0x0C; //置通道12
        ADC_CONTR |= 0x40; // 启动ADC转换
        adc_res = (float)ADC_Value * V_REF / ADC_RES_MAX ;
        voltage = adc_res * VOLTAGE_PRECISION; // 计算采样电压值
        v_bat = voltage * (V_BAT_MAX - V_BAT_MIN) / (V_REF - V_BAT_MIN); // 计算电池电压值
        battery_percent = (v_bat - V_BAT_MIN)  / (V_BAT_MAX - V_BAT_MIN) * 100; // 计算电池电量百分比
        UartSend(battery_percent);
    }
    

    以上是对该问题的解答,代码已进行部分修改以修复相关问题。希望能对您有帮助。

    评论

报告相同问题?

问题事件

  • 创建了问题 3月25日

悬赏问题

  • ¥15 怎么把512还原为520格式
  • ¥15 MATLAB的动态模态分解出现错误,以CFX非定常模拟结果为快照
  • ¥15 求高通平台Softsim调试经验
  • ¥15 canal如何实现将mysql多张表(月表)采集入库到目标表中(一张表)?
  • ¥15 wpf ScrollViewer实现冻结左侧宽度w范围内的视图
  • ¥15 栅极驱动低侧烧毁MOSFET
  • ¥30 写segy数据时出错3
  • ¥100 linux下qt运行QCefView demo报错
  • ¥50 F1C100S下的红外解码IR_RX驱动问题
  • ¥20 基于matlab的航迹融合 航迹关联 航迹插补