一、代碼分享:
1、ADC頭文件
#ifndef ADC_H_ #define ADC_H_ #include "common.h" typedef enum { // ---------------------------------ADC0------------------------- ADC0_DP0 = 0, // PTE20 ADC0_SE0 = 0, ADC0_DP1 = 1, // PTE16 ADC0_SE1 = 1, ADC0_DP2 = 2, // PTE18 ADC0_SE2 = 2, ADC0_DP3 = 3, // PTE22 ADC0_SE3 = 3, ADC0_DM0 = 4, // PTE21 ADC0_SE4a= 4, ADC0_DM1 = 5, // PTE17 ADC0_SE5a= 5, ADC0_DM2 = 6, // PTE19 ADC0_SE6a= 6, ADC0_DM3 = 7, // PTE23 ADC0_SE7a= 7, ADC0_SE4b= 4, // PTE29 不支持軟件ADC,傳遞進軟件觸發ADC,會當作 a通道處理 ADC0_SE5b= 5, // PTD1 不支持軟件ADC,傳遞進軟件觸發ADC,會當作 a通道處理 ADC0_SE6b= 6, // PTD5 不支持軟件ADC,傳遞進軟件觸發ADC,會當作 a通道處理 ADC0_SE7b= 7, // PTD6 不支持軟件ADC,傳遞進軟件觸發ADC,會當作 a通道處理 ADC0_SE8, // PTB0 ADC0_SE9, // PTB1 ADC0_RES0, // 保留 ADC0_SE11, // PTC2 ADC0_SE12, // PTB2 ADC0_SE13, // PTB3 ADC0_SE14, // PTC0 ADC0_SE15, // PTC1 ADC0_RES1, // 保留 ADC0_RES2, // 保留 ADC0_RES3, // 保留 ADC0_RES4, // 保留 ADC0_RES5, // 保留 ADC0_RES6, // 保留 ADC0_RES7, // 保留 ADC0_SE23, // PTE30 DAC0_OUT = ADC0_SE23, // PTE30 DAC0輸出 ,傳入 ADC函數會當作 ADC0_SE23 處理 ADC0_RES8, // 保留 ADC0_RES9, // 保留 Temp0_Sensor, // Temperature Sensor,內部溫度測量,可用ADC函數 Bandgap0, // 溫度補償結構帶隙基准源 不支持ADC ADC0_RES10, // 保留 VREFH0, // 參考高電壓,可用ADC函數 ,結果恆為 2^n-1 VREFL0, // 參考低電壓,可用ADC函數 ,結果恆為 0 Module0_Dis, // 不支持 ADC } ADCn_Ch_e; typedef enum //ADC模塊 { ADC0, ADC1 } ADCn_e; //精度位數 typedef enum ADC_nbit { ADC_8bit = 0x00, ADC_10bit = 0x02, ADC_12bit = 0x01, ADC_16bit = 0x03 } ADC_nbit; enum HardwareAverage { sample4 = 0, sample8 = 1, sample16 = 2, sample32 = 3, }; //外部函數接口聲明 extern void adc_init (ADCn_Ch_e); //ADC初始化 extern uint16_t adc_once (ADCn_Ch_e, ADC_nbit); //采集一次一路模擬量的AD值 extern uint16_t ad_ave(ADCn_Ch_e adcn_ch, ADC_nbit bit, uint8_t N); //均值濾波 extern void adc_stop (ADCn_e); //停止ADC轉換 #endif
2、ADC主文件
#include "adc.h" ADC_MemMapPtr ADCN[1] = {ADC0_BASE_PTR}; //定義一個指針數組保存 ADCN 的地址 void adc_start(ADCn_Ch_e adcn_ch, ADC_nbit bit) ; /*! * @brief ADC初始化 * @param ADCn_Ch_e ADC通道 * @since v5.0 * @note 此初始化僅支持軟件觸發,不是每個通道都支持ADC 軟件觸發, 具體說明見 ADCn_Ch_e 的注釋說明 * Sample usage: adc_init (ADC0_SE10 ); //初始化 ADC0_SE10 ,使用 PTA7 管腳 */ void adc_init(ADCn_Ch_e adcn_ch) { uint8_t adcn = adcn_ch >> 5 ; //uint8_t ch = adcn_ch & 0x1F; //ADC_MemMapPtr adc_ptr = ADCN[adcn]; 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); break; default: ASSERT(0); } switch(adcn_ch) { case ADC0_SE0: port_init(PTE20, ALT0); break; case ADC0_SE1: port_init(PTE16, ALT0); break; case ADC0_SE2: port_init(PTE18, ALT0); break; case ADC0_SE3: port_init(PTE22, ALT0); break; case ADC0_SE4a: port_init(PTE21, ALT0); break; case ADC0_SE5a: port_init(PTE17, ALT0); break; case ADC0_SE6a: port_init(PTE19, ALT0); break; case ADC0_SE7a: port_init(PTE23, ALT0); break; case ADC0_SE8: port_init(PTB0, ALT0); break; case ADC0_SE9: port_init(PTB1, ALT0); break; case ADC0_SE11: port_init(PTC2, ALT0); break; case ADC0_SE12: port_init(PTB2, ALT0); break; case ADC0_SE13: port_init(PTB3, ALT0); break; case ADC0_SE14: port_init(PTC0, ALT0); break; case ADC0_SE15: port_init(PTC1, ALT0); break; case ADC0_SE23: port_init(PTE30, ALT0); break; case Temp0_Sensor: // Temperature Sensor,內部溫度測量,可用ADC函數 break; case VREFH0: // 參考高電壓,可用ADC函數 ,結果恆為 2^n-1 break; case VREFL0: // 參考低電壓,可用ADC函數 ,結果恆為 0 break; default: ASSERT(0); //斷言,傳遞的管腳不支持 ADC 單端軟件觸發,請換 其他管腳 break; } } uint16_t adc_once(ADCn_Ch_e adcn_ch, ADC_nbit bit) //采集某路模擬量的AD值 { ADCn_e adcn = (ADCn_e)(adcn_ch >> 5) ; uint16_t result = 0; adc_start(adcn_ch, bit); //啟動ADC轉換 while (( ADC_SC1_REG(ADCN[adcn], 0 ) & ADC_SC1_COCO_MASK ) != ADC_SC1_COCO_MASK); //只支持A通道 result = ADC_R_REG(ADCN[adcn], 0); ADC_SC1_REG(ADCN[adcn], 0) &= ~ADC_SC1_COCO_MASK; return result; } /************************************************************************* * 野火嵌入式開發工作室 * * 函數名稱:ad_ave * 功能說明:多次采樣,取平均值 * 參數說明:ADCx 模塊號( ADC0、 ADC1) * ADC_Channel 通道號 * ADC_nbit 精度( ADC_8bit,ADC_12bit, ADC_10bit, ADC_16bit ) * N 均值濾波次數(范圍:0~255) * 函數返回:16位無符號結果值 * 修改時間:2012-2-10 * 備 注:修改蘇州大學的例程 *************************************************************************/ uint16_t ad_ave(ADCn_Ch_e adcn_ch, ADC_nbit bit, uint8_t N) //均值濾波 { uint32_t tmp = 0; uint8_t i; //ASSERT( ((adcn == ADC0) && (ch >= AD8 && ch <= AD18)) || ((adcn == ADC1) && (ch >= AD4a && ch <= AD17)) ) ; //使用斷言檢測ADCn_CHn是否正常 for(i = 0; i < N; i++) tmp += adc_once(adcn_ch,bit); tmp = tmp / N; return (uint16_t)tmp; } /*! * @brief 啟動ADC軟件采樣(不支持B通道) * @param ADCn_Ch_e ADC通道 * @param ADC_nbit ADC精度( ADC_8bit,ADC_12bit, ADC_10bit, ADC_16bit ) * @since v5.0 * @note 此函數內部調用,啟動后即可等待數據采集完成 * Sample usage: adc_start(ADC0_SE10, ADC_8bit); */ void adc_start(ADCn_Ch_e adcn_ch, ADC_nbit bit) { ADCn_e adcn = (ADCn_e)(adcn_ch >> 5) ; uint8_t ch = (uint8_t)(adcn_ch & 0x1F); //初始化ADC默認配置 ADC_CFG1_REG(ADCN[adcn]) = (0 //| ADC_CFG1_ADLPC_MASK //ADC功耗配置,0為正常功耗,1為低功耗 | ADC_CFG1_ADIV(2) //時鍾分頻選擇,分頻系數為 2^n,2bit | ADC_CFG1_ADLSMP_MASK //采樣時間配置,0為短采樣時間,1 為長采樣時間 | ADC_CFG1_MODE(bit) | ADC_CFG1_ADICLK(0) //0為總線時鍾,1為總線時鍾/2,2為交替時鍾(ALTCLK),3為 異步時鍾(ADACK)。 ); ADC_CFG2_REG(ADCN[adcn]) = (0 //| ADC_CFG2_MUXSEL_MASK //ADC復用選擇,0為a通道,1為b通道。 //| ADC_CFG2_ADACKEN_MASK //異步時鍾輸出使能,0為禁止,1為使能。 | ADC_CFG2_ADHSC_MASK //高速配置,0為正常轉換序列,1為高速轉換序列 | ADC_CFG2_ADLSTS(0) //長采樣時間選擇,ADCK為4+n個額外循環,額外循環,0為20,1為12,2為6,3為2 ); //寫入 SC1A 啟動轉換 ADC_SC1_REG(ADCN[adcn], 0 ) = (0 | ADC_SC1_AIEN_MASK // 轉換完成中斷,0為禁止,1為使能 //| ADC_SC1_DIFF_MASK // 差分模式使能,0為單端,1為差分 | ADC_SC1_ADCH( ch ) //輸入通道選擇位 ); //ADC_SC1_REG(ADCN[adcn], 1 ) = 0; } /*! * @brief 停止ADC軟件采樣 * @param ADCn_e ADC模塊號( ADC0、 ADC1) * @since v5.0 * Sample usage: adc_stop(ADC0); */ void adc_stop(ADCn_e adcn) { ADC_SC1_REG(ADCN[adcn], 0) = (0 | ADC_SC1_AIEN_MASK // 轉換完成中斷,0為禁止,1為使能 //| ADC_SC1_DIFF_MASK // 差分模式使能,0為單端,1為差分 | ADC_SC1_ADCH(Module0_Dis) //輸入通道選擇,此處選擇禁止通道 ); }
二、使用方法:
uint16_t t=0; adc_init(ADC0_DP0); //ADC初始化 while(1) { t = adc_once(ADC0_DP0, ADC_16bit); //采集一次一路模擬量的AD值 }