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.2 Reference voltage
typedef enum
{
ADC_VREF_1_5V , //Internal 1.5V
ADC_VREF_2_5V , //Internal 2.5V
ADC_VREF_3_3V , //Supply voltage as reference voltage
ADC_VREF_External , //Use external reference voltage
}ADC_VREF; //Reference voltage
It is worth noting that the reference manual explains that
the sampling voltage of the following MCU is not allowed to exceed the reference voltage:
Nadc=4095VinVRVR+VR
Nadc=4095VinVRVR+VR
According to the reference formula, it must be less than the reference voltage. If it exceeds the reference voltage, the output can only reach the maximum reference voltage, and the microcontroller may also be burned out.
1.3 Conversion accuracy
typedef enum
{
ADC_8bit , //8-bit accuracy, maximum value 256-1
ADC_10bit , //10-bit accuracy, maximum value 1024-1
ADC_12bit , //12-bit accuracy, maximum value 4096-1
}ADC_Resolution; //Accuracy
2 Initialization
/****************************************************************************
* Function name: ADC_Init(uint16_t ch,ADC_VREF Vref,ADC_Resolution nBit)
* Function description: ADC initializes one or more ADC channels
* Parameter description:
uint16_t ch: channel to be initialized
ADCVREF Vref: reference voltage
ADC_Resolution nBit: conversion accuracy
* Function returns: None
******************************************************************************/
void ADC_Init(uint16_t ch,ADC_VREF Vref,ADC_Resolution nBit)
{
ADC12->ENC = DISABLE; //Reset this bit first, otherwise some registers cannot be operated after setting
uint16_t SREF_RegValue = 0u;
switch(Vref) //Select reference voltage
{
case ADC_VREF_1_5V:
REFCTL0 &=~ REFMSTR; //Give control of REF reference voltage to ADC
ADC12->ADCREFON = BIT_SET;
ADC12->REF2_5V = RESET;
SREF_RegValue = ADC12_SREF_1; //Use the internal reference voltagebreak
;
case ADC_VREF_2_5V:
REFCTL0 &=~ REFMSTR;
ADC12->ADCREFON = BIT_SET;
ADC12->REF2_5V = BIT_SET;
SREF_RegValue = ADC12_SREF_1; //Use the internal reference voltagebreak
;
case ADC_VREF_External:
P5SEL |= BIT0; //VeREF+
P5SEL |= BIT1; //VeREF-
SREF_RegValue = ADC12_SREF_2; //Use external reference voltage
case ADC_VREF_3_3V:
SREF_RegValue = ADC12_SREF_0; //Use power supply voltage as reference voltage,
break;
default :break;
}
//Initialize channel
uint16_t CH_Mask = 0x01;
for(uint8_t CH_Num=0; CH_Num < ADC_CH_NUM; CH_Num++)
{
if(ch & CH_Mask) //Channel to be initialized
{
if((CH_Mask & InitialedChannel_Bit) == 0) //If the channel has not been initialized
{
ADC12->MCTL[InitialedChannel_Num].INCH = CH_Num;
ADC12->MCTL[InitialedChannel_Num].REF = SREF_RegValue; //reference voltage selection, channel setting
ADC_Channel_Bit[InitialedChannel_Num] = CH_Mask; //set the channel initialization flag InitialedChannel_Bit |= CH_Mask; //set the initialized channel flag
InitialedChannel_Num ++; //increase the number of initialized channels by 1
}
else //if the channel has been initialized before, reset it here and only set the channel reference voltage
{
ADC12->MCTL[ADC_GetChanelNum((ADC_CHn)CH_Mask)].REF = SREF_RegValue; //change the reference voltage
}
}
CH_Mask <<= 1;
}
if(InitialedChannel_Num > 1) //When there are multiple channels, add the sequence channel end bit
{
for(int i=0; i<(InitialedChannel_Num-1); i++) //Clear all the previous channel sequence end bits
{
ADC12->MCTL.EOS = RESET;
}
ADC12->MCTL[InitialedChannel_Num-1].EOS = BIT_SET; //The last channel adds the sequence channel conversion end bit
}
//General configuration
ADC12->SHT0 = M0_M7_SAMPLE_HOLD_TIME; //0-7 channel sampling and holding time
ADC12->SHT1 = M8_M15_SAMPLE_HOLD_TIME; //8-15 channel sampling and holding time
ADC12->ON = BIT_SET;/ Sampling time, AD core is turned on
ADC12->MSC = BIT_SET;
ADC12->SSEL = ADC12_SSEL_ADC12OSC; //Clock selection
ADC12->SHP = BIT_SET;
//When there are multiple channels, set it to serial channel single conversion mode, and when there is a single channel, set it to single channel single conversion mode
ADC12->CONSEQ = (InitialedChannel_Num > 1) ? BIT_SET : RESET;
//Set ADC precision
ADC12->RES = nBit;
//Turn on the clock
UCS->MODOSC_REQEN = BIT_SET; //ADC uses MODCLK, so configure the clock here, about 5MHz.
//Configure the channel as the second function
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) //If the temperature sensor channel is used, turn on the temperature sensor
{
ADC12->TCOFF = RESET;
}
ADC12->ENC = ENABLE; //This bit must be set after initialization is completed
//DELAY_MS(5); //Delay to wait for the reference voltage to be established
}
Here is the sampling and holding interval
//Macro definition ADC12MEM8 to ADC12MEM15 sampling and holding time 0-15
#define M8_M15_SAMPLE_HOLD_TIME 3
//Macro definition ADC12MEM0 to ADC12MEM7 sampling and holding time 0-15
#define M0_M7_SAMPLE_HOLD_TIME 3
Notes
1. After initialization, the accuracy of all channels is the same, that is, the conversion accuracy of all channels depends only on the accuracy of the last configuration
2. The internal reference voltage of all channels can only use one of 1.5 or 2.5V
Example of use:
ADC_Init(ADC_CH1+ADC_CH3,ADC_VREF_1_5V,ADC_10bit);
//Initialize two channels at the same time, use the internal 1.5V reference voltage, 10-bit accuracy
3. Sampling example
/*!
* COPYRIGHT NOTICE
* Copyright (c) 2016,CTGU-GB
* All rights reserved.
*
*
* @file main.c
* @brief MSP430F5529 platform main program
* @author CTGU-GB
*/
#include "include.h"
double adcDataTest[20];
/***************************************************************************
* Function name: ADC_Filter(u32 num,double *adcDataStorage)
* Function description: ADC filter function
* Author: klaus Email: xcf2016a@outlook.com
* Parameter description: uint8_t num: number of input filter data
* double *adcDataStorage: filter array
* Function returns: filter result
******************************************************************************/
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(); //Disable general interrupts
LED_Init(LED_ALL); //LED light initializationOLED_Init
();
ADC_Init(ADC_CH2,ADC_VREF_3_3V,ADC_10bit); //Initialize channel, P6.1
while(1)
{
int i;
for(i=0;i<20;i++)
{
adcDataTest=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); //在指定位置打印
}
}
|