CB2201 ADC应用指南

简介: 介绍CB2201开发板的ADC外设使用

CB2201 ADC应用指南

1. 了解CB2201中的ADC

CB2201开发板上有一个16通道的ADC,其中连接到YoC接口上的通道有14个,这14个通道在开发板上的位置如下:

image.png

*注意
在使用ADC个通道的时候,一定要注意与这些通道引脚复用的功能。比如:CH14 和CH15 通道复用的是IIC 功能。最需要的注意的是:CH2 和CH3 通道复用的是CSI 程序默认的printf 输出串口,如果使用了CH2 和CH3 通道将导致默认的printf 没有任何输出。*
用户可使用3种模式操作ADC

  1. 单通道单次转换模式
  2. 单通道多次转换模式
  3. 多通道扫描转换模式

1.ADC寄存器说明

寄存器名 地址 宽度 说明 复位默认值
ADC_CR 0x6000 11 ADC控制寄存器 0x0001
ADC_DR 0x6004 12 ADC数据寄存器 0x0000
ADC_SR 0x6008 9 ADC状态寄存器 0x0000
ADC_CMPR 0x600C 22 ADC比较寄存器 0x0000
ADC_IE 0x6010 3 ADC中断使能寄存器 0x0000
ADC_IFLG 0x6014 3 ADC中断状态寄存器 0x0000
ADC_STC 0x6018 1 ADC启动寄存器 0x0000
ADC_SAMSEL 0x601C 1 ADC采样模式选择寄存器 0x0001
ADC_DMACR 0x6020 1 ADC FIFO DMA使能寄存器 0x0000
ADC_DMADL 0x6024 4 ADC DMA接收数据深度 0x0000

1.1 寄存器简介

关于寄存器更详细的描述,请参考CH2201 芯片手册。
ADC_CR ADC控制寄存器

Bits Fields R/W Description
[31:12] Reserved
[11:8] SEQC R/W SEQ 模式下,转换次数
[7] Reserved
[6:3] CH_SEL R/W 通道选择
[2:1] CMS R/W 模式选择
00 = 单通道单次
01 = 多通道扫描
10 = 单通道连续
[0] ADC_DOWN R/W ADC模块关闭
0 = ADC模块使能
1 = ADC模块关闭

ADC_DR ADC数据寄存器

Bits Fields R/W Description
[31:12] Reserved
[11:0] DATA R/W ADC转换结果

ADC_SR ADC状态寄存器

Bits Fields R/W Description
[31:9] Reserved
[8] OVERW R 转换结果数据覆盖
[7] VALID R 转换结果数据有效
[6:3] CCC R 当前转换通道
[2] BUSY R ADC正在转换中
[1] CMPF R 转换结果匹配中比较寄存器
[0] ADEF R 转换结束

ADC_CMPR ADC比较寄存器

Bits Fields R/W Description
[31:22] Reserved
[21:10] CMPD R/W 比较阈值
[9:6] CNT R/W 比较匹配次数
[5:2] CMPCH R/W 比较通道选择
[1] CMPCOND R/W 比较条件设置
0 = 小于阈值匹配
1 = 大于等于阈值匹配
[0] CMPEN R/W 比较功能使能

ADC_IE ADC中能使能寄存器

Bits Fields R/W Description
[31:3] Reserved
[2] CMPIE R/W 比较匹配中断使能
[1] OVWRIE R/W 数据覆盖中断使能
[0] CPLTIE R/W 采样转换结束中断使能

ADC_IFLG ADC中断状态寄存器

Bits Fields R/W Description
[31:3] Reserved
[2] CMPIE R/W 比较匹配中断
[1] OVWRIE R/W 数据覆盖中断
[0] CPLTIE R/W 采样转换结束中断

ADC_STC ADC启动转换寄存器

Bits Fields R/W Description
[31:1] Reserved
[0] START R/W ADC采样触发位

ADC_SAMSEL ADC采样设置寄存器

Bits Fields R/W Description
[31:1] Reserved
[0] SAMSEL R/W 不重要

ADC_DMACR ADC DMA控制寄存器

Bits Fields R/W Description
[31:1] Reserved
[0] DMAEN R/W DMA功能使能

ADC_DMADL ADC DMA数据深度寄存器

Bits Fields R/W Description
[31:4] Reserved
[3:0] DMADL R/W DMA触发条件
当ADC采样到足够的数据时(超过DMADL 个数据),就会触发DMA请求

2. 驱动程序的使用

*要使用本文中的驱动程序,首先将附录中的驱动文件保存到本地并添加到CDK工程中
.c 文件添加到工程中,.h 文件复制到CDK 的include 路径中*
使用该驱动程序也非常简单:1. 配置ADC通道输入引脚;2. 开始转换并读取转换结果。 具体如下:

2.1 单通道单次转换模式

以下程序演示对两个通道:ADC_CH0 和 ADC_CH10 分别进行单通道单次采样,并将结果打印:

#include <stdio.h>
#include "soc.h"
#include "my_adc.h"

int main(void)
{
    uint32_t adc_value;
    
    // single channel, single convertion
    adc_pin_init(0);    // adc channel 0 pin initialize
    adc_pin_init(10);   // adc channel 10 pin initialize
    while (1) {
        adc_single_read(0, &adc_value);
        printf("analog value from CH0 = %d\n", adc_value);
        adc_single_read(10, &adc_value);
        printf("analog value from CH10 = %d\n", adc_value);
       mdelay(1000);
    }
}

以上程序调用了驱动程序中的两个函数:
adc_pin_init()
第一个参数:ADC通道选择,该参数可以是范围从0 到15

adc_single_read()
第一个参数:ADC通道选择,该参数可以是范围从0 到15
第二个参数:ADC转换结果存放位置,是一个int型指针,函数执行完成后会将ADC结果存入到指针指向的位置

将CB2201 开发板串口连接到计算机,并打开一个串口终端。
编译下载程序,然后复位开发板。
将CH0 或者CH10 通道通过杜邦线连接到GND 或者3.3V 上,看打印结果有什么变化。

2.2 单通道连续转换模式

以下程序演示在Channel 0上,一次连续采样10次,并将采样结果通过串口打印出:

#include <stdio.h>
#include "soc.h"
#include "my_adc.h"

int main (void)
{
    uint32_t adc_value[16];
    uint32_t tmp_i;
    
    // single channel, continous convertion
    adc_pin_init(0);
    
    while (1) {
        adc_seq_read(0, 10, adc_value);  // ADC onvert 10 times continously
        for (tmp_i=0; tmp_i<10; tmp_i++) {
            printf("adc_value[%d] = %d\n", tmp_i, adc_value[tmp_i]);
        }
        mdelay(1000);
    }
}

以上程序调用了驱动程序中的两个函数:
adc_pin_init()
第一个参数:ADC通道选择,该参数可以是范围从0 到15

adc_seq_read()
第一个参数:ADC通道选择,该参数可以是范围从0 到15
第二个参数:ADC连续转换次数,该参数可以使范围从0 到15
第三个参数:ADC转换结果存放位置,是一个int型指针,函数执行完成后会将ADC结果存入到指针指向的位置

将CB2201 开发板串口连接到计算机,并打开一个串口终端。
编译下载程序,然后复位开发板。
将CH0 通道通过杜邦线连接到GND 或者3.3V 或者在0到3.3V之间的电压上,看打印结果有什么变化。

在单通道连续转换模式下,每次小的转换操作需要14 个时钟周期。如:连续转换10 次,总共需要140 个时钟周期。

2.3 多通道扫描模式

以下程序演示对ADC 通道从CH0 和CH1 的扫描操作。

#include <stdio.h>
#include "soc.h"
#include "my_adc.h"
int main (void)
{
    uint32_t adc_value[16];
    uint32_t tmp_i;
    
    // multi-channel, scan mode
    adc_pin_init(0);
    adc_pin_init(1);

    
    while (1) {
        adc_scan_read(1, adc_value);    // ADC convert 2 times, from channel 0 to channel 1
        for (tmp_i=0; tmp_i<2; tmp_i++) {
            printf("adc_value[%d] = %d\n", tmp_i, adc_value[tmp_i]);
        }
        mdelay(1000);        
    }
}

以上程序调用了驱动程序中的两个函数:
adc_pin_init()
第一个参数:ADC通道选择,该参数可以是范围从0 到15

adc_scan_read()
第一个参数:ADC通道选择,该参数可以是范围从0 到15,表示在ADC转换中,从CH0 扫描到该参数表示的通道
第二个参数:ADC转换结果存放位置,是一个int型指针,函数执行完成后会将ADC结果存入到指针指向的位置

将CB2201 开发板串口连接到计算机,并打开一个串口终端。
编译下载程序,然后复位开发板。
将CH0 或者CH1 通道通过杜邦线连接到GND 或者3.3V 或者在0到3.3V之间的电压上,看打印结果有什么变化。

2.4 使用ADC中断

以下程序演示如何使用ADC中断。程序开启ADC转换之后可以去执行其他操作,等到ADC 转换完成之后,ADC向CPU 发出中断信号,然后CPU 才会将ADC 转换结果读出。

#include <stdio.h>
#include "soc.h"
#include "my_adc.h"
#include "drv_adc.h"

volatile uint32_t adc_value[16];
volatile uint32_t adc_cmplt;
    
void adc_interrupt_callback (int32_t idx, adc_event_e event)
{
    printf("adc interrupt ...\n");
    if (event == ADC_EVENT_CONVERSION_COMPLETE) {
        adc_read(adc_value, 10);
        adc_cmplt = 1;
    }
}

int main (void)
{
    uint32_t tmp_i;
    
    // single channel, continous convertion
    adc_pin_init(0);
    drv_adc_initialize(0, adc_interrupt_callback);
    adc_enable_cnv_interrupt();
    
    adc_seq_start(0, 10);
    
    
    while (1) {
        if (adc_cmplt) {
            adc_cmplt = 0;
            for (tmp_i=0; tmp_i<10; tmp_i++) {
                printf("adc_value[%d] = %d\n", tmp_i, adc_value[tmp_i]);
            }
            mdelay(1000);
            adc_seq_start(0, 10);
        }
    }
}

以上程序中,
首先实现一个ADC中断回调函数:
adc_interrupt_callback, 该函数有两个参数:
第一个参数:ADC设备编号,这个参数在回调函数中用不到的。
第二个参数:ADC中断类型,按照上面寄存器说明中的介绍,ADC中断类型有3 种,分别为:

ADC_EVENT_CONVERSION_COMPLETE, ADC_EVENT_DATA_OVERWRITE, ADC_EVENT_DATA_COMPARE_VALID

然后需要调用adc_pin_init()函数初始化ADC 引脚;
调用drv_adc_initialize()函数指定ADC 的中断回调函数;
调用adc_seq_read()函数,开启单通道连续转换
在函数主循环中,等待ADC 转换完成,并开启新的转换。

按照之前章节中所述开始演示本例程,查看结果。

2.5 使用ADC比较功能

以下程序演示如何使用ADC中的比较功能。
这个功能是:开启ADC采样,如果采样到的数值大于等于(或者小于)用户设定的一个阈值,就会把比较匹配的标志位置起来,如果用户同时开启的相应的中断,则还会产生一个中断。

#include <stdio.h>
#include "soc.h"
#include "my_adc.h"
#include "drv_adc.h"
volatile uint32_t adc_value[16];
volatile uint32_t adc_cmplt, adc_cmp_vld;
    
void adc_interrupt_callback (int32_t idx, adc_event_e event)
{
    printf("adc interrupt ...\n");
    if (event == ADC_EVENT_CONVERSION_COMPLETE) {
        adc_read(adc_value, 10);
        adc_cmplt = 1;
    } else if (event == ADC_EVENT_DATA_COMPARE_VALID) {
        adc_cmp_vld = 1;
    }
}

int main (void)
{
    uint32_t tmp_i;
    
    // single channel, continous convertion
    adc_pin_init(0);
    drv_adc_initialize(0, adc_interrupt_callback);
    adc_enable_cnv_interrupt();
    adc_enable_cmp_interrupt();
    adc_set_compare(0, 4000, ADC_CMP_GE, 0);
    
    //adc_single_start(0);
    adc_seq_start(0, 10);
    
    
    while (1) {
        if (adc_cmplt) {
            adc_cmplt = 0;
            printf("adc_value[%d] = %d\n", 0, adc_value[0]);
            mdelay(1000);
            //adc_single_start(0);
            adc_seq_start(0, 10);
        } 
        if (adc_cmp_vld) {
            adc_cmp_vld = 0;
            printf("ADC compare valid ...\n");
        }
    }
}

以上程序中,
首先实现一个ADC中断回调函数:adc_interrupt_callback,
该函数有两个参数:
第一个参数:ADC设备编号,这个参数在回调函数中用不到的。
第二个参数:ADC中断类型,按照上面寄存器说明中的介绍,ADC中断类型有3 种,分别为:

ADC_EVENT_CONVERSION_COMPLETE, ADC_EVENT_DATA_OVERWRITE, ADC_EVENT_DATA_COMPARE_VALID,

这次我们需要处理的类型有两种;

然后需要调用adc_pin_init()函数初始化ADC 引脚;
drv_adc_initialize() 函数指定ADC 的中断回调函数;
adc_enable_xx_interrupt() 使能相应的中断;
adc_set_compare()设置比较条件:该函数需要4 个参数:

  1. 通道选择:设置需要比较的通道;
  2. 比较阈值:
  3. 比较条件:ADC_CMP_GE 表示大于等于阈值,ADC_CMP_LT表示小于阈值;
  4. 匹配次数:设置需要联系匹配多少次才会设置标志位,0 表示只要匹配一次机会设置标志位继而可以产生中断;

然后再循环中等待转换结果和匹配结果。
本文作者:huanghh
点击查看原文

相关文章
|
7月前
|
传感器
AC31 40和50系列
AC31 40和50系列
AC31 40和50系列
|
6月前
|
传感器 网络架构
使用AC/DC电源模块的案例
使用AC/DC电源模块的案例
使用AC/DC电源模块的案例
|
7月前
选择适合自己应用的AC/DC电源模块
选择适合自己应用的AC/DC电源模块
选择适合自己应用的AC/DC电源模块
|
7月前
|
监控 数据库
ABB AC800F SD802F电源模块
ABB AC800F SD802F电源模块
ABB AC800F SD802F电源模块
|
7月前
|
监控 数据可视化 机器人
ABB 分布式控制系统-DCS AC700F 控制器
ABB 分布式控制系统-DCS AC700F 控制器
|
7月前
|
存储
STM32--ADC模数转换
STM32--ADC模数转换
136 0
|
7月前
|
芯片
|
7月前
|
传感器 监控
ABB SPAD346C 集成式差动继电器
ABB SPAD346C 集成式差动继电器
|
人工智能 搜索推荐 BI
GJR5251200R0101 07EA90-SI
GJR5251200R0101 07EA90-SI
44 0

热门文章

最新文章