BF7006学习笔记6 - ADC

目录

1. 初始化

1.1 关闭ADC

1.2 设置触发方式

1.3 设置分频率

1.4 设置频率

1.5 时序设置

1.5.1 采样时序与比较时序间隔选择

1.5.2 采样延迟时间选择

1.5.3 采样完毕后距离转换间隔时间选择

1.5.4 模拟输入时钟信号分频

1.6 设置采样时间

1.7 默认寄存器配置

2. 使能ADC

2.1 使能通道

2.2 开启ADC

2.3 开启转换

3. 获取结果


BF7006的ADC是12位的,只有一组,共28个通道,其中24个是外部通道。 

#define HW_ADC_CH_0            0
#define HW_ADC_CH_1            1
#define HW_ADC_CH_2            2
#define HW_ADC_CH_3            3
#define HW_ADC_CH_4            4
#define HW_ADC_CH_5            5
#define HW_ADC_CH_6            6
#define HW_ADC_CH_7            7
#define HW_ADC_CH_8            8
#define HW_ADC_CH_9            9
#define HW_ADC_CH_10           10
#define HW_ADC_CH_11           11
#define HW_ADC_CH_12           12
#define HW_ADC_CH_13           13
#define HW_ADC_CH_14           14
#define HW_ADC_CH_15           15
#define HW_ADC_CH_16           16
#define HW_ADC_CH_17           17
#define HW_ADC_CH_18           18
#define HW_ADC_CH_19           19
#define HW_ADC_CH_20           20
#define HW_ADC_CH_21           21
#define HW_ADC_CH_22           22
#define HW_ADC_CH_23           23
#define HW_ADC_CH_24           24            //VREFA
#define HW_ADC_CH_25           25            //VREFS
#define HW_ADC_CH_26           26            //Temperature
#define HW_ADC_CH_27           27            //BG(1.267V Typical)
#define HW_ADC_CH_MAX          28

为了保持通道连续, 把VREFA和VREFS改到通道24、25,软件上做变换。

1. 初始化

1.1 关闭ADC

ADC_SC1寄存器的输入通道位选择全部设置为1即可关闭ADC。

ADC_SC1 = 0x1f;

默认使用单次转换(位5为0)。

1.2 设置触发方式

通过ADC_SC2 寄存器的位6设置触发方式,默认设置为软件触发。

ADC_SC2 = 0;

1.3 设置分频率

通过ADC_CFG寄存器的位2设置。

if(resolution == 8)
    ADC_CFG = 0;                //resolution = 8
else
    ADC_CFG = (1 << 2);         //resolution = 12

1.4 设置频率

ADC的时钟源只有系统时钟。通过ADC_CFG寄存器的位4:6设置频率分频系数。 当系统时钟等于32M时,ADC必须最少二分频,即ADC最大支持16M。

switch(clkDiv)
{
    case ADC_CLK_DIV1:
    default:
        if(SystemCoreClock == (uint32_t)32*1000*1000)
            ADC_CFG |= (1 << 4);                        //max support 16M
        break;
    case ADC_CLK_DIV2:
        ADC_CFG |= (1 << 4);
        break;
    case ADC_CLK_DIV3:
        ADC_CFG |= (7 << 4);
        break;
    case ADC_CLK_DIV4:
        ADC_CFG |= (2 << 4);
        break;
    case ADC_CLK_DIV6:
        ADC_CFG |= (3 << 4);
        break;
    case ADC_CLK_DIV8:
        ADC_CFG |= (4 << 4);
        break;
    case ADC_CLK_DIV10:
        ADC_CFG |= (5 << 4);
        break;
    case ADC_CLK_DIV12:
        ADC_CFG |= (6 << 4);
        break;
}

1.5 时序设置

一个完整的ADC转换过程由以下时序组成:T= Timer1+ Sample_Time+ Time2+ Time3

Timer1=(ADC_CKC_SAMDEL+2)* 单个ADC时钟时间;

Sample_Timer= (ADC_SPT+1)* 单个ADC时钟时间;

Time2=(ADC_CKC_WNUM +3)* 单个ADC时钟时间;

Time3=(12+2)* 单个ADC时钟时间(12位模式)

Time3=(8+2)* 单个ADC时钟时间(8位模式)

通过ADC_CKC 寄存器设置时序。

1.5.1 采样时序与比较时序间隔选择

通过ADC_CKC寄存器的位7设置。

 ADC可以配置比较功能来检查上限或下限,这里是设置采样时序与比较时序间隔,一般是设置为1个ADC时钟。

ADC_CKC = (1 << 7);

1.5.2 采样延迟时间选择

通过ADC_CKC寄存器的位4:6设置。

 即设置ADC转换过程中Timer1的时间。这个时间遵循的是频率越高,数字越大,似乎没规律,只能参考例程设置对应的值。

1.5.3 采样完毕后距离转换间隔时间选择

通过ADC_CKC寄存器的位2:3设置。

 即设置ADC转换过程中Time2的时间。

1.5.4 模拟输入时钟信号分频

通过ADC_CKC寄存器的位1:0设置。

这个具体的信息没有写,只有一个要求:需保证ADC_CKC_WNUM *ADC时钟周期>5*(系统时钟的ADC_CKC_CKV配置周期)

以上3个配置没有规律,所以只能参考例程配置(可能是经验值):

ADC_CKC |= 0x00 | ((uint8_t)0x00 << 2) | ((uint8_t)0x01 << 4);      //CKV = 1, WNUM = 3, SAMDEL = 2
switch(clkDiv)
{
    case ADC_CLK_DIV1:
    default:
        if(SystemCoreClock == (uint32_t)32*1000*1000)
        {
            ADC_CFG |= (1 << 4);                        //max support 16M
            ADC_CKC |= 0x01 | ((uint8_t)0x03 << 2) | ((uint8_t)0x03 << 4);      //CKV = 2, WNUM = 6, SAMDEL = 8
        }
        else if(SystemCoreClock == (uint32_t)16*1000*1000)
        {
            ADC_CKC |= 0x00 | ((uint8_t)0x03 << 2) | ((uint8_t)0x03 << 4);      //CKV = 1, WNUM = 6, SAMDEL = 8
        }
        else
        {
            ADC_CKC |= 0x00 | ((uint8_t)0x03 << 2) | ((uint8_t)0x02 << 4);      //CKV = 1, WNUM = 6, SAMDEL = 4
        }
        break;
    case ADC_CLK_DIV2:
        ADC_CFG |= (1 << 4);
        if(SystemCoreClock == (uint32_t)32*1000*1000)
        {
            ADC_CKC |= 0x01 | ((uint8_t)0x03 << 2) | ((uint8_t)0x03 << 4);      //CKV = 2, WNUM = 6, SAMDEL = 8
        }
        else if(SystemCoreClock == (uint32_t)16*1000*1000)
        {
            ADC_CKC |= 0x01 | ((uint8_t)0x03 << 2) | ((uint8_t)0x02 << 4);      //CKV = 2, WNUM = 6, SAMDEL = 4
        }
        break;
    case ADC_CLK_DIV3:
        ADC_CFG |= (7 << 4);
        if(SystemCoreClock == (uint32_t)32*1000*1000)
        {
            ADC_CKC |= 0x01 | ((uint8_t)0x01 << 2) | ((uint8_t)0x03 << 4);      //CKV = 2, WNUM = 4, SAMDEL = 8
        }
        else if(SystemCoreClock == (uint32_t)16*1000*1000)
        {
            ADC_CKC |= 0x01 | ((uint8_t)0x01 << 2) | ((uint8_t)0x02 << 4);      //CKV = 2, WNUM = 4, SAMDEL = 4
        }
        break;
    case ADC_CLK_DIV4:
        ADC_CFG |= (2 << 4);
        if(SystemCoreClock == (uint32_t)32*1000*1000)
        {
            ADC_CKC |= 0x02 | ((uint8_t)0x03 << 2) | ((uint8_t)0x02 << 4);      //CKV = 4, WNUM = 6, SAMDEL = 4
        }
        else if(SystemCoreClock == (uint32_t)16*1000*1000)
        {
            ADC_CKC |= 0x01 | ((uint8_t)0x00 << 2) | ((uint8_t)0x01 << 4);      //CKV = 2, WNUM = 3, SAMDEL = 2
        }
        break;
    case ADC_CLK_DIV6:
        ADC_CFG |= (3 << 4);
        if(SystemCoreClock == (uint32_t)32*1000*1000)
        {
            ADC_CKC |= 0x02 | ((uint8_t)0x00 << 2) | ((uint8_t)0x01 << 4);      //CKV = 4, WNUM = 3, SAMDEL = 2
        }
        else if(SystemCoreClock == (uint32_t)16*1000*1000)
        {
            ADC_CKC |= 0x01 | ((uint8_t)0x00 << 2) | ((uint8_t)0x01 << 4);      //CKV = 2, WNUM = 3, SAMDEL = 2
        }
        break;
    case ADC_CLK_DIV8:
        ADC_CFG |= (4 << 4);
        if(SystemCoreClock == (uint32_t)32*1000*1000)
        {
            ADC_CKC |= 0x02 | ((uint8_t)0x00 << 2) | ((uint8_t)0x01 << 4);      //CKV = 4, WNUM = 3, SAMDEL = 2
        }
        else if(SystemCoreClock == (uint32_t)16*1000*1000)
        {
            ADC_CKC |= 0x01 | ((uint8_t)0x00 << 2) | ((uint8_t)0x01 << 4);      //CKV = 2, WNUM = 3, SAMDEL = 2
        }
        break;
    case ADC_CLK_DIV10:
        ADC_CFG |= (5 << 4);
        if(SystemCoreClock == (uint32_t)32*1000*1000)
        {
            ADC_CKC |= 0x02 | ((uint8_t)0x00 << 2) | ((uint8_t)0x01 << 4);      //CKV = 4, WNUM = 3, SAMDEL = 2
        }
        else if(SystemCoreClock == (uint32_t)16*1000*1000)
        {
            ADC_CKC |= 0x01 | ((uint8_t)0x00 << 2) | ((uint8_t)0x01 << 4);      //CKV = 2, WNUM = 3, SAMDEL = 2
        }
        break;
    case ADC_CLK_DIV12:
        ADC_CFG |= (6 << 4);
        if(SystemCoreClock == (uint32_t)32*1000*1000)
        {
            ADC_CKC |= 0x02 | ((uint8_t)0x00 << 2) | ((uint8_t)0x01 << 4);      //CKV = 4, WNUM = 3, SAMDEL = 2
        }
        else if(SystemCoreClock == (uint32_t)16*1000*1000)
        {
            ADC_CKC |= 0x01 | ((uint8_t)0x00 << 2) | ((uint8_t)0x01 << 4);      //CKV = 2, WNUM = 3, SAMDEL = 2
        }
        break;
}

1.6 设置采样时间

通过ADC_SPT 寄存器设置采样时间,好像也没有什么标准限制,参考例程设为15.

ADC_SPT = 15;

1.7 默认寄存器配置

有3个寄存器是要采用默认的配置,不能修改,也没有任何说明。

ADC_ISEL = 0x19;
ADC_FRSEL = 0x00;
ADC_CTRLSEL = 0x00;

2. 使能ADC

2.1 使能通道

通过ADC_APCTL寄存器设置,每个位对应通道。由于把VREFA和VREFS改到通道24、25,这里做个转换。

    if(port >= HW_ADC_MAX)
        return;
    
    if(ch >= HW_ADC_CH_MAX)
        return;
    
    if(ch == HW_ADC_CH_24)
        ch = 29;
    if(ch == HW_ADC_CH_25)
        ch = 30;
    
    ADC_APCTL = 0x00;
    ADC_APCTL |= ch;

2.2 开启ADC

通过ADC_PD寄存器设置。

ADC_PD = 0x00;

2.3 开启转换

通过设置ADC_SC1的位0:4对应通道即开启转换。

ADC_SC1 |= 0x1f;
ADC_SC1 &= (0xe0 | ch);

3. 获取结果

通过ADC_SC1寄存器的位7判断转换结束。

 然后通过ADC_DATA寄存器得到ADC值。

uint16_t adcGetValue(uint8_t port, uint8_t ch)
{
    while((ADC_SC1 & (1 << 7)) == 0);
    return (uint16_t)ADC_DATA;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深圳驰创芯电子有限公司

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值