CB2201 ADC應用指南
1. 了解CB2201中的ADC
CB2201開發闆上有一個16通道的ADC,其中連接配接到YoC接口上的通道有14個,這14個通道在開發闆上的位置如下:

*注意
在使用ADC個通道的時候,一定要注意與這些通道引腳複用的功能。比如:CH14 和CH15 通道複用的是IIC 功能。最需要的注意的是:CH2 和CH3 通道複用的是CSI 程式預設的printf 輸出序列槽,如果使用了CH2 和CH3 通道将導緻預設的printf 沒有任何輸出。*
使用者可使用3種模式操作ADC
- 單通道單次轉換模式
- 單通道多次轉換模式
- 多通道掃描轉換模式
1.ADC寄存器說明
寄存器名 | 位址 | 寬度 | 說明 | 複位預設值 |
---|---|---|---|---|
ADC_CR | 0x6000 | 11 | ADC控制寄存器 | 0x0001 |
ADC_DR | 0x6004 | 12 | ADC資料寄存器 | 0x0000 |
ADC_SR | 0x6008 | 9 | ADC狀态寄存器 | |
ADC_CMPR | 0x600C | 22 | ADC比較寄存器 | |
ADC_IE | 0x6010 | 3 | ADC中斷使能寄存器 | |
ADC_IFLG | 0x6014 | ADC中斷狀态寄存器 | ||
ADC_STC | 0x6018 | 1 | ADC啟動寄存器 | |
ADC_SAMSEL | 0x601C | ADC采樣模式選擇寄存器 | ||
ADC_DMACR | 0x6020 | ADC FIFO DMA使能寄存器 | ||
ADC_DMADL | 0x6024 | 4 | ADC DMA接收資料深度 |
1.1 寄存器簡介
關于寄存器更詳細的描述,請參考CH2201 晶片手冊。
ADC_CR ADC控制寄存器
Bits | Fields | R/W | Description |
---|---|---|---|
[31:12] | Reserved | ||
[11:8] | SEQC | SEQ 模式下,轉換次數 | |
[7] | |||
[6:3] | CH_SEL | 通道選擇 | |
[2:1] | CMS | 模式選擇 00 = 單通道單次 01 = 多通道掃描 10 = 單通道連續 | |
[0] | ADC_DOWN | ADC子產品關閉 0 = ADC子產品使能 1 = ADC子產品關閉 |
ADC_DR ADC資料寄存器
[11:0] | DATA | ADC轉換結果 |
ADC_SR ADC狀态寄存器
[31:9] | |||
[8] | OVERW | R | 轉換結果資料覆寫 |
VALID | 轉換結果資料有效 | ||
CCC | 目前轉換通道 | ||
[2] | BUSY | ADC正在轉換中 | |
[1] | CMPF | 轉換結果比對中比較寄存器 | |
ADEF | 轉換結束 |
ADC_CMPR ADC比較寄存器
[31:22] | |||
[21:10] | CMPD | 比較門檻值 | |
[9:6] | CNT | 比較比對次數 | |
[5:2] | CMPCH | 比較通道選擇 | |
CMPCOND | 比較條件設定 0 = 小于門檻值比對 1 = 大于等于門檻值比對 | ||
CMPEN | 比較功能使能 |
ADC_IE ADC中能使能寄存器
[31:3] | |||
CMPIE | 比較比對中斷使能 | ||
OVWRIE | 資料覆寫中斷使能 | ||
CPLTIE | 采樣轉換結束中斷使能 |
ADC_IFLG ADC中斷狀态寄存器
比較比對中斷 | |||
資料覆寫中斷 | |||
采樣轉換結束中斷 |
ADC_STC ADC啟動轉換寄存器
[31:1] | |||
START | ADC采樣觸發位 |
ADC_SAMSEL ADC采樣設定寄存器
SAMSEL | 不重要 |
ADC_DMACR ADC DMA控制寄存器
DMAEN | DMA功能使能 |
ADC_DMADL ADC DMA資料深度寄存器
[31:4] | |||
[3:0] | DMADL | 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轉換結果存放位置,是一個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_seq_read()
第二個參數:ADC連續轉換次數,該參數可以使範圍從0 到15
第三個參數:ADC轉換結果存放位置,是一個int型指針,函數執行完成後會将ADC結果存入到指針指向的位置
将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_scan_read()
第一個參數:ADC通道選擇,該參數可以是範圍從0 到15,表示在ADC轉換中,從CH0 掃描到該參數表示的通道
将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_EVENT_CONVERSION_COMPLETE, ADC_EVENT_DATA_OVERWRITE, ADC_EVENT_DATA_COMPARE_VALID,
這次我們需要處理的類型有兩種;
drv_adc_initialize() 函數指定ADC 的中斷回調函數;
adc_enable_xx_interrupt() 使能相應的中斷;
adc_set_compare()設定比較條件:該函數需要4 個參數:
- 通道選擇:設定需要比較的通道;
- 比較門檻值:
- 比較條件:ADC_CMP_GE 表示大于等于門檻值,ADC_CMP_LT表示小于門檻值;
- 比對次數:設定需要聯系比對多少次才會設定标志位,0 表示隻要比對一次機會設定标志位繼而可以産生中斷;
然後再循環中等待轉換結果和比對結果。
本文作者:huanghh
點選檢視原文