智能车学习(三)—— 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值
 }
posted @ 2015-10-08 20:25  Blue Mountain  阅读(3810)  评论(0编辑  收藏  举报