AiPi-Eyes-S1是安信可開源團(tuán)隊(duì)專門為Ai-M61-32S設(shè)計(jì)的一款開發(fā)板,支持WiFi6、BLE5.3。所搭載的Ai-M61-32S 模組具有豐富的外設(shè)接口,具體包括 DVP、MJPEG、Dispaly、AudioCodec、USB2.0、SDU、以太網(wǎng) (EMAC)、SD/MMC(SDH)、SPI、UART、I2C、I2S、PWM、GPDAC、GPADC、ACOMP 和 GPIO 等。
AiPi-Eyes-S1集成了SPI屏幕接口,DVP攝像頭接口,外置ES8388音頻編解碼芯片以及預(yù)留TF卡座,并且引出USB接口,可接入U(xiǎn)SB攝像頭。
從零開始學(xué)習(xí)小安派:
1、零基礎(chǔ)開發(fā)小安派-Eyes-S1【入門篇】——初識(shí)小安派-Eyes-S1
2、零基礎(chǔ)開發(fā)小安派-Eyes-S1【入門篇】——安裝VMware與Ubuntu
3、入門篇:零基礎(chǔ)開發(fā)小安派-Eyes-S1——新建工程并燒錄調(diào)試
4、零基礎(chǔ)開發(fā)小安派-Eyes-S1入門篇——Win下SSH連接Linux
5、零基礎(chǔ)開發(fā)小安派-Eyes-S1【入門篇】——Samba共享文件夾
6、零基礎(chǔ)開發(fā)小安派-Eyes-S1【入門篇】——工程文件架構(gòu)
7、零基礎(chǔ)開發(fā)小安派-Eyes-S1【外設(shè)篇】——GPIO 輸入輸出
8、零基礎(chǔ)開發(fā)小安派-Eyes-S1【外設(shè)篇】——GPIO中斷編程
9、零基礎(chǔ)開發(fā)小安派-Eyes-S1【外設(shè)篇】——PWM
10、零基礎(chǔ)開發(fā)小安派-Eyes-S1【外設(shè)篇】——UART
11、零基礎(chǔ)開發(fā)小安派-Eyes-S1【外設(shè)篇】——I2C
ADC 指的是模數(shù)轉(zhuǎn)換器(Analog-to-Digital Converter),它是一種用于將模擬信號(hào)轉(zhuǎn)換為數(shù)字信號(hào)的電子設(shè)備或電路。
模擬信號(hào)是連續(xù)變化的信號(hào),可以取無(wú)限個(gè)可能的值,而數(shù)字信號(hào)則是離散的,只能表示有限個(gè)數(shù)值。ADC 的作用就是將模擬信號(hào)轉(zhuǎn)換為離散的數(shù)字信號(hào),以便數(shù)字電子系統(tǒng)進(jìn)行處理、存儲(chǔ)和傳輸。
ADC 的基本工作原理是通過一系列的采樣和量化過程來(lái)實(shí)現(xiàn)模擬到數(shù)字的轉(zhuǎn)換:
1.采樣(Sampling):ADC 根據(jù)一定的時(shí)間間隔,從模擬信號(hào)中獲取一系列離散的采樣點(diǎn)。采樣率決定了采樣點(diǎn)的密度,較高的采樣率可以更精確地表示原始模擬信號(hào)。
2.量化(Quantization):采樣得到的模擬信號(hào)樣本通常是連續(xù)的,量化則將每個(gè)采樣點(diǎn)映射為一個(gè)特定的數(shù)字值。量化過程將連續(xù)的模擬信號(hào)離散化,并分配給每個(gè)樣本一個(gè)數(shù)字值。
3.編碼(Encoding):編碼將量化后的數(shù)字值表示為二進(jìn)制形式,以便于數(shù)字系統(tǒng)處理。常見的編碼方式包括無(wú)符號(hào)二進(jìn)制、補(bǔ)碼和格雷碼等。
總的來(lái)說,生活中會(huì)有許多“模擬量”,如一段從低音到高音的音頻,在數(shù)字信號(hào)中,不能簡(jiǎn)單的把低音表示 0,高音表示 1,這樣歌曲中間的音頻變化是空的,沒有小數(shù)點(diǎn)這些概念來(lái)顯示他們從 0 到 0.5 到 1 的過程。所以需要有個(gè)模數(shù)轉(zhuǎn)換的過程,稱為 ADC。比如用 12 位精度的 ADC 來(lái)表示這段音頻,低音就 0,高音就是 2^12 次也就是 4096,那么在這段音頻中我們就可以通過 0-4096 的過程來(lái)判斷音頻的高和低,具體到高到有多高,低到有多低,而 ADC 的精度越高,如 16 位,就可達(dá)到 0-65535 的范圍。
一、了解小安派-Eyes-S1 的 ADC
芯片內(nèi)置一個(gè) 12bits 的逐次逼近式模擬數(shù)字轉(zhuǎn)換器 (ADC),支持 12 路外部模擬輸入和若干內(nèi)部模擬信號(hào)選擇。ADC 可以工作在 4 種模式下,轉(zhuǎn)換結(jié)果為 12/14/16bits 左對(duì)齊模式。
ADC 擁有深度為 32 字節(jié)的 FIFO,支持多種中斷,支持 DMA 操作。ADC 除了用于普通模擬信號(hào)測(cè)量外,還可以用于測(cè)量供電電壓,此外 ADC 還可以通過測(cè)量?jī)?nèi)/外部二極管電壓用于溫度檢測(cè)。
具有 12 路外部模擬通道,對(duì)應(yīng)的 GPIO 如下:
此外,還具有 2 路 DAC 內(nèi)部通道,1 路 VBAT/2 通道,1 路 TSEN 通道
adc clock div
對(duì) adc 時(shí)鐘再一次進(jìn)行分頻。分頻后的時(shí)鐘必須小于等于 500K。
ADC CLK = CLK_SOURCE/CLK_DIV/adc_clk_div
#define ADC_CLK_DIV_4 1
#define ADC_CLK_DIV_8 2
#define ADC_CLK_DIV_12 3
#define ADC_CLK_DIV_16 4
#define ADC_CLK_DIV_20 5
#define ADC_CLK_DIV_24 6
#define ADC_CLK_DIV_32 7
adc resolution
adc 位數(shù),可以選擇 12B、14B、16B。其中 14B 和 16B 自帶過采樣處理
#define ADC_RESOLUTION_12B 0
#define ADC_RESOLUTION_14B 2
#define ADC_RESOLUTION_16B 4
adc vref
adc 內(nèi)置參考電壓選擇,可以選擇 2.0 V 或者 3.2V
#define ADC_VREF_3P2V 0
#define ADC_VREF_2P0V 1
二、結(jié)構(gòu)體與 API
struct bflb_adc_config_s
說明:adc 初始化配置結(jié)構(gòu)體。
struct bflb_adc_config_s {
uint8_t clk_div;
uint8_t scan_conv_mode;
uint8_t continuous_conv_mode;
uint8_t differential_mode;
uint8_t resolution;
uint8_t vref;
};
掃描模式:可按照用戶指定通道個(gè)數(shù)和順序逐個(gè)轉(zhuǎn)換,結(jié)果推入 ADC 的 FIFO
連續(xù)轉(zhuǎn)換模式:允許 ADC 連續(xù)不斷地執(zhí)行模數(shù)轉(zhuǎn)換,只需要調(diào)用一次 ADC 啟動(dòng)
差分模式:ADC 支持單端輸入模式和差分模式,選擇單端時(shí)負(fù)極輸入通道選擇 GND
struct bflb_adc_channel_s
說明:配置 adc 通道時(shí)使用。
struct bflb_adc_channel_s {
uint8_t pos_chan;
uint8_t neg_chan;
};
struct bflb_adc_result_s
說明:adc 標(biāo)準(zhǔn)轉(zhuǎn)換結(jié)果
struct bflb_adc_result_s {
int8_t pos_chan;
int8_t neg_chan;
int32_t value;
int32_t millivolt;
};
bflb_adc_init
說明: 初始化 adc。adc 使用之前需要開啟 adc ip 時(shí)鐘、設(shè)置 adc 時(shí)鐘源和分頻值、選擇使用的 gpio 為 analog 模式。
void bflb_adc_init(struct bflb_device_s *dev, const struct bflb_adc_config_s *config);
bflb_adc_deinit
說明: 反初始化 adc。
void bflb_adc_deinit(struct bflb_device_s *dev);
bflb_adc_link_rxdma
說明: adc dma 功能開關(guān)。
void bflb_adc_link_rxdma(struct bflb_device_s *dev, bool enable);
bflb_adc_channel_config
說明: 配置 adc 通道。
int bflb_adc_channel_config(struct bflb_device_s *dev, struct bflb_adc_channel_s *chan, uint8_t channels);
bflb_adc_start_conversion
說明: 啟動(dòng) adc 轉(zhuǎn)換。連續(xù)轉(zhuǎn)換模式下只需要調(diào)用一次。
void bflb_adc_start_conversion(struct bflb_device_s *dev);
bflb_adc_stop_conversion
說明: 停止 adc 轉(zhuǎn)換。
void bflb_adc_stop_conversion(struct bflb_device_s *dev);
bflb_adc_get_count
說明: 獲取 adc 轉(zhuǎn)換個(gè)數(shù)。
uint8_t bflb_adc_get_count(struct bflb_device_s *dev);
bflb_adc_read_raw
說明: 讀取一次 adc 轉(zhuǎn)換值。
uint32_t bflb_adc_read_raw(struct bflb_device_s *dev);
bflb_adc_rxint_mask
說明: adc 轉(zhuǎn)換完成中斷開關(guān)。
void bflb_adc_rxint_mask(struct bflb_device_s *dev, bool mask);
bflb_adc_errint_mask
說明: adc 錯(cuò)誤中斷開關(guān)。
void bflb_adc_errint_mask(struct bflb_device_s *dev, bool mask);
bflb_adc_get_intstatus
說明: adc 中斷標(biāo)志。
uint32_t bflb_adc_get_intstatus(struct bflb_device_s *dev);
返回值如下:
ADC_INTSTS_NEG_SATURATIONADC_INTSTS_NEG_SATURATION
ADC_INTSTS_FIFO_UNDERRUN
ADC_INTSTS_FIFO_OVERRUN
ADC_INTSTS_ADC_READY
bflb_adc_int_clear
說明: 清除 adc 中斷標(biāo)志。
void bflb_adc_int_clear(struct bflb_device_s *dev, uint32_t int_clear);
int_clear 可以填入以下參數(shù):
ADC_INTCLR_NEG_SATURATIONADC_INTCLR_POS_SATURATION
ADC_INTCLR_FIFO_UNDERRUN
ADC_INTCLR_FIFO_OVERRUN
ADC_INTCLR_ADC_READY
bflb_adc_parse_result
說明: 對(duì) adc 轉(zhuǎn)換結(jié)果進(jìn)行解析。
void bflb_adc_parse_result(struct bflb_device_s *dev, uint32_t *buffer, struct bflb_adc_result_s *result, uint16_t count);
bflb_adc_tsen_init
說明: 初始化 adc tsen 模塊。
void bflb_adc_tsen_init(struct bflb_device_s *dev, uint8_t tsen_mod);
bflb_adc_tsen_get_temp
說明: 獲取 adc tsen 模塊采集的溫度。
float bflb_adc_tsen_get_temp(struct bflb_device_s *dev);
bflb_adc_vbat_enable
說明: 開啟 vbat 。
void bflb_adc_vbat_enable(struct bflb_device_s *dev);
bflb_adc_vbat_disable
說明: 關(guān)閉 vbat。
void bflb_adc_vbat_disable(struct bflb_device_s *dev);
三、示例——連續(xù)讀取 IO 的 ADC 值,ADC 轉(zhuǎn)換完成中斷
Main
#include "bflb_adc.h"
#include "bflb_mtimer.h"
#include "board.h"
#include "bflb_gpio.h"
//頭文件
struct bflb_device_s *adc;
//外設(shè)結(jié)構(gòu)體設(shè)置
void My_adc_gpio_init()
{
struct bflb_device_s *gpio;
gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(gpio, GPIO_PIN_0, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
}
//設(shè)置需要AD采集的IO腳,對(duì)應(yīng)的通道和IO要匹配
volatile uint32_t raw_data;
//接收AD值變量
void adc_isr(int irq, void *arg)
{
uint32_t intstatus = bflb_adc_get_intstatus(adc);
if (intstatus & ADC_INTSTS_ADC_READY) {
bflb_adc_int_clear(adc, ADC_INTCLR_ADC_READY);
raw_data= bflb_adc_read_raw(adc);
}
}
//中斷函數(shù),清除中斷標(biāo)志位,將讀取的AD變量賦給raw_data
int main(void)
{
board_init();
My_adc_gpio_init();
adc = bflb_device_get_by_name("adc");
/* adc clock = XCLK / 2 / 32 */
struct bflb_adc_config_s cfg;
cfg.clk_div = ADC_CLK_DIV_32;
cfg.scan_conv_mode = false;
cfg.continuous_conv_mode = false;
cfg.differential_mode = false;
cfg.resolution = ADC_RESOLUTION_16B;
cfg.vref = ADC_VREF_3P2V;
//adc結(jié)構(gòu)體配置
struct bflb_adc_channel_s chan;
chan.pos_chan = ADC_CHANNEL_9;
chan.neg_chan = ADC_CHANNEL_GND;
//通道配置,單端模式下neg選擇GND,pos注意對(duì)應(yīng)IO口的通道
bflb_adc_init(adc, &cfg);
bflb_adc_channel_config(adc, &chan, 1);
bflb_adc_rxint_mask(adc, false);
bflb_irq_attach(adc->irq_num, adc_isr, NULL);
bflb_irq_enable(adc->irq_num);
//中斷使能配置
while (1) {
struct bflb_adc_result_s result;
bflb_adc_start_conversion(adc);
bflb_adc_parse_result(adc, (uint32_t *)&raw_data, &result, 1);
printf("rnpos chan %drnADC Value = %drnCurrent Voltage = %d mvrn", result.pos_chan, result.value, result.millivolt);
bflb_adc_stop_conversion(adc);
bflb_mtimer_delay_ms(1000);
//主函數(shù)讀取AD值并轉(zhuǎn)化為電壓
}
}
四、效果
審核編輯 黃宇
-
芯片
+關(guān)注
關(guān)注
455文章
50714瀏覽量
423131 -
adc
+關(guān)注
關(guān)注
98文章
6495瀏覽量
544457 -
模擬信號(hào)
+關(guān)注
關(guān)注
8文章
1128瀏覽量
52442 -
開源
+關(guān)注
關(guān)注
3文章
3309瀏覽量
42471
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論