TI【LP_MSPM0L1306开发板】测评——ADC使用以及示例学习
本帖最后由 EPTmachine 于 2023-10-15 13:47 编辑<h1>ADC使用和示例学习</h1>
<p>MSPM0L1306在TI的产品推荐中时针对低功耗的模拟增强型产品,其ADC模块的特性包括:</p>
<p>• 12 位输出分辨率,速率高达 1.45MSPS 且 ENOB 大于 11 位</p>
<p>• 多达 10 个外部输入通道</p>
<p>• 内部通道用于温度检测、电源监测和模拟信号链(与 OPA、GPAMP 或其他的互连)</p>
<p>• 软件可选基准:</p>
<p>– 1.4V 和 2.5V 的可配置内部专用 ADC 基准电压 (VREF)</p>
<p>– MCU 电源电压 (VDD)</p>
<p>– 通过 VREF+和 VREF- 引脚为 ADC 提供外部基准</p>
<p>• 在运行、睡眠和停止模式下运行,并支持从待机模式触发</p>
<h2>硬件概述</h2>
<p>在数据手册中可以确定各个通道的信号映射关系如下图</p>
<p></p>
<p>在TI提供的示例程序中,对ADC在不同配置模式下的使用给出了示例代码,这可以帮助我们快速上手ADC的使用。关于具体原理可以参考MSPM0的用户手册。</p>
<p></p>
<h2>ADC单次采样</h2>
<p>代码示例adc12_single_conversion_vref_internal演示了使用ADC进行单次采样,采样完成后,读取转接结果寄存器中的值,当测量值大于参考电压的一半时,点亮LED1,当测量值小于参考电压的一半时,熄灭LED1。</p>
<p>ADC的参考电压选择为内部参考电压2.5V。</p>
<p></p>
<p>由于代码示例在上电后使用默认时钟频率</p>
<p>默认 CPU 时钟为 MCLK = SYSOSC ~32MHz。默认 LFCLK = LFOSC ~32kHz。ADCCLK 通过 ADC 模块初始化设置为 SYSOSC。</p>
<p>在原理图上可以确定LED1连接在PA0上,PA0为低电平时,LED1点亮。</p>
<p></p>
<p>在SysConfig中对PA0的配置如下图所示</p>
<p></p>
<p>在SysConfig中对ADC0的参数进行配置,时钟源选择为SYSISC,对其进行8分频,采样时间设置为500ADCCLK。采样模式为单次采样,触发方式为软件触发。</p>
<p></p>
<p>ADC转换时使用控制块0,转换通道为12,分辨率选择为12位分辨率,开启转换结果完成中断,具体的配置如下图所示。</p>
<p></p>
<p>通过查看数据手册可知,该通道对应的管脚为PA25。</p>
<p></p>
<p></p>
<p>主程序的实现逻辑位等待ADC采样中断函数置位相关的控制变量,然后读取转换结果寄存器中的ADC采样值,由于分辨率位12,采样值的变化范围为0-4096,所以量程范围内的中间值为0x7FF(2047),采样结果与该值对比,大于该值点亮LED1,小于该值熄灭LED1。然后启动下一次ADC采样。代码如下所示:</p>
<pre>
<code class="language-cpp">#include "ti_msp_dl_config.h"
volatile bool gCheckADC;
uint16_t adcResult;
int main(void)
{
adcResult=0;
SYSCFG_DL_init();
NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
gCheckADC = false;
/* Confirm VREF has settled before triggering ADC12 conversion */
while (DL_VREF_CTL1_READY_NOTRDY == DL_VREF_getStatus(VREF))
;
while (1) {
DL_ADC12_startConversion(ADC12_0_INST);
while (false == gCheckADC) {
//__WFE();
}
adcResult = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0);
if (adcResult > 0x7ff) {
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);
}
gCheckADC = false;
DL_ADC12_enableConversions(ADC12_0_INST);
}
}
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;
}
}</code></pre>
<p>使用信号发生器在PA25引脚输入模拟信号,示例的效果视频如下:</p>
<p>ee84dec323dcf4df76f8bc3ea5b56cb5<br />
</p>
<h2>ADC窗口比较模式</h2>
<p>MSPM0的ADC模块具有比较器功能,设置比较器的上限值和下限值,完成采样后的采样值与这两个值进行对比。在SysConfig中,控制LED1的PA0的配置如图所示。</p>
<p></p>
<p>ADC的采样时钟为SYSOSC,分频系数设置为4,采样模式为软件自动触发的单次采样。</p>
<p></p>
<p>ADC的转换控制块选择为0,参考电压选择为VDDA(3.3V),启用比较器模式。</p>
<p></p>
<p>设置比较器的上限值和下限值为同一数值,同时开启比较器阈值判断中断。</p>
<p></p>
<p>主程序的逻辑在初始化外设并开启ADC采样后,等待比较器中断发生,并在中断函数改变LED1控制引脚的状态。主程序的源代码如下:</p>
<pre>
<code class="language-cpp">#include "ti_msp_dl_config.h"
int main(void)
{
SYSCFG_DL_init();
NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
DL_ADC12_startConversion(ADC12_0_INST);
DL_SYSCTL_enableSleepOnExit();
while (1) {
__WFI();
}
}
void ADC12_0_INST_IRQHandler(void)
{
switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) {
case DL_ADC12_IIDX_WINDOW_COMP_HIGH:
DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
break;
case DL_ADC12_IIDX_WINDOW_COMP_LOW:
DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
break;
default:
break;
}
}</code></pre>
<p>程序的演示效果如视频所示:</p>
<p>d36d50105480fc816e2e6bdc1cc95acc<br />
</p>
<h2>总结</h2>
<p>MSPM0的ADC模块除了基本的ADC采样功能外,提供了额外的高级比较功能,可以以更少的CPU资源来实现相同的功能,目前对其功能进行了简单的了解,网站上丰富的示例工程展示了不同的ADC应用,可以帮助用户快速上手ADC的使用。</p>
<p>网站上丰富的示例工程展示了不同的ADC应用,可以帮助用户快速上手ADC的使用。</p>
<p>认真学习了其中的一个。</p>
lugl4313820 发表于 2023-10-15 20:46
网站上丰富的示例工程展示了不同的ADC应用,可以帮助用户快速上手ADC的使用。
认真学习了其中的一个。
<p>TI的文档做的确实很贴心,结合开发手册和示例程序,开发者可以很快地实现相应地功能。</p>
EPTmachine 发表于 2023-10-15 21:29
TI的文档做的确实很贴心,结合开发手册和示例程序,开发者可以很快地实现相应地功能。
<p>分布讲解的也很细致,重要的是还有中文文档,就是有时候在线查询那里连接不稳定</p>
<p>有没有朋友实现多个采样通道+DMA传输的呢</p>
页:
[1]