zoukankan      html  css  js  c++  java
  • 智能车学习(三)—— 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值
     }
  • 相关阅读:
    移动端高清、多屏适配方案
    Cookie存中文乱码的问题
    手机网站-前端开发布局技巧汇总
    深入理解javascript中的立即执行函数(function(){…})()
    test
    [PAT] A1013 Battle Over Cities (25分)
    PAT索引
    [PAT] A1012 The Best Rank
    [PAT] A1091 Acute Stroke
    [PAT] A1067 Sort with Swap(0, i)
  • 原文地址:https://www.cnblogs.com/BlueMountain-HaggenDazs/p/4862192.html
Copyright © 2011-2022 走看看