MSP430F5529 ADC参考

MSP430F5529 ADC参考笔记

1.ADC12_A初始化参数

typedef struct ADC_MemMap
{
  union
  {
    uint16_t CTL0;
    struct
    {
      uint16_t SC             :1;  /* ADC12 Start Conversion */
      uint16_t ENC            :1;  /* ADC12 Enable Conversion */
      uint16_t TOVIE          :1;  /* ADC12 Timer Overflow interrupt enable */
      uint16_t OVIE           :1;  /* ADC12 Overflow interrupt enable */
      uint16_t ON             :1;  /* ADC12 On/enable */
      uint16_t ADCREFON       :1;  /* ADC12 Reference on */
      uint16_t REF2_5V        :1;  /* ADC12 Ref 0:1.5V / 1:2.5V */
      uint16_t MSC            :1;  /* ADC12 Multiple SampleConversion */
      uint16_t SHT0           :4;  /* ADC12 Sample Hold 0 Select  */
      uint16_t SHT1           :4;  /* ADC12 Sample Hold 1 Select  */
    };
  };
  union
  {
    uint16_t CTL1;
    struct
    {
      uint16_t ADBUSY         :1;    /* ADC12 Busy */
      uint16_t CONSEQ         :2;    /* ADC12 Conversion Sequence Select  */
      uint16_t SSEL           :2;    /* ADC12 Clock Source Select  */
      uint16_t DIV            :3;    /* ADC12 Clock Divider Select  */
      uint16_t ISSH           :1;    /* ADC12 Invert Sample Hold Signal */
      uint16_t SHP            :1;    /* ADC12 Sample/Hold Pulse Mode */
      uint16_t SHS            :2;    /* ADC12 Sample/Hold Source  */
      uint16_t CSTARTADD      :4;    /* ADC12 Conversion Start Address  */
    };
  };
  union
  {
    uint16_t CTL2;
    struct
    {
      uint16_t REFBURST       :1;    /* ADC12+ Reference Burst */
      uint16_t ADCREFOUT      :1;    /* ADC12+ Reference Out */
      uint16_t SR             :1;    /* ADC12+ Sampling Rate */
      uint16_t DF             :1;    /* ADC12+ Data Format */
      uint16_t RES            :2;    /* ADC12+ Resolution  */
      uint16_t TCOFF          :1;    /* ADC12+ Temperature Sensor Off */
      uint16_t PDIV           :1;    /* ADC12+ predivider 0:/1   1:/4 */
    };
  };
  uint16_t RESERVED_1[2];
  uint16_t IFG;
  uint16_t IE;
  uint16_t IV;
  struct
  {
      uint8_t INCH            :4;     /* ADC12 Input Channel Select*/
      uint8_t REF             :3;     /* ADC12 Select Reference  */
      uint8_t EOS             :1;     /* ADC12 End of Sequence */
  }MCTL[16];
  uint16_t MEM[16];
}volatile * ADC_MemMapPtr;

#define ADC12_SSEL_ADC12OSC       0
#define ADC12_SSEL_ACLK           1                   
#define ADC12_SSEL_MCLK           2
#define ADC12_SSEL_SMCLK          3   

#define ADC12_SREF_0            0
#define ADC12_SREF_1            1
#define ADC12_SREF_2            2
#define ADC12_SREF_3            3
#define ADC12_SREF_4            4
#define ADC12_SREF_5            5
#define ADC12_SREF_6            6
#define ADC12_SREF_7            7

#define ADC_BASE_PTR                     ((ADC_MemMapPtr)__MSP430_BASEADDRESS_ADC12_PLUS__)

1.1 初始化的通道及引脚

typedef enum
{
  ADC_CH0        =BIT0,  //P6.0
  ADC_CH1        =BIT1,  //P6.1
  ADC_CH2        =BIT2,  //P6.2
  ADC_CH3        =BIT3,  //P6.3
  ADC_CH4        =BIT4,  //P6.4
  ADC_CH5        =BIT5,  //P6.5
  ADC_CH6        =BIT6,  //P6.6
  ADC_CH7        =BIT7,  //P6.7
  ADC_CH8        =BIT8,  //VeREF+    //外部正基准
  ADC_CH9        =BIT9,  //VeREF-    //外部负基准
  ADC_CH10       =BITA,  //片内温度传感器
  ADC_CH11       =BITB,  //(AVCC-AVSS)/2
  ADC_CH12       =BITC,  //P7.0
  ADC_CH13       =BITD,  //P7.1
  ADC_CH14       =BITE,  //P7.2
  ADC_CH15       =BITF,  //P7.3
  ADC_CH_NUM     =16u,   //通道数量
}ADC_CHn;       //通道

1.2 参考电压

typedef enum
{
  ADC_VREF_1_5V         ,  //内部1.5V
  ADC_VREF_2_5V         ,  //内部2.5V
  ADC_VREF_3_3V         ,  //供电电压作为参考电压
  ADC_VREF_External     ,  //使用外部提供参考电压
}ADC_VREF;         //参考电压

值得注意的是,参考手册里面解释如下
3
单片机的采样电压是不允许超过参考电压:

N a d c = 4095 V i n V R V R + V R

从参考公式来看,必须小于参考电压,如果超过参考电压,输出只能到最大参考电压,并且还会可能烧坏单片机

1.3 转换精度

typedef enum
{
  ADC_8bit              ,  //8 位精度,最大值256-1
  ADC_10bit             ,  //10位精度,最大值1024-1
  ADC_12bit             ,  //12位精度,最大值4096-1
}ADC_Resolution;   //精度

2 初始化

/*******************************************************************************
*  函数名称:ADC_Init(uint16_t ch,ADC_VREF Vref,ADC_Resolution nBit)
*  功能说明:ADC初始化一个或多个ADC通道
*  参数说明:
            uint16_t ch     :要初始化的通道
            ADCVREF Vref    :参考电压
            ADC_Resolution nBit   :转换精度
*  函数返回:无
********************************************************************************/
void ADC_Init(uint16_t ch,ADC_VREF Vref,ADC_Resolution nBit)
{
  ADC12->ENC = DISABLE; //先对该位复位,否则置位后有些寄存器不能再进行操作
  uint16_t SREF_RegValue = 0u;
  switch(Vref)           //选择参考电压
  {
  case ADC_VREF_1_5V:
    REFCTL0 &=~ REFMSTR;                //把REF参考电压控制权交给ADC
    ADC12->ADCREFON = BIT_SET;
    ADC12->REF2_5V = RESET;
    SREF_RegValue = ADC12_SREF_1;       //使用内部提供的参考电压
    break;
  case ADC_VREF_2_5V:
    REFCTL0 &=~ REFMSTR;
    ADC12->ADCREFON = BIT_SET;
    ADC12->REF2_5V = BIT_SET;
    SREF_RegValue = ADC12_SREF_1;       //使用内部提供的参考电压
    break;
  case ADC_VREF_External:      
    P5SEL |= BIT0;       //VeREF+
    P5SEL |= BIT1;       //VeREF-
    SREF_RegValue = ADC12_SREF_2;       //使用外部参考电压
  case ADC_VREF_3_3V:
    SREF_RegValue = ADC12_SREF_0;       //使用电源电压作为参考电压,
    break;
  default :break;
  }
  //初始化通道
  uint16_t CH_Mask = 0x01;
  for(uint8_t CH_Num=0; CH_Num < ADC_CH_NUM; CH_Num++)
  {
    if(ch & CH_Mask)   //要初始化的通道
    {
      if((CH_Mask & InitialedChannel_Bit) == 0)   //如果该通道未被初始化过               
      {
        ADC12->MCTL[InitialedChannel_Num].INCH = CH_Num;
        ADC12->MCTL[InitialedChannel_Num].REF  = SREF_RegValue;//参考电压选择,通道设置
        ADC_Channel_Bit[InitialedChannel_Num] = CH_Mask;//将该通道初始化标志置位                                                 InitialedChannel_Bit |= CH_Mask; //置位已初始化的通道标志位
        InitialedChannel_Num ++;//初始化的通道数加1
      }
      else //如果是之前已经初始化过的通道,则要在这里从新设置一下,只设置通道参考电压
      {
        ADC12->MCTL[ADC_GetChanelNum((ADC_CHn)CH_Mask)].REF = SREF_RegValue;//改变参考电压            
      }
    }
    CH_Mask <<= 1;
  }
  if(InitialedChannel_Num > 1)                 //有多个通道时要加上序列通道结束位
  {
    for(int i=0; i<(InitialedChannel_Num-1); i++)   //前面所有通道序列结束位清零
    {
      ADC12->MCTL[i].EOS = RESET;
    }
    ADC12->MCTL[InitialedChannel_Num-1].EOS = BIT_SET;  //最后一通道加上序列通道转换结束位
  }
  //一般配置
  ADC12->SHT0 = M0_M7_SAMPLE_HOLD_TIME; //0-7通道采样与保持时间
  ADC12->SHT1 = M8_M15_SAMPLE_HOLD_TIME;//8-15通道采样与保持时间
  ADC12->ON = BIT_SET;/ 采样时间,AD内核开启
  ADC12->MSC = BIT_SET;
  ADC12->SSEL = ADC12_SSEL_ADC12OSC;//时钟选择
  ADC12->SHP = BIT_SET;
  //有多个通道时设为序列通道单次转换模式,单个通道时设为单通道单次转换模式   
  ADC12->CONSEQ = (InitialedChannel_Num > 1) ? BIT_SET : RESET;        
  //设置ADC精度
  ADC12->RES = nBit;    
  //开启时钟
  UCS->MODOSC_REQEN = BIT_SET; //ADC使用的是MODCLK 所以在这里配置该时钟,约5MHz左右
  //配置通道为第二功能
  if(ch & 0x00ff)
  {
     GPIO_MultiBits_Init(P6,(ch & 0x00ff),GPI | SEL);
  }
  if(ch & 0xf000)
  {
     GPIO_MultiBits_Init(P7,((ch & 0xf000)>>12),GPI | SEL);
  }
  if(ch & ADC_CH10) //如果使用了温度传感器通道,则开启温度传感器
  {
    ADC12->TCOFF = RESET;
  }
  ADC12->ENC = ENABLE;     //该位必须在初始化完成后再置位
  //DELAY_MS(5);     //延时等待参考电压建立
}

这里采样与保持间隔

//宏定义ADC12MEM8 to ADC12MEM15采样与保持时间  0-15
#define M8_M15_SAMPLE_HOLD_TIME  3
//宏定义ADC12MEM0 to ADC12MEM7 采样与保持时间  0-15
#define M0_M7_SAMPLE_HOLD_TIME   3

注意点
1. 初始化后所有通道精度相同,即所有通道转换精度只取决于最后一次配置的精度
2. 所有通道内部参考电压只能使用1.5或2.5V中的一种

使用示例

ADC_Init(ADC_CH1+ADC_CH3,ADC_VREF_1_5V,ADC_10bit);        
//同时初始化两个通道,使用内部提供的1.5V参考电压,10位精度

3.采样实例

/*!
*     COPYRIGHT NOTICE
*     Copyright (c) 2016,CTGU-GB
*     All rights reserved.
*
*
* @file       main.c
* @brief      MSP430F5529 平台主程序

* @author     CTGU-GB
* @version    v2.7
* @date       2016-11-26
*/
#include "include.h"
double adcDataTest[20];
/*******************************************************************************
*  函数名称:ADC_Filter(u32 num,double *adcDataStorage)
*  功能说明:ADC滤波函数
*  作者:klaus 邮箱:[email protected]
*  参数说明:uint8_t num 输入滤波数据个数
*            double *adcDataStorage:滤波数组
*  函数返回:滤波结果
********************************************************************************/
double ADC_Filter(uint8_t num,double *adcDataStorage)
{
  uint8_t i,j,k;
  uint8_t noswap=1;
  double adc_sum_tmp=0,adc_ave_tmp=0;

  for(i=0;i<num-1;++i){   
      for(j=0;j<num-i-1;++j)
      {
          if(adcDataStorage[j]>adcDataStorage[j+1]){
              adcDataStorage[j]=adcDataStorage[j]+adcDataStorage[j+1];
              adcDataStorage[j+1]=adcDataStorage[j]-adcDataStorage[j+1];
              adcDataStorage[j]=adcDataStorage[j]-adcDataStorage[j+1];
              noswap=0;
          }
       }
      if(noswap) break;
  }
  for(k=2;k<num-2;k++)adc_sum_tmp += adcDataStorage[k];
  //adc_sum_tmp -= (adcDataStorage[0]+adcDataStorage[1]+adcDataStorage[num-2]+adcDataStorage[num-1]);    
  adc_ave_tmp=adc_sum_tmp/(num-4);
  adc_sum_tmp=0;

  return adc_ave_tmp;
}

void main()
{
  DisableInterrupts();          //禁止总中断

  LED_Init(LED_ALL);              //LED灯初始化
  OLED_Init();

  ADC_Init(ADC_CH2,ADC_VREF_3_3V,ADC_10bit);       //初始化通道,P6.1

  while(1)
  {  

    int i;
    for(i=0;i<20;i++)
    {
      adcDataTest[i]=ADC_ReadChanelOnce(ADC_CH2)*3.3/1023;
      DELAY_MS(10);
    }
    double ad = ADC_Filter(20,adcDataTest);
    OLED_PrintfAt(FONT_ASCII_8X16,0,0,"ADValue:\n%.3f V",ad);         //在指定位置打印

  }
}

猜你喜欢

转载自blog.csdn.net/klaus_x/article/details/81177466