MSPM0L1306例程学习-ADC部分(2)

发布时间:2023年12月17日

MSPM0L1306例程学习系列
使用的TI的官方例程,即SDK里边包含的例程代码。
可以到TI官网下载并且安装SDK: https://www.ti.com.cn/tool/cn/download/MSPM0-SDK/

MCU使用的是MSPM0L1306, 对于ADC部分,有10个例程:
在这里插入图片描述

前边讲了3个例程,今天讲第4个例程,使用ADC的内部通道,对系统的电源电压进行测量。 ADC模块硬件上预留有多个内部通道,可以用于系统的内部测量。如下图所示,A0-A9是连接到外部IO引脚的,其它通道是连接到内部模块的。
电源监测使用A15,系统内部将电源电压进行1/3分压之后,送到ADC模块。
在这里插入图片描述
官方的这个例程设计得一般,比大小没有太大意义,不如直接设断点看计算出的电源电压;更多可以查看下边的代码注释。

同样的,因为用了sysconfig图形配置工具,系统的初始化配置如下:
在这里插入图片描述

与前边的代码例程相比,不需要每次转换完以后都调用DL_ADC12_enableConversions(ADC12_0_INST)来使能ADC转换,即ENC=1。 因为这个例程ADC的工作模式变了,配置成单通道、多次转换模式。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
实验步骤:

  1. 下载程序;
  2. 添加查看的变量gAdcResultVolts;
  3. 设置断点,查看ADC的采样结果值(有可能被优化了),查看计算出来的电压值gAdcResultVolts;
  4. 万用表测量电源电压,对比计算出来的电压值;

在这里插入图片描述

在这里插入图片描述

添加注释后的详细代码参考如下:

/*
 * ADC转换的SDK例程
 * 文件名:adc12_monitor_supply.c
 * 描述:
 *   使用ADC内部通道(有专门的一路用于监测电源电压),测量系统的电源电压。
 *   1、单通道、多次转换、自动采样模式、软件触发;
 *   2、使用MEM0,选择ADC通道15(内部电源监控通道,取电源电压的1/3送到ADC模块)
 *   3、使用内部参考电压,2.5V
 *   4、PA0引脚连接有LED灯;
 *   5、对通道15进行AD采样和转换,根据转换结果进行LED的指示操作:
 *     a.当转换结果小于ADC12_SUPPLY_MONITOR_VALUE时,LED灭; 否则,点亮LED
 *     b.例程这个灯亮和灯灭设计的没啥意义,建议通过断点直接查看电源电压;
 *
 * 操作描述:
 *   1、下载程序;
 *   2、添加查看的变量gAdcResultVolts;
 *   3、设置断点,查看ADC的采样结果值(有可能被优化了),查看计算出来的电压值gAdcResultVolts;
 *   4、万用表测量电源电压,对比计算出来的电压值;
 *
 * 注意事项:
 *   1、从数据手册里可以查看到,电源电压监测通道为A15(内部通道);将电源电压分压后使用,1/3*VDD
 *   2、查看ADC的采样结果值,这个变量有可能被优化了,但不影响计算的电压值;思考下,怎么才能不优化?
 *
 * 思考:
 *   万用表测量电源电压,看测量值是否符合预取结果。
 *
 * 修改:
 *   基于官方的sdk例程增加注释,xie_sx@126.com
 */

#include "ti_msp_dl_config.h"

/*
 * 作为入门例程,这个宏定义把系统整复杂了;
 * 定义了这么多,最终就是想等到一个变量: ADC12_SUPPLY_MONITOR_VALUE
 * 用于将ADC的转换结果跟它进行比较;
 * 这个例程,比大小没有太大意义,不如直接设断点看计算出的电源电压;
 *
 * 能理解这个公式就行,根据AD的转换结果反算出电压;
 * gAdcResultVolts = (adcResult * ADC12_REF_VOLTAGE) / (1 << ADC12_BIT_RESOLUTION) * 3;
 *
 * (1 << ADC12_BIT_RESOLUTION) --》12位的AD,2的12次方;
 * AD的转换结果adcResult / 2的12次方,  再?参考电压ADC12_REF_VOLTAGE, 计算出当前AD的采样对应的电压;
 * 电源电压还要再?3
 */

/* clang-format off */
#define ADC12_BIT_RESOLUTION                (12)
#define ADC12_REF_VOLTAGE                   (2.5)
#define ADC12_SUPPLY_MONITOR_VOLTAGE        (2.5)
 #define ADC12_SUPPLY_MONITOR_VALUE         ( (1 << ADC12_BIT_RESOLUTION) * \
                                              (ADC12_SUPPLY_MONITOR_VOLTAGE / \
                                               (3 * ADC12_REF_VOLTAGE)))
/* clang-format on */

volatile bool gCheckADC;
volatile float gAdcResultVolts;

int main(void)
{
    uint16_t adcResult;

    //器件初始化
    SYSCFG_DL_init();

    //配置器件的中断
    NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);

    //ADC12的结果更新标志位清零
    gCheckADC = false;

    //软件启动ADC12转换
    DL_ADC12_startConversion(ADC12_0_INST);

    while (1)
    {

        //等待转换完成
        //如果标志位gCheckADC不是true,程序在while循环等待
        //gCheckADC=true后,程序继续往下执行
        while (false == gCheckADC)
        {
            __WFE();
        }

        //ADC12的结果更新标志位清零
        gCheckADC = false;

        //从结果寄存器读取本次的转换结果
        adcResult = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0);

        //将ADC的转换结果换算成电压值?
        gAdcResultVolts = (adcResult * ADC12_REF_VOLTAGE) / (1 << ADC12_BIT_RESOLUTION) * 3;

        //比较的话,还是直接用ADC的采样的结果进行比较,整型数.结果为整数以进行高效处理
        if (adcResult > ADC12_SUPPLY_MONITOR_VALUE)
        {
            DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
        }
        else
        {
            DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
        }
    }
}


/*
 * ADC12中断处理函数
 *
 * 中断里只设置结果更新标志位gCheckADC
 *
 */

void ADC12_0_INST_IRQHandler(void)
{
    switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST))
    {
        case DL_ADC12_IIDX_MEM0_RESULT_LOADED:
            gCheckADC = true;
            break;
        default:
            break;
    }
}

文章来源:https://blog.csdn.net/xie_sx/article/details/134965713
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。