智能車學習(三)—— ADC學習


一、代碼分享:

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值
 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM