欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 手游 > ambiq apollo3 ADC实例程序注释

ambiq apollo3 ADC实例程序注释

2025/3/31 9:22:47 来源:https://blog.csdn.net/xu_wenming/article/details/146505993  浏览:    关键词:ambiq apollo3 ADC实例程序注释

#include "am_mcu_apollo.h"       // Apollo MCU 外设寄存器定义和HAL库
#include "am_bsp.h"             // 板级支持包(引脚定义、LED函数等)
#include "am_util.h"            // 通用工具函数(如printf重定向)

//*****************************************************************************
//
// 全局变量
//
//*****************************************************************************
static void *g_ADCHandle;        // ADC设备句柄,用于操作ADC实例
uint32_t g_ui32SampleCount;      // ADC采样计数信号量(ISR与主程序同步)
uint16_t g_ui16ADCVDD_code;      // 电压分压器的ADC原始码值(电池电压)
uint16_t g_ui16ADCTEMP_code;     // 温度传感器的ADC原始码值

//*****************************************************************************
//
// ADC配置结构体
//
//*****************************************************************************
const static am_hal_adc_config_t g_sADC_Cfg =
{
    .eClock = AM_HAL_ADC_CLKSEL_HFRC_DIV2, // ADC时钟源选择高频RC时钟分频2(约6MHz)
    .ePolarity = AM_HAL_ADC_TRIGPOL_RISING,// 触发极性为上升沿
    .eTrigger = AM_HAL_ADC_TRIGSEL_SOFTWARE, // 触发源为软件触发(实际由Timer3触发)
    .eReference = AM_HAL_ADC_REFSEL_INT_1P5,// 内部1.5V参考电压
    .eClockMode = AM_HAL_ADC_CLKMODE_LOW_POWER, // 低功耗时钟模式
    .ePowerMode = AM_HAL_ADC_LPMODE1,       // 空闲时进入低功耗模式1
    .eRepeat = AM_HAL_ADC_REPEATING_SCAN    // 重复扫描模式(循环采样)
};

//*****************************************************************************
//
// 定时器3配置结构体(用于触发ADC采样)
//
//*****************************************************************************
am_hal_ctimer_config_t g_sTimer3 =
{
    0, // 不链接A和B定时器
    // Timer3A配置为PWM重复模式,时钟源为32Hz低频RC(LFRC)
    (AM_HAL_CTIMER_FN_PWM_REPEAT | AM_HAL_CTIMER_LFRC_32HZ),
    0  // Timer3B未使用
};

//*****************************************************************************
//
// ADC中断服务程序(ISR)
//
//*****************************************************************************
void am_adc_isr(void)
{
    uint32_t ui32IntStatus;
    
    // 获取并清除ADC中断状态
    am_hal_adc_interrupt_status(g_ADCHandle, &ui32IntStatus, true);
    am_hal_adc_interrupt_clear(g_ADCHandle, ui32IntStatus);

    am_devices_led_toggle(am_bsp_psLEDs, 3); // 切换LED3指示中断触发

    // 从ADC FIFO读取所有样本
    am_hal_adc_sample_t sSample;
    uint32_t ui32NumSamples = 1;
    while (AM_HAL_ADC_FIFO_COUNT(ADC->FIFO)) 
    {
        am_hal_adc_samples_read(g_ADCHandle, true, NULL, &ui32NumSamples, &sSample);
        
        // 根据Slot区分采样来源
        if (sSample.ui32Slot == 5) // Slot5配置为BATT通道(电池电压)
        {
            g_ui16ADCVDD_code = AM_HAL_ADC_FIFO_SAMPLE(sSample.ui32Sample);
        }
        else if (sSample.ui32Slot == 7) // Slot7配置为TEMP通道(温度传感器)
        {
            // 取高10位(精度配置为10bit),低6位舍去
            g_ui16ADCTEMP_code = sSample.ui32Sample & 0xFFC0; 
        }
    }
    g_ui32SampleCount++; // 更新采样计数(通知主程序)
}

//*****************************************************************************
//
// ADC初始化函数
//
//*****************************************************************************
void adc_init(void)
{
    am_hal_adc_slot_config_t sSlotCfg = {0};
    
    // 初始化ADC实例并获取句柄
    if (am_hal_adc_initialize(0, &g_ADCHandle) != AM_HAL_STATUS_SUCCESS) {
        am_util_stdio_printf("ADC实例初始化失败!\n");
    }
    
    // 上电ADC模块
    am_hal_adc_power_control(g_ADCHandle, AM_HAL_SYSCTRL_WAKE, false);
    
    // 应用ADC全局配置
    am_hal_adc_configure(g_ADCHandle, (am_hal_adc_config_t*)&g_sADC_Cfg);
    
    // 配置各Slot参数(0-4、6未使用)
    for (int i = 0; i <= 6; i++) {
        if (i != 5) {
            sSlotCfg.bEnabled = false;
            am_hal_adc_configure_slot(g_ADCHandle, i, &sSlotCfg);
        }
    }
    
    // 配置Slot5(BATT电压分压器)
    sSlotCfg.bEnabled = true;
    sSlotCfg.eChannel = AM_HAL_ADC_SLOT_CHSEL_BATT; // 选择BATT通道
    sSlotCfg.ePrecisionMode = AM_HAL_ADC_SLOT_14BIT;// 14位精度模式
    am_hal_adc_configure_slot(g_ADCHandle, 5, &sSlotCfg);
    
    // 配置Slot7(温度传感器)
    sSlotCfg.eChannel = AM_HAL_ADC_SLOT_CHSEL_TEMP; // 选择TEMP通道
    sSlotCfg.ePrecisionMode = AM_HAL_ADC_SLOT_10BIT;// 10位精度模式
    am_hal_adc_configure_slot(g_ADCHandle, 7, &sSlotCfg);
    
    am_hal_adc_enable(g_ADCHandle); // 使能ADC模块
}

//*****************************************************************************
//
// 定时器初始化(配置Timer3A触发ADC采样)
//
//*****************************************************************************
static void timer_init(void)
{
    #define TIMERNUM 3 // Apollo3中仅Timer3支持ADC触发
    uint32_t ui32Period = 2000; // 2000ms周期(2秒)
    
    am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_LFRC_START, 0); // 启动LFRC(32Hz)
    
    am_hal_ctimer_clear(TIMERNUM, AM_HAL_CTIMER_TIMERA); // 清除Timer3A
    am_hal_ctimer_config(TIMERNUM, &g_sTimer3);          // 应用定时器配置
    
    // 计算比较寄存器值(32Hz时钟下,2000ms对应64个计数)
    ui32Period = ui32Period * 32 / 1000; 
    am_hal_ctimer_period_set(TIMERNUM, AM_HAL_CTIMER_TIMERA, 
                            ui32Period, (ui32Period >> 1));
    
    am_hal_ctimer_adc_trigger_enable(); // 使能Timer3触发ADC
    am_hal_ctimer_start(TIMERNUM, AM_HAL_CTIMER_TIMERA); // 启动Timer3A
}

//*****************************************************************************
//
// 主函数
//
//*****************************************************************************
int main(void)
{
    // 初始化系统时钟、缓存、低功耗模式等
    am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
    am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
    am_hal_cachectrl_enable();
    am_bsp_low_power_init();
    
    // 外设初始化
    am_devices_led_array_init(am_bsp_psLEDs, AM_BSP_NUM_LEDS);
    am_hal_gpio_pinconfig(AM_BSP_GPIO_BUTTON0, g_AM_BSP_GPIO_BUTTON0);
    am_bsp_itm_printf_enable(); // 启用ITM调试输出
    
    // ADC和定时器初始化
    adc_init();
    timer_init();
    
    // 获取并打印温度校准参数(OTP中存储的工厂校准值)
    float fTrims[4];
    am_hal_adc_control(g_ADCHandle, AM_HAL_ADC_REQ_TEMP_TRIMS_GET, fTrims);
    am_util_stdio_printf("校准温度: %.3f°C, 电压: %.3fV, 偏移: %.3f\n", 
                        fTrims[0], fTrims[1], fTrims[2]);
    
    // 中断配置
    NVIC_EnableIRQ(ADC_IRQn);
    am_hal_interrupt_master_enable();
    am_hal_adc_interrupt_enable(g_ADCHandle, AM_HAL_ADC_INT_WCINC | AM_HAL_ADC_INT_FIFOOVR2);
    
    g_ui32SampleCount = 0;
    am_hal_adc_sw_trigger(g_ADCHandle); // 启动首次ADC转换
    
    // 主循环
    while (1) 
    {
        if (g_ui32SampleCount > 0) 
        {
            // 计算电池电压(基于分压比3:1)
            float fVBATT = (g_ui16ADCVDD_code * 3.0f * 1.5f) / (1024.0f / 64.0f);
            
            // 计算温度(通过HAL函数转换电压到摄氏度)
            float fVT[3] = { (g_ui16ADCTEMP_code * 1.5f) / (1024.0f * 64.0f), 0, 0 };
            am_hal_adc_control(g_ADCHandle, AM_HAL_ADC_REQ_TEMP_CELSIUS_GET, fVT);
            float fTempC = fVT[1];
            float fTempF = fTempC * 9.0f/5.0f + 32.0f; // 转换为华氏度
            
            am_util_stdio_printf("VBatt: %.2fV, Temp: %.1f°C (%.1f°F)\n", 
                                fVBATT, fTempC, fTempF);
            
            g_ui32SampleCount = 0; // 重置采样计数
        }
        
        // 进入深度睡眠,等待下次中断
        am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
    }
}

关键注解说明:

  1. ADC配置

    • 使用内部1.5V参考电压,适合测量小信号

    • 重复扫描模式实现连续采样

    • Slot5和Slot7分别对应BATT和TEMP通道,精度不同

  2. 定时器触发

    • Timer3A配置为32Hz LFRC时钟,产生2秒周期

    • 比较寄存器设置占空比50%,确保稳定触发

  3. 中断处理

    • 每次ADC完成转换后触发中断

    • 通过Slot编号区分不同通道数据

    • 原始数据存储到全局变量供主程序处理

  4. 电压计算

    c

    复制

    fVBATT = (ADC代码 * 3.0 * 1.5V) / (1024/64) 

    基于分压电阻比3:1和14位ADC量程(1.5V参考)

  5. 温度计算

    • 使用HAL库函数am_hal_adc_control直接转换

    • 公式依据Apollo3温度传感器特性曲线

  6. 低功耗设计

    • 主循环中进入DEEP SLEEP模式

    • ADC和Timer均使用低功耗时钟源

  7. 校准参数

    • 从芯片OTP中读取出厂校准值

    • 提高温度测量精度至±2°C以内

此程序实现了Apollo3芯片的电池电压监测和温度检测功能,通过定时器触发ADC采样,在中断中获取数据,主程序进行物理量转换和显示,具有低功耗特性。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词