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; //参考电压
值得注意的是,参考手册里面解释如下
单片机的采样电压是不允许超过参考电压:
Nadc=4095∗Vin−VR−VR+−VR−
Nadc=4095∗Vin−VR−VR+−VR−
从参考公式来看,必须小于参考电压,如果超过参考电压,输出只能到最大参考电压,并且还会可能烧坏单片机。
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位精度
采样实例
/*!
* COPYRIGHT NOTICE
* Copyright (c) 2016,CTGU-GB
* All rights reserved.
de "include.h"
double adcDataTest[20];
/*******************************************************************************
* 函数名称:ADC_Filter(u32 num,double *adcDataStorage)
* 功能说明:ADC滤波函数
* 作者:klaus 邮箱:xcf2016a@outlook.com
* 参数说明: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); //在指定位置打印
}
}
|