一,ADC12基本原理
1.1,参考电压发生器
所有的 ADC 和 DAC 模块都需要一个基准信号,这个信号就是我们常说的 Vref+,Vref-。 MSP430 的 ADC12 模块内部带有参考电源,通过控制 REFON 信号来启动内部参考电源,并且通过 REF2_5V 控制内部参考电源产生 1.5V 或者 2.5V 的 Vref+。 最后给 ADC 模块转换器的参考电压 Vr+和 Vr-通过 SREF_x 设置 6 种组合方式: Vr+可以在 AVcc(系统模拟电源),Vref+(内部参考电源),Veref+(外部输入的参考电源)之间选择, Vr-可以在 AVss(系统模拟地),Vref-/Veref-(内部或外部参考电源)。
编者按:说白了在以上流程图可以看到,有两组基准电压选择器(SREF2和SREF1,SREF0)分别控制基准电压的“-”和“+”。
1.2,时钟发生器
这部分浩阔各种时钟信号,ADC12CLK 转换时钟,ADC12SSEL 选择内核时钟,ADC12DIV 时钟分频。 产生的ADC12CLK一方面用于转换(12-bit SAR)一方面用于生成采样时间(Sample Timer)。
1.3,转换结果存储
ADC12 一共有 12 个转换通道,设置了 16 个转换存储器用于暂时存储转换结果,合理设置后,ADC12 硬件会自动将转换的结果保存到相应的存储器里。
1.4,具有采样保持功能的 12 位模数转换内核
转换内核是有一个采样保持器和一个转换器组成。由于 ADC 转换需要一定的时间,对高速变化的信号进行瞬时采样时,不等 ADC 转换完成,外部输入的信号就已经改变。所以在 ADC 转换器前加入了采样保持器,一旦 ADC 开始转换,采样保持器则进行保持,即使现场输入的信号的变化比较快,也不会影响到 ADC 的转换工作。 12位的ADC转换器将Vr+和Vr-之间分割为2^12(4096)等份,然后将输入的模拟信号进行转换,输出0~4095 的数字。如果输入电压 Vin≤ Vr-则结果为 0,Vin≥Vr+结果为 4095。
编者按:说白了,就是上述的流程图采样保持电路(Sample and Hold)通过前面触发延时控制采样时间,而在没有触发采样时,就完成转换(12-bit SAR)。
1.5,采样转换时续控制电路
这部分浩阔各种时钟信号,ADC12CLK 转换时钟,SAMPCON 采样转换信号,SHT 控制采样周期,SHS 控制采样触发来源。 由图可以看出来 SAMPCON 信号高的时候采样,低的时候转换。而 SAMPCON 有 2 个来源,一来自采样 定时器,另一路由用户自己控制,通过 SHP 选择。
编者按:说白了,就是一个是直接控制(SHP=0)SAMPCON为高电平,转换,中间没有延时,一旦触发立刻采样转换,这样如果是连续采样,可能会导致出错。另个设置触发时间间隔保证采样触发上个电压完成,适合自动采样。
扩展采样(SHP=0)
有时序图可以看到,采样直接与触发源同步,这样如果短期再来个触发源时,不就干扰了转换时间。
脉冲采样(SHP=1)
由时序图可以看到通过采样定时器(Sample Timer)可以达到触发一次,延时采样。这样不会相互干扰。
二,寄存器设置
- 12 位转换精度,1 位非线形误差,1 位非线形积分误差
- 多种时钟源给 ADC12 模块,切本身自带时钟发生器
- 内置温度传感器
- TimerA/TimerB 硬件触发器
- 8 路外部通道和 4 路内部通道
- 内置参考电压源和 6 种参考电压组合
- 4 种模式的模数转换
- 16bit 的转换缓存
- ADC12 关闭支持超低功耗
- 采用速度快,最高 200Kbps
- 自动扫描
- DMA 使能
2.1,ADC12CTL0
ADC12ON:
ADC12 内核控制 0 关闭 ADC12 内核实现低功耗 1 开启 ADC12 内核
REFON:
内部基准电压发生器控制 0 关闭内部基准电压发生器 1 开启内部基准电压发生器
REF2_5V:
内部基准电压选择 1.5V/2.5V 0 选择 1.5V 内部参考电压 1 选择 2.5V 内部参考电压
SHT0x:
0~7 通道的采样保持器时间控制 定义了 ADC12MEM0~7 中转换采样时序与采样时钟的关系 保持时间越短,采样速度越快,反映电压波动明显 Tsample= 4×TADC12CLK×N(N13 时,N=256)
SHT1x:
8~15 通道的采样保持器时间控制 定义了 ADC12MEM8~15 中转换采样时序与采样时钟的关系 保持时间越短,采样速度越快,反映电压波动明显 Tsample= 4×TADC12CLK×N(N13 时,N=256)
MSC:
多次采样/转换控制位
当 SHP=1,CONSEQ≠0 时,MSC 位才能生效 (因为在多次采样时,必然要用采样定时进行延时,否则会出现转换数据错误,这也就是脉冲采样,然后似乎扩展采样多余的:为什么会有扩展采样,因为这是为了提高msp430的优越性,当有了扩展采样,在我们想要采样可以直接改变触发源,采样一次,而不是重复采样,节约能量)
0 每次转换需要 SHI 信号的上升沿出发采样定时器
1 首次转换需要 SHI 信号的上升沿出发采样定时器, 以后每次转换在前一次转换结束后立即进行
ADC12SC:(软件触发)
采样转换控制位
在 ENC=1,ISSH=0 的情况下:
SHP=1 时:ADC12SC 由 0 变 1 时,启动 A/D 转换,转换完成后 ADC12SC 自动复位 SHP=0 时:ADC12SC 高电平时采样,ADC12SC 复位启动一次转换
其中 ENC=1 表示转换允许,ISSH 表示输入信号为同相输入信号(一般默认为同向信号), SHP=1 表示采 样信号 SAMPCON 来自于采样定时器, SHP=0 表示 SAMPCON 采样有 ADC12SC 直接控制。
注意:当软件启动一次 A/D 转换时,ADC12SC 和 ENC 要在一条语句内完成设置。
ENC:
转换允许位 0 ADC12 为初始状态,不能启动 A/D 转换 1 首次转换由 SAMPCON 的上升沿启动
注意: [1]在 CONSEQ=0(单通道单次转换)的情况下,当 ADC12BUSY=1 时, ENC=0 则会结束转换进程,并且得到错误结果。 [2]在 CONSEQ≠0(非单通道单次转换)的情况下,当 ADC12BUSY=1 时, ENC=0 则转换正常结束,得到正确结果
ADC12TVIE:
转换时间溢出中断允许(多次采样请求) 当前转换还没有完成时,又得到一次采样请求,如果 ADC12TVIE 允许的话,会产生中断。 0 允许发生转换时间溢出产生中断 1 禁止发生转换时间溢出产生中断
ADC12OVIE:
溢出中断允许(ADC12MEMx 多次写入) 当 ADC12MEMx 还没有被读出的时候,而又有新的数据要求写入 ADC12MEMx 时, 如果允许则会产生中断 0 允许溢出中断 1 禁止溢出中断
2.2,ADC12CTL1
0
ADC12SSELx:
ADC12 时钟选择 0 ADC12OSC(ADC12 内部时钟源) 1 ACLK 2 MCLK 3 SMCLK
ADC12DIVx:
ADC12 时钟分频控制 ADC12 时钟源的分频因子选择位,分频因子为(x+1)
ISSH:
采样触发信号同向/反向 0 采样信号为同相输入 1 采样信号为反相输入
SHP:
采样信号 SAMPCON 选择 0 SAMPCON 信号来自采样触发输入信号 1 SAMPCON 信号来自采样定时器,由采样输入信号的上升沿触发
SHSx:
采样触发源选择 0 ADC12SC 1 TimerA.OUT1 2 TimerB.OUT1 3 TimerB.OUT2
CSTARTADD:
单通道模式转换通道/多通道模式守通道 定义单次转换的启始地址或者序列通道转换的首地址。
COMSEQx:
转换模式
0 单通道单次转换 1 序列通道单次转换 2 单通道多次转换 3 序列通道多次转换
ADC12BUSY:
忙标志(转换中...) 0 表示 ADC12 没有活动的操作 1 ADC12 正在采样/转换期间,忙~~
2.3,ADC12MCTLX
EOS:
多通道转换末通道标志 0 序列没有结束 1 该序列中最后一次转换
SREFx:
基准源选择 0 Vr+=AVcc, Vr-=AVss 1 Vr+=Vref+, Vr-=AVss 2,3 Vr+=Veref+, Vr-=AVss 4 Vr+=AVcc, Vr-=Vref-/Veref5 Vr+=AVcc, Vr-=Vref-/Veref6,7 Vr+=AVcc, Vr-=Vref-/Vere
INCHx:
所对应的模拟电压输入通道 0~7 A0~A7 8 Veref+ 9 Veref-/Vref10 片内温度传感器 11~15 (AVcc-AVss)/2
2.4,ADC12MEMX
该组寄存器为 12 位寄存器,用来存放 A/D 转换结果,其中只用到了低 12 位,高 4 位为 0。
2.5,有关中断寄存器
ADC12IFG 中断标志寄存器
ADC12IFGx:中断标志位 对应于 ADC12MEMx,当 A/D 转换完成后,数据被存入 ADC12MEMx,此时 ADC12IFGx 标志置位。
[6] ADC12IE 中断控制寄存器
ADC12IEx:中断允许位 对应于 ADC12IFGx,如果 ADC12IEx 允许,则当 ADC12IFGx 置位时会进入 ADC12 的中断服务程序
三,代码
ADC12 模块一共提供了 4 钟转换模式
- 单通道单次转换
- 序列通道单次转换
- 单通道多次转换
- 序列通道多次转换
注意这里的代码都是用脉冲模式,因为这样直接封装,主函数不用手调触发
3.1,单通道模式
查询方式
void ADC12_Init_0()
{
// 内核开启, 启动内部基准,选择 2.5V 基准,设置采样保持时间
//一般情况设置ADC12CTL0都是这样设置,至于那两个中断一般不设置
ADC12CTL0 = ADC12ON + REFON + REF2_5V + SHT0_2;//这里是脉冲模式
// 时钟源为内部5M振荡器, 触发采样为ADC12SC 且上升沿有效
//采样来自采样定时器, 转换地址为 ADC12MCTL4
ADC12CTL1 = ADC12SSEL_0 + SHP + CONSEQ_0+CSTARTADD_4;
// 参考电压:V+=Vref+,V-=AVss ADC 通道:A0
ADC12MCTL4 = SREF_1 + INCH_0;
ADC12CTL0 |= ENC + ADC12SC; // 转换使能开始转换
while((ADC12IFG & 0x0010) == 0); // 软件查询中断标志, 等待转换结束
/* 写处理程序 */
}
中断
unsigned int TEMP;
void ADC12_Init_0()
{
// 内核开启, 启动内部基准,选择 2.5V 基准,设置采样保持时间
//一般情况设置ADC12CTL0都是这样设置,至于那两个中断一般不设置
ADC12CTL0 = ADC12ON + REFON + REF2_5V + SHT0_2;//这里是脉冲模式
// 时钟源为内部5M振荡器, 触发采样为ADC12SC 且上升沿有效
//采样来自采样定时器, 转换地址为 ADC12MCTL4
ADC12CTL1 = ADC12SSEL_0 + SHP + CONSEQ_0+CSTARTADD_4;
// 参考电压:V+=Vref+,V-=AVss ADC 通道:A0
ADC12MCTL4 = SREF_1 + INCH_0;
// 中断允许
ADC12IE = 0x0010; //因为我们存储数据在ADC12MCTL4
_EINT();
ADC12CTL0 |= ENC + ADC12SC; // 转换使能开始转换
}
#pragma vector=ADC_VECTOR
__interrupt void ADC12ISR(void)
{
TEMP = ADC12MEM4; //读取ADC转换值
}
3.2,序列通道模式
查询方式
void ADC_Init_1(void)
{
// ADC12 控制寄存器设置
ADC12CTL0 = ADC12ON + REFON + REF2_5V+MSC + SHT0_6+SHT1_6;
// CONSEQ_1 表示当前模式为序列通道单次转换, 起始地址为 ADC12MCTL4, 结束地址 ADC12MCTL6
ADC12CTL1 = ADC12SSEL_0 + SHP + CONSEQ_1 + CSTARTADD_4;
// 转换通道设置
ADC12MCTL4 = SREF_1 + INCH_0; // 参考电压:V+=Vref+,V-=AVss ADC 通道:A0
ADC12MCTL5 = SREF_1 + INCH_1; // 参考电压:V+=Vref+,V-=AVss ADC 通道:A1
ADC12MCTL6 = SREF_1 + INCH_10 + EOS; // 参考电压:V+=Vref+,V-=AVss ADC 通道:片内温度传感器
// 启动转换
//ADC12IE = 0x0040;
// _EINT();
ADC12CTL0 |= ENC + ADC12SC; // 转换使能开始转换
while((ADC12IFG & 0x0040) == 0); // 等待转换结束也就是ADC12MCTL6中断标志
TEMP = ADC12MEM4;
}
中断
void ADC_Init_1(void)
{
// ADC12 控制寄存器设置
ADC12CTL0 = ADC12ON + REFON + REF2_5V+MSC + SHT0_6+SHT1_6;
// CONSEQ_1 表示当前模式为序列通道单次转换, 起始地址为 ADC12MCTL4, 结束地址 ADC12MCTL6
ADC12CTL1 = ADC12SSEL_0 + SHP + CONSEQ_1 + CSTARTADD_4;
// 转换通道设置
ADC12MCTL4 = SREF_1 + INCH_0; // 参考电压:V+=Vref+,V-=AVss ADC 通道:A0
ADC12MCTL5 = SREF_1 + INCH_1; // 参考电压:V+=Vref+,V-=AVss ADC 通道:A1
ADC12MCTL6 = SREF_1 + INCH_10 + EOS; // 参考电压:V+=Vref+,V-=AVss ADC 通道:片内温度传感器
// 启动转换
ADC12IE = 0x0040;
_EINT();
ADC12CTL0 |= ENC + ADC12SC; // 转换使能开始转换
// while((ADC12IFG & 0x0040) == 0); // 等待转换结束也就是ADC12MCTL6中断标志
//TEMP = ADC12MEM4;
}
#pragma vector=ADC_VECTOR
__interrupt void ADC12ISR(void)
{
TEMP=ADC12MEM6;
//读取ADC转换值
}
3.3,单通道重复模式
中断
void ADC_Init_3(void)
{
// ADC12 控制寄存器设置
// 对于多次转换需要设置 MSC
ADC12CTL0 = ADC12ON + REFON + REF2_5V + SHT0_2 + MSC;
// CONSEQ_2 表示当前模式为单通道多次转换, 转换地址为 ADC12MCTL4
ADC12CTL1 = ADC12SSEL_0 + SHP + CONSEQ_2 + CSTARTADD_4;
// 转换通道设置
ADC12MCTL4 = SREF_1 + INCH_0 + EOS; // 参考电压:V+=Vref+,V-=AVss ADC 通道:A0
// 中断允许
ADC12IE = 0x0010;
_EINT();
// 启动转换
ADC12CTL0 |= ENC + ADC12SC; // 转换使能开始转换
}
#pragma vector=ADC_VECTOR
__interrupt void ADC12ISR(void)
{
TEMP=ADC12MEM4;
//读取ADC转换值
}
3.4,多通道循环
中断
void ADC_Init(void)
{
// ADC12 控制寄存器设置
ADC12CTL0 = ADC12ON + REFON + REF2_5V + SHT0_2 +SHT1_2+ MSC;
ADC12CTL1 = ADC12SSEL_0 + SHP + CONSEQ_3 + CSTARTADD_4;
// 转换通道设置
ADC12MCTL4 = SREF_1 + INCH_0 ; // 参考电压:V+=Vref+,V-=AVss ADC 通道:A4
ADC12MCTL5 = SREF_1 + INCH_10 ; // 参考电压:V+=Vref+,V-=AVss ADC 通道:A5
ADC12MCTL6 = SREF_1 + INCH_11 + EOS; // 参考电压:V+=Vref+,V-=AVss ADC 通道:A6
// 中断允许
ADC12IE = 0x0040;
_EINT();
// 启动转换
ADC12CTL0 |= ENC + ADC12SC; // 转换使能开始转换
}
#pragma vector=ADC_VECTOR
__interrupt void ADC12ISR(void)
{
TEMP=ADC12MEM6;
//读取ADC转换值
}
|
|
2022-2-11 11:28:38
评论
举报
|
|
|