MSP430的ADC12模块使用及代码(寄存器)

        以我的MSPf5529LP为例,它有A0-A15共计16个输入通道,其中有12个是外部通道。与之相应地,ADC12部分有相当多的各种寄存器,接下来一一介绍,最后依然附上一些代码。

目录

寄存器介绍

ADC12CTLn                ADC12MEMx                ADC12MCTLx

ADC12IE                     ADC12IFG                    ADC12IV

例程

温度传感器                  灰度传感器

总结


寄存器介绍

        由于其为数众多的通道数,ADC12有相当可观数量的寄存器,但是去除重合的一些后只有6个,它们分别负责处理一些功能。

ADC12CTLn

        它分为CTL0、CTL1、CTL2。三者的功能区别也不小,分别介绍一下。然后ADC12CTL0的设置很多,ADC12CT1和ADC12CTL2的操作我用到不多,查到的资料也不多,所以对它的讲解会和机翻很像。

        ADC12CTL0

ADC12SHTnx

这一位寄存器控制采样时间的长度

ADC12SHT1x负责通道8-15,ADC12SHT0x负责通道0-7

二者都是4位的,所以可以写出0-15的所有数字

ADC12SHTnx = xxxx b(四位二进制数),如果将二进制数化为十进制数y

那么采样时间的长度即为2^(2+y)个ADC12CLK时钟周期长度

ADC12MSC

如果机翻的话翻成混合采样,实际上就是连续采样,只在多通道或连续采样时才可用

0  采集到SHI的上升沿信号时触发采样和转换

1  在第一次采集到SHI上升信号后,每次采样转换完成立刻执行下一次

ADC12REF2_5V

控制参考电压(只在下面那个REFON置1时可用)

0  参考电压为1.5V

1  参考电压为2.5V

ADC12REFON

是否选择参考

0  不选择

1  选择使用参考

ADC12ON

打开ADC12_A

0  关闭

1  打开

ADC12OVIE

ADC12MEMx(储存x通道采集到的数据的寄存器,后面会说)的溢出中断使能,如果设置这位的话GIE中断也要配一下

0  失能

1  使能

ADC12TOVIE

ADC12转换超时(时间的“溢出”)使能,如果设置这位的话GIE中断也要配一下

0  失能

1  使能

这一位和上一位用的都很少

ADC12ENC

使能转换,这一位的地位有些特殊

0  失能

1  使能

所有其他寄存器的更改配置操作都要在这一位为0时配置

ADC12SC

启动转换,它会在开始后自动复0,所以要在循环里手动置1

0  不要开始采样

1  开始采样

        ADC12CTL1

ADC12CSTARTADDx数据起始地址,从0到F,对应MEM0-MEM15
ADC12SHSx

采样-保持源的选择

00  ADC12SC

01  10  11  这三个取决于具体型号

ADC12SHP

采样-保持 脉冲-模式选择

0  SAPCON信号源自采样输入信号

1  SAMPCON信号源自采样定时器

ADC12ISSH

反转采样信号(0和1反转)

0  不反转

1  反转

ADC12DIVx分频系数。有三位,所以可以1-8分频
ADC12SSELx

选择时钟,同样是ACLK和SMCLK更常用

00  ADC12OSC(MODCLK)

01  ACLK

10  MCLK

11  SMCLK

ADC12CONSEQx

转换模式,这个根据实际需要来使用

00  单通道单采集

01  多通道单采集

10  单通道多采集

11  多通道多采集

ADC12BUSY

标志当前是否有操作

0  无操作

1  有操作

        ADC12CTL2

ADC12PDIV

控制时钟预分频系数

0  1分频(不分频)

1  4分频

ADC12TCOFF

控制ADC12外接的温度传感器,不用的话最好关闭省电,置1才是关闭

注意:这一位只有在REFMSTR置0时才可用

0  开启

1  关闭

ADC12RES

这个位定义了转换结果分辨率

00  8位(9个时钟周期转换时间)

01  9位(11个时钟周期转换时间)

10  10位(13个时钟周期转换时间)

11  保留(就是暂时先不用)

ADC12DF

数据回读格式

0  无符号

1  有符号

ADC12SR

配置采样率

0  最高约200kps

1  最高约50kps

ADC12REFOUT

参考输出,只在REFMSTR置0时有效

0  关闭

1  开启

ADC12REFBURST

设置缓冲器的

0  持续打开缓冲器

1  只在采样转换时打开缓冲器

ADC12MEMx

         就是通过前面ADC12CSTARTADDx那一位寄存器控制送到这些寄存器里以供使用。

ADC12MCTLx

ADC12EOS

表明是采样序列的最后一个,这样说可能有些抽象,看一下代码就清楚了

0  不是结尾

1  是结尾

ADC12SREFx选择参考,一共有8个,全部贴出来太多了
ADC12INCHx选择输入通道,四位对应到A0-A7,内部参考,A13-A15共计十五个通道

ADC12IE

        看着很哈人,但是实际上只要使能你需要的通道就可以了,并不麻烦。

ADC12IFG

         当对应的通道号引起中断后,对应IFG置1。

ADC12IV

         类似于TAxIV,它也可以记录到底是哪一位引起了中断。


例程

        有关寄存器的介绍终于算是结束了,这么多的内容可能对阅读不那么友好,接下来跟着例程看寄存器怎么配置,AD采集的例子不多,全部都是抽象的也不太好,结合具体的外设来看。我介绍两个,一个温度传感器,一个灰度传感器,正好契合一个单通道采集和一个多通道采集。

温度传感器

        这个传温度的传感器跳动可能比较大,我自己测的时候一直在27℃-29℃跳变。具体想要查看温度数值的话可以debug,在观察窗口里面看,或者添加一个OLED也可以,我自己是加了OLED的,但是因为本篇的篇幅太长了,于是将之删去。

#include <msp430.h>

#define CALADC12_15V_30C  *((unsigned int *)0x1A1A)   
#define CALADC12_15V_85C  *((unsigned int *)0x1A1C)   
//这两个宏定义用于温度校准使用,不必在意,校准30和85
#define REF_30C CALADC12_15V_30C
#define REF_85C CALADC12_15V_85C

unsigned int temp;
volatile float temperatureDegC;
volatile float temperatureDegF;
//volatile类型的变量主要是因为单片机访问机制的问题,如果不加上这一位可能导致读取的数据不变
int main(void)
{
    WDTCTL = WDTPW + WDTHOLD;                 
    REFCTL0 &= ~REFMSTR;                      // 将REFMSTR置0以设置参考
    ADC12CTL0 = ADC12ON + ADC12SHT0_8 + ADC12REFON ;  
//打开ADC12;设置采样时间;开启参考(未设置ADC12REF2_5V位,故参考电压1.5V)
    ADC12CTL1 = ADC12SHP;                     // 以采样定时器为SAMPCON信号源
    ADC12IE = 0x001;                          // 使能MEM0的IFG中断
    __delay_cycles(100);                      // 等待ref设置完成
    ADC12CTL0 |= ADC12ENC;

  while(1)
  {
    ADC12CTL0 &= ~ADC12SC;                  // 手动停止上一次采集
    ADC12CTL0 |= ADC12SC;                   // 重新开始新的一次

    __bis_SR_register(LPM4_bits + GIE);     // 进入低功耗模式4并使能中断(等待采样完成)
//在中断结束后会自动退出低功耗模式,就进入了下面的计算
    temperatureDegC=(float)(((long)temp-REF_30C)*(85 - 30))/(REF_85C - REF_30C)+30.0f;
    temperatureDegF = temperatureDegC * 9.0f / 5.0f + 32.0f;

  }
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC12_VECTOR
__interrupt void ADC12ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC12_VECTOR))) ADC12ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(ADC12IV,34))
  {
  case  0: break;                           // Vector  0:  无
  case  2: break;                           // Vector  2:  ADC 溢出
  case  4: break;                           // Vector  4:  ADC 超时
  case  6:                                  // Vector  6:  ADC12IFG0
    temp = ADC12MEM0;                       
    __bic_SR_register_on_exit(LPM4_bits);   
           break;
  case  8: break;                           // Vector  8:  ADC12IFG1
  case 10: break;                           // Vector 10:  ADC12IFG2
  case 12: break;                           // Vector 12:  ADC12IFG3
  case 14: break;                           // Vector 14:  ADC12IFG4
  case 16: break;                           // Vector 16:  ADC12IFG5
  case 18: break;                           // Vector 18:  ADC12IFG6
  case 20: break;                           // Vector 20:  ADC12IFG7
  case 22: break;                           // Vector 22:  ADC12IFG8
  case 24: break;                           // Vector 24:  ADC12IFG9
  case 26: break;                           // Vector 26:  ADC12IFG10
  case 28: break;                           // Vector 28:  ADC12IFG11
  case 30: break;                           // Vector 30:  ADC12IFG12
  case 32: break;                           // Vector 32:  ADC12IFG13
  case 34: break;                           // Vector 34:  ADC12IFG14
  default: break;
  }
}

灰度传感器

        是P6.0到P6.4五个引脚,对应五路灰度传感器。

#include <msp430.h>

volatile unsigned int A0results;
volatile unsigned int A1results;
volatile unsigned int A2results;
volatile unsigned int A3results;
volatile unsigned int A4results;

int main(void)
{
    WDTCTL = WDTPW + WDTHOLD;                  
    P6SEL = BIT0 + BIT1 + BIT2 + BIT3 + BIT4; // 使能                      
    ADC12CTL0 = ADC12ON + ADC12MSC + ADC12SHT0_8; 
//打开ADC12   在第一个SHI信号后自动采样   设置采样时间
    ADC12CTL1 = ADC12SHP + ADC12CONSEQ_3;     // 使用定时器作为采样信号源, 多通道采集
    ADC12MCTL0 = ADC12INCH_0;                 // A0
    ADC12MCTL1 = ADC12INCH_1;                 // A1
    ADC12MCTL2 = ADC12INCH_2;                 // A2
    ADC12MCTL3 = ADC12INCH_3;                 // A3
    ADC12IE = 0x08;                           // 使能IFG3
    ADC12CTL0 |= ADC12ENC;                    // 使能转换
    while(1)
    {
        ADC12CTL0 |= ADC12SC;                     // SC这一位会自动复0,要手动置1
        __bis_SR_register(LPM0_bits + GIE);       // 低功耗0, 使能中断
    }
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC12_VECTOR
__interrupt void ADC12ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC12_VECTOR))) ADC12ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(ADC12IV,34))
  {
  case  0: break;                           // Vector  0:  无
  case  2: break;                           // Vector  2:  ADC溢出
  case  4: break;                           // Vector  4:  ADC超时
  case  6: break;                           // Vector  6:  ADC12IFG0
  case  8: break;                           // Vector  8:  ADC12IFG1
  case 10: break;                           // Vector 10:  ADC12IFG2
  case 12:                                  // Vector 12:  ADC12IFG3
    A0results = ADC12MEM0;           
    A1results = ADC12MEM1;           
    A2results = ADC12MEM2;           
    A3results = ADC12MEM3;           
    A4results = ADC12MEM4;
    __bic_SR_register_on_exit(LPM0_bits);
  case 14: break;                           // Vector 14:  ADC12IFG4
  case 16: break;                           // Vector 16:  ADC12IFG5
  case 18: break;                           // Vector 18:  ADC12IFG6
  case 20: break;                           // Vector 20:  ADC12IFG7
  case 22: break;                           // Vector 22:  ADC12IFG8
  case 24: break;                           // Vector 24:  ADC12IFG9
  case 26: break;                           // Vector 26:  ADC12IFG10
  case 28: break;                           // Vector 28:  ADC12IFG11
  case 30: break;                           // Vector 30:  ADC12IFG12
  case 32: break;                           // Vector 32:  ADC12IFG13
  case 34: break;                           // Vector 34:  ADC12IFG14
  default: break; 
  }  
}

总结

        ADC12的寄存器特别多,配置起来也很复杂,尤其是工程比较大时配置得很让人头疼,这也是大多数人选择不用寄存器的主要原因。但是就一般情况来说,配置还是有迹可循的。在大多数情况下只需要如下配置。

ADC12CTL0 = ADC12ON + ADC12MSC + ADC12SHT0_8;

打开ADC ,自动采样,选择采样时间

ADC12CTL1 = ADC12SHP + ADC12CONSEQ_x;

选择采样源,根据需要选择采集方式

ADC12MCTLx = ADC12INCH_x;

选择输入通道

ADC12IE = BITx;

使能对应输入通道对应的IFG

ADC12CTL0 |= ADC12ENC;

最后再使能转换,注意这条一定在最后

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值