杰理 AC632 芯片 ADC

        蓝牙芯片有2种ADC,一种是普通多通道10bit ADC,一种是音频mic单通道16bit LADC。

普通ADC => 无DMA,单次采样单通道,带校准带参考电压,ADC采样值可以换算成绝对电压值。

音频LADC => 支持DMA连续采样,无参考电压,一般用作交流变化量的采样使用。

 普通ADC外设说明:

量程电压 => 强VDDIO的电压值,满值ADC值:0x3FFL对应芯片的VDDIO电压值。 强VDDIO设置为VDDIOM_VOL_32V,即3.2V,那能测量的范围就是0V-3.2V。 强VDDIO设置为VDDIOM_VOL_30V,即3.0V,那能测量的范围就是0V-3.0V。
参考电压 => LDOREF电压,芯片内部的固定幅值参考电压。(生产会存在一定的离散)
校准值 => 芯片出产校准值,get_vbg_trim(),校准芯片LDOREF电压的偏差值。

ADC通道说明:

芯片内部通道 => 芯片内部某些外设或结构电路,会预留有ADC通道,连接到ADC外设,用于芯片内部模块的自校准。
外部通道GPIO引脚 => 引脚是否具有ADC功能,是固定的,软件无法映射的。设计板子注意引脚功能。

 SDK有专门的接口文件 adc_api.c 和adc_api.h。
adc的使用方式,SDK预留了2种方式:

注册定时采样 => u32 adc_add_sample_ch(u32 ch); 在定时器中断函数里,定时轮询所有的注册通道。注册的通道越多,轮询的时间越长。 usr_timer_add(NULL, adc_scan, 10, 0); 此语句即每10ms切换下一个通道采样。
独占式立即采样 => adc_enter_occupy_mode(); adc_occupy_run(); adc_exit_occupy_mode(); 立即采样需要打断定时轮询的操作。立即采样当前设置的通道。 一般用于采样频率高,电压变化快,采样时刻短的场景。

1. 注册定时采样

//以下初始化代码添加到void adc_init()里
u32 gpio = IO_PORTA_01;//指定IO,要和ADC通道对应上
gpio_set_pull_down(gpio, 0);//看需求是否需要开内部下拉,会有20%的误差,不同芯片理论电阻值不一样,看规格书说明
gpio_set_pull_up(gpio, 0);//看需求是否需要开内部上拉,会有20%的误差,不同芯片理论电阻值不一样,看规格书说明
gpio_set_die(gpio, 0);//模拟态
gpio_set_dieh(port, 0);//模拟态
gpio_set_direction(gpio, 1);//输入态
u32 ch = AD_CH_PA1; ///指定ADC通道,要和GPIO对应上
adc_add_sample_ch(ch);//添加检测通道
#define CH_SAMPLE_FREQ    1000 //ms
adc_set_sample_freq(ch, CH_SAMPLE_FREQ);//设置固定的采样频率,一般不设置,就是最高的轮询时间

//以下2句自己写个函数丢定时器里
//注意:这里只负责读取AD转换的结果值和根据VDDIO换算出电压值,并不是实际的AD转换过程。AD转换是adc_sample(ch)函数开启的,转换完成后会进入中断,在中断服务函数___interrupt static void adc_isr()里读取结果。

u32 adc = adc_get_value(ch); //!!!切记,不建议用adc值做判断,不同的VDDIO电压adc值是不一样!!!
u32 voltage = adc_get_voltage(ch);//一定要用带校准值换算的接口,电压值才是准确的

 2. 独占式立即采样

u32 io_adc_check(u8 port, u8 ch) //耗时250us
{
    log_info("%s[%d %d]", __func__, port, ch);
    u32 adc_value = 0;
    u32 voltage = 0;
    gpio_set_die(port, 0);//模拟态
    gpio_set_dieh(port, 0);//模拟态
    gpio_set_direction(port, 1);//输入态
    gpio_set_pull_down(port, 0);
    gpio_set_pull_up(port, 0);
    adc_enter_occupy_mode(ch); //!!!注意此函数有bug,不一定会进入独占模式
    // 参考下面说明优化 while(adc_enter_occupy_mode(ch));
    adc_value = adc_occupy_run();
    adc_exit_occupy_mode();
    voltage = adc_value_to_voltage(adc_get_value(AD_CH_LDOREF), adc_value);
    log_info("%s[0x%08x %d]", __func__, adc_value, voltage);
    return voltage;
}
u32 voltage = io_adc_check(IO_PORTA_01, AD_CH_PA1);
//公版SDK独占模式adc采样的bug优化
int adc_enter_occupy_mode(u32 ch) //此函数改成带返回值
{
    if (JL_ADC->CON & BIT(4)) {
        return 1;
    }
    adc_queue[ADC_MAX_CH].ch = ch;
    cur_ch_value = adc_sample(ch);
    return 0;
}
while(adc_enter_occupy_mode(ch)); //调用方式改成while死等adc中断释放adc外设,其他语句不变

3.抢占式快速采样立即采样

static volatile u8 is_break = 0;
void adc_scan(void *priv)
{
    static u8 adc_sample_flag = 0;
    if (adc_queue[ADC_MAX_CH].ch != -1) {   //occupy mode
        return;
    }
    if (JL_ADC->CON & BIT(4)) {
        return ;
    }
    if(is_break){ // 添加此段代码 start
        adc_sample(adc_queue[cur_ch].ch);
        is_break = 0;
        return;
    }             // 添加此段代码 end
    if (adc_sample_flag) {
    ......
}
AT_VOLATILE_RAM_CODE//指定以下函数放到内部RAM里运行
u32 adc_fast_sample(u32 ch) //96M频率耗时1us-2us之间
{
    /* printf("%s[%d 0x%x]", __func__, clk_get("lsb"), ch); */
    u16 adc_value = 0;
    /* local_irq_disable(); */
    is_break = 1; //打断原先未采样完的通道,adc_scan需要重新设置采样
    adc_queue[ADC_MAX_CH].ch = ch;
    JL_ADC->CON = BIT(6);//CPND:只写,写‘1’清除中断请求位,写‘0’无效(该 bit充当 kst,对该写‘1’将启动 ADC 转换)
    JL_ADC->CON |= ((ch&0xf)<<8);//IO通道
    JL_ADC->CON |= ((0x0<<12)|BIT(4)|BIT(3)|(0b000));//lsb 1分频
    JL_ADC->CON |= BIT(6);//启动 ADC 转换
    while ((JL_ADC->CON & BIT(7)) == 0);//判断是否转换完成。PND:只读,中断请求位,当 ADC 完成一次转换后,此位会被设置为‘1’,需由软件清‘0’
    adc_value = JL_ADC->RES;//读取转换结果
    JL_ADC->CON = BIT(6);//清除中断请求位
    adc_queue[ADC_MAX_CH].ch = -1;
    /* local_irq_enable(); */
    return adc_value;
}

4. 其他注意事项
公版SDK初始化的ADC采样时钟不高,采样一次大概耗时66us,理论最高可做到2us采样一次。
程序在开机的时候,必须要调用 adc_init(), 不要调整SDK此函数的调用位置 ,建议其他功能都要放到此函数之后。
注册定时采样和独占式采样和抢占式快速采样均是使用中断方式。
检测外部电压较高的电池(超过4.5V)时,硬件上可以用分压电阻加MOS管方式,软件上采用快速抢占式立即采样,在检测前打开MOS管,检测完毕关闭MOS即可,可以极大的降低系统功耗。
————————————————
版权声明:本文为CSDN博主「ydgd118」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ydgd118/article/details/128188758

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值