MSP430内置ADC12模块的配置与应用
MSP430微控制器集成了一个功能丰富的ADC12模块,支持12位精度的模数转换。该模块适用于对采样精度要求适中、功耗敏感的应用场景。其主要特性包括:±1 LSB的积分非线性误差、可选时钟源(包括内部SMCLK)、内建温度传感器、多通道输入(8个外部通道和4个内部通道),以及多种参考电压组合方式。此外,它还支持自动序列采样、定时器触发启动、DMA数据传输和低功耗模式,适合实现高效的数据采集系统。
ADC12模块的转换结果可通过以下公式计算实际输入电压:
Vin = (ADC12MEM × Vref+ - Vref-) / 4096 + Vref-
其中,ADC12MEM为12位数字输出值,Vref+ 和 Vref- 分别为正负参考电压。
在使用ADC12时需特别注意采样保持阶段的时间设置。MSP430的模拟输入等效电路包含信号源内阻RS、开关电阻RI和采样电容CI(典型值约20pF)。为确保采样精度,必须保证电容在采样周期内充分充电。最小采样时间tsamp应满足:
tsamp ≥ 8 × (RS + RI) × CI
假设RI ≈ 5kΩ,CI = 20pF,若设定采样时间为4μs,则允许的最大信号源内阻约为6.8kΩ。当源阻抗较高时,应适当延长采样周期,通过调整SHT位域来增加采样时间窗口。
为了提高参考电压稳定性,TI建议在AVCC、REF+和REF-引脚附近并联去耦电容,通常采用0.1μF陶瓷电容与10μF电解电容并联的方式,以降低噪声干扰,提升转换精度。
初始化函数设计
以下是一个通用的ADC12初始化函数,支持多通道顺序采样和重复转换模式:
unsigned char Init_ADC12(unsigned char channelCount, unsigned char channelConfig[], unsigned char repeatMode)
{
if (channelCount == 0 || channelCount > 16)
return 0;
// 启动ADC模块,启用内部2.5V参考电压,设置采样时间
ADC12CTL0 = ADC12ON | REFON | REF2_5V | SHT0_0;
ADC12CTL1 = SHP | ADC12SSEL_3; // 使用SMCLK作为时钟源,采样定时器控制
for (int i = 0; i < channelCount; i++) {
*(volatile unsigned char*)(&ADC12MCTL0 + i) = channelConfig[i];
}
// 在最后一个通道设置结束标志EOS
*(volatile unsigned char*)(&ADC12MCTL0 + channelCount - 1) |= EOS;
// 配置连续或单次序列模式
if (repeatMode) {
ADC12CTL1 |= CONSEQ_3; // 重复序列模式
} else {
ADC12CTL1 |= CONSEQ_1; // 单次序列模式
}
// 开启对应中断(最后一个通道完成触发)
ADC12IE |= (1 << (channelCount - 1));
return 1;
}
参数说明:
- channelCount:参与采样的通道数量。
- channelConfig[]:每个通道的配置字节,格式如下:
| 位段 | 含义 |
|---|---|
| 7-4 (SREFx) | 参考电压选择: 000: AVCC/AVSS 001: VREF+/AVSS(内部2.5V) ... 111: 外部差分参考 |
| 3-0 (INCHx) | 输入通道选择: 0000–0111: A0–A7 1010: 温度传感器 1001: 内部地偏置检测 |
示例调用:
unsigned char config[3];
config[0] = SREF_1 + INCH_0; // A0, 使用内部2.5V参考
config[1] = SREF_1 + INCH_1; // A1
config[2] = SREF_1 + INCH_2; // A2
Init_ADC12(3, config, 1); // 三通道循环采样
启动与中断处理
初始化完成后,通过以下函数启动转换:
void Start_Conversion(void)
{
ADC12CTL0 |= ENC; // 允许转换
ADC12CTL0 |= ADC12SC; // 触发软件启动
}
当整个通道序列转换完成后,将触发ADC中断。用户可在中断服务程序中读取结果并进行后续处理:
#pragma vector = ADC_VECTOR
__interrupt void ADC_ISR(void)
{
static unsigned int index = 0;
resultBuffer[0][index] = ADC12MEM0;
resultBuffer[1][index] = ADC12MEM1;
resultBuffer[2][index] = ADC12MEM2;
index++;
if (index >= 32) { // 完成32组采样
ADC12CTL0 &= ~ENC; // 停止转换
index = 0;
Process_Data(); // 用户自定义数据处理
}
}
主程序调用示例
#include <msp430x16x.h>
#include "adc12_driver.h"
extern unsigned int resultBuffer[3][32];
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // 关闭看门狗
DCOCTL = DCO0 + DCO1; // 设置DCO频率
BCSCTL1 = RSEL2; // SMCLK = DCO
unsigned char chCfg[3] = {SREF_1 + INCH_0, SREF_1 + INCH_1, SREF_1 + INCH_2};
if (!Init_ADC12(3, chCfg, 1)) {
while(1); // 初始化失败
}
_EINT(); // 开启全局中断
Start_Conversion();
LPM0; // 进入低功耗模式0,由中断唤醒
}
该实现展示了如何利用ADC12模块完成三通道循环采样,并将每轮结果存入缓冲区。开发者可根据具体需求修改中断处理逻辑,如启用DMA传输、结合Timer_B实现周期触发或连接串口实时上传数据。