DYyanfa 2024-03-27 16:06 采纳率: 31.3%
浏览 59

stc8g1k08采集电池电压异常,和实际电压值不对应

stc8g1k08采集电池电压,如下程序,当前电压为1.8V,但是ADC采集出来的值为36(见图片)


#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 Delay1ms(void)    
{
    unsigned char data i, j;

    _nop_();
    _nop_();
    _nop_();
    i = 11;
    j = 190;
    do
    {
        while (--j);
    } while (--i);
}

void ADC_BATTERY() 
{
//    unsigned char battery_percent = 0;  // 定义电量百分比变量
    float adc_res,battery_percent;
    float v_bat;
    ADC_CONTR &= 0xf0;    //底四位清零
    ADC_CONTR |= 0x0C;    //置通道12
    ADC_CONTR |= 0x40;  // 启动ADC转换
    Delay1ms;
    Delay1ms;
    Delay1ms;
    Delay1ms;
    Delay1ms;
    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.0;// 计算电池电量百分比
    UartSend(adc_res * 10);

img

  • 写回答

3条回答 默认 最新

  • 专家-皆知 2024-03-27 16:06
    关注

    引自免费微信小程序:皆我百晓生

    从您提供的代码和图片来看,问题可能出现在ADC的采样过程中。首先,ADC的采样速率应该是根据您的系统时钟来设置的,而不是固定的ADC时钟/2。其次,ADC的采样过程中可能存在一些噪声,这可能导致ADC的采集值与实际电压值不对应。

    为了解决这个问题,我建议您尝试以下步骤:

    1. 调整ADC的采样速率。您可以在ADC_Init函数中设置ADC时钟,尝试增加或减少时钟周期以提高或降低采样速率。

    2. 优化ADC的采样过程。在ADC_ISR函数中,您可以通过增加ADC转换的次数来减少噪声,从而提高采样精度。

    3. 对ADC的采样值进行滤波处理。您可以使用滤波器来减少ADC采样值中的噪声。

    下面是一个简单的C语言示例,用于演示如何使用滤波器来减少ADC采样值中的噪声:

    #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;  // 定义全局变量,用于存储采样结果
    unsigned int filter_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 Delay1ms(void)    
    {
        unsigned char data i, j;
    
        _nop_();
        _nop_();
        _nop_();
        i = 11;
        j = 190;
        do
        {
            while (--j);
        } while (--i);
    }
    
    void ADC_BATTERY() 
    {
        //    unsigned char battery_percent = 0;  // 定义电量百分比变量
        float adc_res,battery_percent;
        float v_bat;
        ADC_CONTR &= 0xf0;    //底四位清零
        ADC_CONTR |= 0x0C;    //置通道12
        ADC_CONTR |= 0x40;  // 启动ADC转换
        Delay1ms;
        Delay1ms;
        Delay1ms;
        Delay1ms;
        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.0;// 计算电池电量百分比
        UartSend(adc_res * 10);
    }
    
    void ADC_Filter() 
    {
        filter_value = ADC_Value;
        while (1)
        {
            if (ADC_Value == filter_value)
            {
                break;
            }
            filter_value = (filter_value + ADC_Value) / 2;
            Delay1ms();
        }
    }
    

    这个示例中的滤波器是一个简单的移动平均滤波器,它将ADC采样值作为输入,并计算其平均值。这有助于减少ADC采样值中的噪声。

    请注意,这只是一个示例,您可能需要根据您的具体需求进行调整。希望这可以帮助您解决问题。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 3月27日

悬赏问题

  • ¥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的航迹融合 航迹关联 航迹插补