一、头文件:
#ifndef __ADC_H__ #define __ADC_H__ 1 #include "adc_cfg.h" /* #define ATD_B11_Check() ad_once(ADC1,SE15,ADC_10bit) ///B11 #define ATD_B10_Check() ad_once(ADC1,SE14,ADC_10bit) ///B10分压 #define ATD_B3_Check() ad_once(ADC0,SE13,ADC_10bit) ///B3CCD0 #define ATD_B2_Check() ad_once(ADC0,SE12,ADC_10bit) ///B2纵向陀螺仪 #define ATD_B1_Check() ad_once(ADC0,SE9,ADC_10bit) ///B1 #define ATD_B0_Check() ad_once(ADC0,SE8,ADC_10bit) ///B0加速度计 #define ATD_E25_Check() ad_once(ADC0,SE18,ADC_10bit) ///E25 #define ATD_E24_Check() ad_once(ADC0,SE17,ADC_10bit) ///E24横陀螺仪 */ typedef enum ADCn //ADC端口 { ADC0, ADC1 } ADCn; //ADC通道 //提醒,用的时候,可以直接用 DP0 代替 DAD0 ,其他的也类似,因为有个宏定义:#define DP0 DAD0 typedef enum ADC_Ch { //SC1n[DIFF]= 0 // ------ADC0---------- ------ADC1-------- DAD0 = 0, // ADC0_DP0 ADC1_DP0 DAD1 = 1, // ADC0_DP1 ADC1_DP1 DAD2 = 2, // PGA0_DP PGA1_DP DAD3 = 3, // ADC0_DP3 ADC1_DP3 //ADCx_CFG2[MUXSEL] 位决定 ADCx_SEn 通道为 a 或 b. AD4a = 4, // 保留 ADC1_SE4a -- PTE0 AD5a = 5, // 保留 ADC1_SE5a -- PTE1 AD6a = 6, // 保留 ADC1_SE6a -- PTE2 AD7a = 7, // 保留 ADC1_SE7a -- PTE3 //也是 4、5、6、7 AD4b = AD4a, // ADC0_SE4b -- PTC2 ADC1_SE4b -- PTC8 AD5b = AD5a, // ADC0_SE5b -- PTD1 ADC1_SE5b -- PTC9 AD6b = AD6a, // ADC0_SE6b -- PTD5 ADC1_SE6b -- PTC10 AD7b = AD7a, // ADC0_SE7b -- PTD6 ADC1_SE7b -- PTC11 AD8 = 8, // ADC0_SE8 -- PTB0 ADC1_SE8 -- PTB0 AD9 = 9, // ADC0_SE9 -- PTB1 ADC1_SE9 -- PTB1 AD10 = 10, // ADC0_SE10 -- PTA7 ADC1_SE10 -- PTB4 AD11 = 11, // ADC0_SE11 -- PTA8 ADC1_SE11 -- PTB5 AD12 = 12, // ADC0_SE12 -- PTB2 ADC1_SE12 -- PTB6 AD13 = 13, // ADC0_SE13 -- PTB3 ADC1_SE13 -- PTB7 AD14 = 14, // ADC0_SE14 -- PTC0 ADC1_SE14 -- PTB10 AD15 = 15, // ADC0_SE15 -- PTC1 ADC1_SE15 -- PTB11 AD16 = 16, // ADC0_SE16 ADC1_SE16 AD17 = 17, // ADC0_SE17 -- PTE24 ADC1_SE17 -- PTA17 AD18 = 18, // ADC0_SE18 -- PTE25 VREF Output AD19 = 19, // ADC0_DM0 ADC1_DM0 AD20 = 20, // ADC0_DM1 ADC1_DM1 AD21 = 21, // 保留 AD22 = 22, // AD23 = 23, // DAC0_OUT(12-bit) -- DAC0_OUT DAC1_OUT(12-bit) AD24 = 24, // 保留 保留 AD25 = 25, // 保留 保留 AD26 = 26, // Temperature Sensor (S.E) Temperature Sensor (S.E) AD27 = 27, // Bandgap (S.E) Bandgap (S.E) AD28 = 28, // 保留 保留 AD29 = 29, // VREFH (S.E) VREFH (S.E) AD30 = 30, // VREFL VREFL AD31 = 31 // 禁用ADC0 禁用ADC1 } ADC_Ch; //精度位数 typedef enum ADC_nbit { ADC_8bit = 0x00, ADC_10bit = 0x02, ADC_12bit = 0x01, ADC_16bit = 0x03 } ADC_nbit; //外部函数接口声明 extern void adc_init (ADCn, ADC_Ch); //AD初始化 extern u16 ad_once (ADCn, ADC_Ch, ADC_nbit); //采集一次一路模拟量的AD值 extern u16 ad_mid (ADCn, ADC_Ch, ADC_nbit); //中值滤波后的结果 extern u16 ad_ave (ADCn, ADC_Ch, ADC_nbit, u8 N); //均值滤波后的结果 extern u16 ad_flt (ADCn, ADC_Ch, ADC_nbit); //与前几次采样均值滤波 速度快于ad_ave很多,如果相邻采样时间比较短,则采样精确于 ad_once。即采样间距较短的情况下优先考虑使用这个 extern void adc_start (ADCn, ADC_Ch, ADC_nbit); //开始adc转换 extern void adc_stop (ADCn); //停止ADC转换 //内部函数声明 static void adc_config_alt(ADC_MemMapPtr adcmap, tADC_ConfigPtr ADC_CfgPtr);//将adc寄存器结构体配置进adc寄存器 #endif /* __ADC16_H__ */
二、源文件:
#include "common.h" #include "adc.h" tADC_Config Master_Adc_Config; //该结构体包含了需要的ADC/PGA配置 volatile struct ADC_MemMap *ADCx[2] = {ADC0_BASE_PTR, ADC1_BASE_PTR}; //定义两个指针数组保存 ADCx 的地址 /********************************函数声明************************************ * 函数名称:adc_init * 功能说明:AD初始化,使能时钟 * 参数说明:ADCn 模块号( ADC0、 ADC1) * ADC_Ch 通道号 * 函数返回:无 *************************************************************************/ void adc_init(ADCn adcn, ADC_Ch ch) { //ASSERT( ((adcn == ADC0) && (ch >= AD8 && ch <= AD18)) || ((adcn == ADC1) && (ch >= AD4a && ch <= AD17)) ) ; //使用断言检测ADCn_CHn是否正常 switch(adcn) { case ADC0: /* ADC0 */ SIM_SCGC6 |= (SIM_SCGC6_ADC0_MASK ); //开启ADC0时钟 SIM_SOPT7 &= ~(SIM_SOPT7_ADC0ALTTRGEN_MASK | SIM_SOPT7_ADC0PRETRGSEL_MASK); SIM_SOPT7 = SIM_SOPT7_ADC0TRGSEL(0); switch(ch) { case AD5b: //PTD1 SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; PORT_PCR_REG(PORTD_BASE_PTR, 1) = PORT_PCR_MUX(0); break; case AD8: //ADC0_SE8 -- PTB0 case AD9: //ADC0_SE9 -- PTB1 SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; PORT_PCR_REG(PORTB_BASE_PTR, ch - AD8 + 0) = PORT_PCR_MUX(0); break; case AD10: //ADC0_SE10 -- PTA7 case AD11: //ADC0_SE11 -- PTA8 SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, ch - AD10 + 7) = PORT_PCR_MUX(0); break; case AD12: //ADC0_SE12 -- PTB2 case AD13: //ADC0_SE13 -- PTB3 SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; PORT_PCR_REG(PORTB_BASE_PTR, ch - AD12 + 2) = PORT_PCR_MUX(0); break; case AD14: //ADC0_SE14 -- PTC0 case AD15: //ADC0_SE15 -- PTC1 SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK; PORT_PCR_REG(PORTC_BASE_PTR, ch - AD14 + 0) = PORT_PCR_MUX(0); break; case AD17: //ADC0_SE17 -- PTE24 case AD18: //ADC0_SE17 -- PTE25 SIM_SCGC5 |= SIM_SCGC5_PORTE_MASK; PORT_PCR_REG(PORTE_BASE_PTR, ch - AD17 + 24) = PORT_PCR_MUX(0); break; default: return; } return; case ADC1: /* ADC1 */ SIM_SCGC3 |= (SIM_SCGC3_ADC1_MASK ); SIM_SOPT7 &= ~(SIM_SOPT7_ADC1ALTTRGEN_MASK | SIM_SOPT7_ADC1PRETRGSEL_MASK) ; SIM_SOPT7 = SIM_SOPT7_ADC1TRGSEL(0); switch(ch) { case AD4a: //ADC1_SE4a -- PTE0 case AD5a: //ADC1_SE5a -- PTE1 case AD6a: //ADC1_SE6a -- PTE2 case AD7a: //ADC1_SE7a -- PTE3 SIM_SCGC5 |= SIM_SCGC5_PORTE_MASK; PORT_PCR_REG(PORTE_BASE_PTR, ch - AD4a + 0) = PORT_PCR_MUX(0); break; case AD8: //ADC1_SE8 -- PTB0 case AD9: //ADC1_SE9 -- PTB1 SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; PORT_PCR_REG(PORTB_BASE_PTR, ch - AD8 + 0) = PORT_PCR_MUX(0); break; case AD10: //ADC1_SE10 -- PTB4 case AD11: //ADC1_SE11 -- PTB5 case AD12: //ADC1_SE12 -- PTB6 case AD13: //ADC1_SE13 -- PTB7 SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; PORT_PCR_REG(PORTB_BASE_PTR, ch - 6) = PORT_PCR_MUX(0); break; case AD14: //ADC1_SE14 -- PTB10 case AD15: //ADC1_SE15 -- PTB11 SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; PORT_PCR_REG(PORTB_BASE_PTR, ch - AD10 + 4) = PORT_PCR_MUX(0); break; case AD17: //ADC1_SE17 -- PTA17 SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; PORT_PCR_REG(PORTA_BASE_PTR, ch) = PORT_PCR_MUX(0); break; default: break; } break; default: break; } } /********************************函数声明************************************ * 函数名称:ad_once * 功能说明:采集一次一路模拟量的AD值 * 参数说明:ADCn 模块号( ADC0、 ADC1) * ADC_Channel 通道号 * ADC_nbit 精度( ADC_8bit,ADC_12bit, ADC_10bit, ADC_16bit ) * 函数返回:16位无符号结果值 * 备 注:B通道不能软件触发!!!! ******************************函数声明*************************************/ u16 ad_once(ADCn adcn, ADC_Ch ch, ADC_nbit bit) { u16 result = 0; //ASSERT( ((adcn == ADC0) && (ch >= AD8 && ch <= AD18)) || ((adcn == ADC1) && (ch >= AD4a && ch <= AD17)) ) ; //使用断言检测ADCn_CHn是否正常 adc_start(adcn, ch, bit); //启动ADC转换 while (( ADC_SC1_REG(ADCx[adcn], 0 ) & ADC_SC1_COCO_MASK ) != ADC_SC1_COCO_MASK); result = ADC_R_REG(ADCx[adcn], 0); ADC_SC1_REG(ADCx[adcn], 0) &= ~ADC_SC1_COCO_MASK; return result; } /************************************************************************* * 函数名称:ad_mid * 功能说明:采集三次一路模拟量的AD值,返回中值 * 参数说明:ADCx 模块号( ADC0、 ADC1) * ADC_Channel 通道号 * ADC_nbit 精度( ADC_8bit,ADC_12bit, ADC_10bit, ADC_16bit ) * 函数返回:16位无符号中值结果 *************************************************************************/ u16 ad_mid(ADCn adcn, ADC_Ch ch, ADC_nbit bit) { u16 i, j, k, tmp; //ASSERT( ((adcn == ADC0) && (ch >= AD8 && ch <= AD18)) || ((adcn == ADC1) && (ch >= AD4a && ch <= AD17)) ) ; //使用断言检测ADCn_CHn是否正常 //3次ADC转换 i = ad_once(adcn, ch, bit); j = ad_once(adcn, ch, bit); k = ad_once(adcn, ch, bit); //取中值 tmp = i > j ? i : j; //tmp取两者最大值 return k > tmp ? tmp : ( k > i ? k : i ); // k>tmp>i tmp>k>i tmp>i>k } /************************************************************************* * 函数名称:ad_ave * 功能说明:多次采样,取平均值 * 参数说明: ADCx 模块号( ADC0、 ADC1) * ADC_Channel 通道号 * ADC_nbit 精度( ADC_8bit,ADC_12bit, ADC_10bit, ADC_16bit ) * N 均值滤波次数(范围:0~255) * 函数返回:16位无符号结果值 *************************************************************************/ u16 ad_ave(ADCn adcn, ADC_Ch ch, ADC_nbit bit, u8 N) //均值滤波 { u32 tmp = 0; u8 i; //ASSERT( ((adcn == ADC0) && (ch >= AD8 && ch <= AD18)) || ((adcn == ADC1) && (ch >= AD4a && ch <= AD17)) ) ; //使用断言检测ADCn_CHn是否正常 for(i = 0; i < N; i++) tmp += ad_once(adcn, ch, bit); tmp = tmp / N; return (u16)tmp; } /************************************************************************* * 函数名称:ad_flt * 功能说明:一次采样后,与前几次采样,求平均值 * 参数说明:ADCx 模块号( ADC0、 ADC1) * ADC_Channel 通道号 * ADC_nbit 精度( ADC_8bit,ADC_12bit, ADC_10bit, ADC_16bit ) * 函数返回:16位无符号结果值 *************************************************************************/ #define SAMP_COUNT 2 //向前滤波 2^SAMP_COUNT 次数 不能太大,不然采样不准 u16 ad_flt(ADCn adcn, ADC_Ch ch, ADC_nbit bit) { static u16 buf[(1<<(SAMP_COUNT))] = {0}; //保存前 2^SAMP_COUNT 次 的采样数据 static u8 n = (u8)(0x100 - (s8)(1 << (SAMP_COUNT))); static u32 sum = 0; //ASSERT( ((adcn == ADC0) && (ch >= AD8 && ch <= AD18)) || ((adcn == ADC1) && (ch >= AD4a && ch <= AD17)) ) ; //使用断言检测ADCn_CHn是否正常 if(n >= (u8)(0x100 - (s8)(1 << (SAMP_COUNT)))) { buf[(u8)((1<<(SAMP_COUNT))+n)] = ad_once(adcn, ch, bit); sum += buf[(u8)((1<<(SAMP_COUNT))+n)]; n++; return ((u16)(sum >> SAMP_COUNT)); } sum -= buf[n]; buf[n] = ad_once(adcn, ch, bit); sum += buf[n]; if (++n >= (1 << (SAMP_COUNT))) { n = 0; } return ((u16)(sum >> SAMP_COUNT)); /* ADC采样值由若干次采样值平均 */ } #undef SAMP_COUNT /************************************************************************* * 函数名称:adc_start * 功能说明:启动adc软件采样,B通道不能用于软件触发!!!! * 参数说明:ADCx 模块号( ADC0、 ADC1) * ADC_Channel 通道号 * ADC_nbit 精度( ADC_8bit,ADC_12bit, ADC_10bit, ADC_16bit ) * 函数返回:无 *************************************************************************/ void adc_start(ADCn adcn, ADC_Ch ch, ADC_nbit bit) { Master_Adc_Config.STATUS1A = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH( ch ); //初始化ADC默认配置 Master_Adc_Config.CONFIG1 = ADLPC_NORMAL | ADC_CFG1_ADIV(ADIV_4) | ADLSMP_LONG | ADC_CFG1_MODE(bit) | ADC_CFG1_ADICLK(ADICLK_BUS); if(adcn==ADC0) { Master_Adc_Config.CONFIG2 = MUXSEL_ADCB //MUXSEL_ADCA | ADACKEN_DISABLED | ADHSC_HISPEED | ADC_CFG2_ADLSTS(ADLSTS_20) ; } else { Master_Adc_Config.CONFIG2 = MUXSEL_ADCA //MUXSEL_ADCA | ADACKEN_DISABLED | ADHSC_HISPEED | ADC_CFG2_ADLSTS(ADLSTS_20) ; } Master_Adc_Config.COMPARE1 = 0x1234u ; //任意值 Master_Adc_Config.COMPARE2 = 0x5678u ; //任意值 adc_config_alt(ADCx[adcn], &Master_Adc_Config); // 配置 ADCn } /************************************************************************* * 函数名称:adc_stop * 功能说明:停止ADC转换 * 参数说明:ADCx 模块号( ADC0、 ADC1) * ADC_Channel 通道号 * 函数返回:无 *************************************************************************/ void adc_stop(ADCn adcn) { Master_Adc_Config.STATUS1A = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(Module_disabled); adc_config_alt(ADCx[adcn], &Master_Adc_Config); // 配置ADC0 } /************************************************************************* * 函数名称:adc_config_alt * 功能说明:将adc寄存器结构体配置进adc寄存器 * 参数说明:adcmap adc基址寄存器地址(ADC0_BASE_PTR,ADC1_BASE_PTR) * ADC_CfgPtr 存放 寄存器值的结构体 * 函数返回:无 *************************************************************************/ void adc_config_alt(ADC_MemMapPtr adcmap, tADC_ConfigPtr ADC_CfgPtr) { ADC_CFG1_REG(adcmap) = ADC_CfgPtr->CONFIG1; ADC_CFG2_REG(adcmap) = ADC_CfgPtr->CONFIG2; ADC_CV1_REG(adcmap) = ADC_CfgPtr->COMPARE1; ADC_CV2_REG(adcmap) = ADC_CfgPtr->COMPARE2; ADC_SC2_REG(adcmap) = ADC_CfgPtr->STATUS2; ADC_SC3_REG(adcmap) = ADC_CfgPtr->STATUS3; ADC_PGA_REG(adcmap) = ADC_CfgPtr->PGA; ADC_SC1_REG(adcmap, A) = ADC_CfgPtr->STATUS1A; ADC_SC1_REG(adcmap, B) = ADC_CfgPtr->STATUS1B; }
三、总结
首先先初始化ADC,然后再再选择何种采样方式的API,不过一般是自己进行滤波处理。
时间: 2024-11-10 01:01:30