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采样,在中断中获取数据,主程序进行物理量转换和显示,具有低功耗特性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/41564.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

26考研——图_图的应用(6)

408答疑 文章目录 四、图的应用图的应用考查形式最小生成树最小生成树概念最小生成树的性质最小生成树中某顶点到其他顶点是否具有最短路径的分析构造最小生成树的算法Prim 算法Prim 算法概述Prim 算法的构建思想Prim 算法的步骤Prim 算法的示例Prim 算法的性质 Kruskal 算法Kr…

Photoshop 2025安装包下载及Photoshop 2025详细图文安装教程

文章目录 前言一、Photoshop 2025安装包下载二、Photoshop 2025安装教程1.解压安装包2.运行程序3.修改安装路径4.设安装目录5.开始安装6.等安装完成7.关闭安装向导8.启动软件9.安装完成 前言 无论你是专业设计师&#xff0c;还是初涉图像处理的小白&#xff0c;Photoshop 2025…

MySQL-存储过程

介绍 基本语法 创建 调用 查看 删除 变量 系统变量 查看 设置 用户定义变量 赋值 使用 局部变量 声明 赋值 流程控制 参数 条件结构 IF case 循环结构 while repeat loop 游标 条件处理程序 介绍 举个简单的例子&#xff0c;我们先select某数据&…

debug 笔记:llama 3.2 部署bug 之cutlassF: no kernel found to launch!

1 问题描述 按照官方的写法 import torch from transformers import pipeline import os os.environ["HF_TOKEN"] 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 model_id "meta-llama/Llama-3.2-3B"pipe pipeline("text-generation", modelmode…

《Python实战进阶》No34:卷积神经网络(CNN)图像分类实战

第34集&#xff1a;卷积神经网络&#xff08;CNN&#xff09;图像分类实战 摘要 卷积神经网络&#xff08;CNN&#xff09;是计算机视觉领域的核心技术&#xff0c;特别擅长处理图像分类任务。本集将深入讲解 CNN 的核心组件&#xff08;卷积层、池化层、全连接层&#xff09;…

【银河麒麟系统常识】命令:uname -m(查看系统架构)

命令&#xff1a; uname -m 功能 常用的 Linux/Unix 终端命令&#xff0c;用于显示当前系统的硬件架构&#xff1b; 返回 返回系统的CPU架构类型&#xff0c;用于判断软件兼容性&#xff1b; 输出结果架构说明常见设备x86_64Intel/AMD 64位 CPU主流 PC、服务器aarch64ARM 64位 …

游戏引擎学习第183天

回顾和今天的计划 我对接下来的进展感到非常兴奋。虽然我们可能会遇到一些问题&#xff0c;但昨天我们差不多完成了将所有内容迁移到新的日志系统的工作&#xff0c;我们正在把一些内容整合进来&#xff0c;甚至是之前通过不同方式记录时间戳的旧平台层部分&#xff0c;现在也…

Redisson 实现分布式锁简单解析

目录 Redisson 实现分布式锁业务方法&#xff1a;加锁逻辑LockUtil 工具类锁余额方法&#xff1a;工具类代码枚举代码 RedisUtil 工具类tryLock 方法及重载【分布式锁具体实现】Supplier 函数式接口调用分析 Redisson 实现分布式锁 业务方法&#xff1a; 如图&#xff0c;简单…

鸿蒙Flutter实战:19-Flutter集成高德地图,跳转页面方式

前言 在之前的文章现有Flutter项目支持鸿蒙II中&#xff0c;介绍了如何使用第三方插件&#xff0c;同时给出了非常多的使用案例&#xff0c;如 flutter_inappwebview&#xff0c;video_player, image_picker 等&#xff0c;本文将开始介绍如何集成高德地图。 整体方案 通过 …

26考研——图_图的代码实操(6)

408答疑 文章目录 五、图的代码实操图的存储邻接矩阵结构定义初始化插入顶点获取顶点位置在顶点 v1 和 v2 之间插入边获取第一个邻接顶点获取下一个邻接顶点显示图 邻接表结构定义初始化图插入顶点获取顶点位置在顶点 v1 和 v2 之间插入边获取第一个邻接顶点获取下一个邻接顶点…

力扣32.最长有效括号(栈)

32. 最长有效括号 - 力扣&#xff08;LeetCode&#xff09; 代码区&#xff1a; #include<stack> #include<string> /*最长有效*/ class Solution { public:int longestValidParentheses(string s) {stack<int> st;int ans0;int ns.length();st.push(-1);fo…

Node.js 下载安装及环境配置教程、卸载删除环境配置超详细步骤(附图文讲解!) 从零基础入门到精通,看完这一篇就够了

Node.js 安装 一、进入官网地址下载安装包 Node.js — Download Node.js 选择对应你系统的Node.js版本&#xff0c;这里我选择的是Windows系统、64位 Tips&#xff1a;如果想下载指定版本&#xff0c;点击【以往的版本】&#xff0c;即可选择自己想要的版本下载 二、安装程序…

SQLark导出功能详解|轻松管理数据库数据与结构

SQLark 作为一款数据库管理工具&#xff0c;为用户提供了丰富且实用的导出功能。在数据库管理与开发过程中&#xff0c;数据及结构的导出操作至关重要&#xff0c;关乎数据的迁移、备份、版本管理以及问题定位等诸多关键环节。接下来&#xff0c;让我们深入了解 SQLark 的导出功…

搭建Redis主从集群

主从集群说明 单节点Redis的并发能力是有上限的&#xff0c;要进一步提高Redis的并发能力&#xff0c;就需要搭建主从集群&#xff0c;实现读写分离。 主从结构 这是一个简单的Redis主从集群结构 集群中有一个master节点、两个slave节点&#xff08;现在叫replica&#xff09;…

自然语言处理(NLP)技术的应用面有哪些

自然语言处理&#xff08;NLP&#xff09;技术在各个领域都有广泛的应用&#xff0c;以下是一些常见的例子&#xff1a; 机器翻译&#xff1a;NLP技术用于开发翻译系统&#xff0c;可以将一个语言的文本自动翻译成另一种语言。例如&#xff0c;谷歌翻译就是一个应用了NLP技术的…

element-plus 的简单应用

前言 本篇博客是 基于 ElementPlus 快速入门_element plus x-CSDN博客 的进阶 最终成果 完成的要求 1 深入学习 设计 | Element Plus 从里面找自己合适的 使用到的 组件有&#xff1a;表格&#xff0c;分页条&#xff0c;表单&#xff0c;卡片 2 具备 前端基础&#xff08;ht…

关于Qt的各类问题

目录 1、问题&#xff1a;Qt中文乱码 2、问题&#xff1a;启动时避免ComBox控件出现默认值 博客会不定期的更新各种Qt开发的Bug与解决方法,敬请关注! 1、问题&#xff1a;Qt中文乱码 问题描述&#xff1a;我在设置标题时出现了中文乱码 this->setWindowTitle("算法…

海思烧录工具HITool电视盒子刷机详解

HiTool是华为开发的一款用于海思芯片设备的刷机和调试工具&#xff0c;可对搭载海思芯片的机顶盒、智能电视等设备进行固件烧录、参数配置等操作。以下为你详细介绍&#xff1a; 功能用途 固件烧录&#xff1a;这是HiTool最主要的功能之一。它能够将下载好的适配固件文件烧录到…

Docker Compose介绍

基本概念 Docker-Compose是Docker官方的开源项目&#xff0c;负责实现对docker容器集群的快速编排。 可以这么理解&#xff0c;docker compose是docker提出的一个工具软件&#xff0c;可以管理多个docker容器组成一个应用&#xff0c;只需要编写一个YAML格式的配置文件docker…

大疆上云api直播功能如何实现

概述 流媒体服务器作为直播画面的中转站,它接收推流端的相机画面,同时拉流端找它获取相机的画面。整个流程如下: 在流媒体服务器上创建流媒体应用(app),一个流媒体服务器上面可以创建多个流媒体应用约定推拉流的地址。假设流媒体服务器工作在1935端口上面,假设创建的流…