6.1. ADC基礎知識
6.1.1.什么是ADC
模擬數字轉換器即A/D轉換器,或簡稱ADC,通常是指一個將模擬信號轉變為數字信號的電子元件。通常的模數轉換器是將一個輸入電壓信號轉換為一個輸出的數字信號。由于數字信號本身不具有實際意義,僅僅表示一個相對大小。故任何一個模數轉換器都需要一個參考模擬量作為轉換的標準,比較常見的參考標準為最大的可轉換信號大小。而輸出的數字量則表示輸入信號相對于參考信號的大小。
6.1.2. CW32的ADC介紹
CW32F003 內部集成一個 12 位精度、最高 1M SPS 轉換速度的逐次逼近型模數轉換器 (SAR ADC),最多可將 16 路模擬信號轉換為數字信號。現實世界中的絕大多數信號都是模擬量,如光、電、聲、圖像信號等,都要由 ADC 轉換成數字信號,才能由 MCU 進行數字化處理。
主要特性
- 12 位精度
- 可編程轉換速度,最高達 1M SPS
- 16 路輸入轉換通道
- 13 路外部引腳輸入- 內置溫度傳感器- 內置 BGR 1.2V 基準- 1/3 VDD 電源電壓
- 4 路參考電壓源(Vref)
- VDD 電源電壓- ExRef(PB04)引腳電壓- 內置 1.5V 參考電壓- 內置 2.5V 參考電壓
- 采樣電壓輸入范圍:0 ~ Vref
- 多種轉換模式,全部支持轉換累加功能
- 單次轉換- 多次轉換
- 連續轉換
- 序列掃描轉換
- 序列斷續轉換
- 支持單通道、序列通道兩種通道選擇,最大同時支持 4 個序列
- 支持輸入通道電壓閾值監測
- 內置信號跟隨器,可轉換高阻抗輸入信號
- 支持片內外設自動觸發 ADC 轉換
6.1.3. ADC基本參數
分辨率:表示ADC轉換器的輸出精度,通常以位數(bit)表示,比如8位、10位、12位等,位數越高,精度越高。
采樣率:表示ADC對模擬輸入信號進行采樣的速率,通常以每秒采樣次數(samples per second,SPS)表示,也稱為轉換速率,表示ADC能夠進行多少次模擬到數字的轉換。
采樣范圍:指ADC可以采集到的模擬輸入信號的電壓范圍,范圍見下:
0 ≤ ADC ≤ Vref
Vref 為參考電壓,CW32F003有四路電壓參考源見上文。
6.1.4. 基本原理
CW32F003采用的是逐次逼近型的12位ADC,逐次逼近型ADC是一種常見的ADC工作原理,它的思想是通過比較模擬信號與參考電壓之間的大小關系來逐步逼近輸入信號的數字表示。在逐次逼近型ADC中,輸入信號和參考電壓被加入一個差分放大器中,產生一個差分電壓。然后,這個差分電壓被輸入到一個逐步逼近的數字量化器中,該量化器以逐步遞減的方式將其與一系列參考電壓進行比較。具體來說,在每個逼近階段,量化器將輸入信號與一個中間電壓點進行比較,將該電壓點上方或下方的參考電壓作為下一個逼近階段的參考電壓。這個過程一直持續到量化器逼近到最終的數字輸出值為止。
圖6-1 電壓采樣電路原理圖
如果使用1.5V作為參考電壓,根據R8和R7的阻值配比可以得到最高采樣電壓為:
1.5 / 10 * (220 + 10)= 34.5V
電流采樣的電路原理圖見圖6-2,對電流采樣本質上是對檢流電阻的電壓進行采樣。
圖6-2 電流采樣原理圖
6.2. ADC優點
1.數字信號具有良好的抗干擾性。數字信號是由一系列離散的數字表示,因此可以抵抗模擬信號受到的各種干擾,如噪聲、漂移等。
2.方便數字信號的存儲、處理和傳輸。由于數字信號是離散的,因此它們可以輕松存儲在計算機內存或其他數字設備中,方便進行處理和傳輸。
3.具有可編程性。現代的ADC出現了很多可編程的功能,例如可編程增益、采樣率和濾波器等,可以根據不同的應用場景進行優化。
4.適用性廣泛。ADC被廣泛應用于工業、通信、醫療、電子測量、音頻、視頻等領域,可轉換各種不同類型的模擬信號,包括電壓、電流、聲音、光信號等。
6.3. ADC應用
ADC的應用非常廣泛。例如,我們可以用ADC將傳感器的模擬信號轉換為數字信號,然后通過計算機進行處理和分析;ADC在音頻處理中也起著重要的作用,將模擬聲音信號轉換為數字信號,并接下來進行數字信號處理;無線電通信中的信號調制也需要使用ADC等。總的來說,ADC在現代電子工程中非常重要,是數字信號處理和控制技術的關鍵部分。
6.4. ADC采樣顯示
在下面我們對CW32F003的ADC通道進行配置,輸入5V電壓給電壓表,CW32將采樣得到的值輸入數碼管顯示,對ADC通道的配置代碼如下;
#include "ADC.h"
uint16_t Volt_Buffer; //存放ADC采樣值
void ADC_init(void)
{
ADC_InitTypeDef ADC_InitStructure; //ADC配置結構體
ADC_SerialChTypeDef ADC_SerialChStructure; //ADC序列通道結構體
GPIO_InitTypeDef GPIO_Init_Struct;
__RCC_GPIOB_CLK_ENABLE(); //打開ADC對應引腳時鐘
__RCC_ADC_CLK_ENABLE(); // 打開ADC時鐘
GPIO_Init_Struct.IT = GPIO_IT_NONE;
GPIO_Init_Struct.Mode = GPIO_MODE_ANALOG;//將GPIO的模式配置成模擬功能
GPIO_Init_Struct.Pins = GPIO_PIN_1; // PB01是電壓采集引腳
GPIO_Init(CW_GPIOB, &GPIO_Init_Struct);
PB01_ANALOG_ENABLE(); //使能模擬引腳
ADC_StructInit(&ADC_InitStructure); // ADC默認值初始化
ADC_InitStructure.ADC_ClkDiv = ADC_Clk_Div4; //ADC工作時鐘配置 PCLK/4 = 6/4 = 1.5Mhz
/*信號電壓較低時,可以降低參考電壓來提高分辨率。改變參考電壓后,同樣二進制表示的電壓值就會不一樣,
最大的二進制(全1)表示的就是你的參考電壓,在計算實際電壓時,就需要將參考電壓考慮進去。*/
ADC_InitStructure.ADC_VrefSel = ADC_Vref_BGR1p5;//參考電壓設置為1.5V
//由于電壓信號為慢速信號,ADC采樣時間為十個ADC采樣周期以確保準確
ADC_InitStructure.ADC_SampleTime = ADC_SampTime10Clk;
//Sqr為序列配置寄存器,這里只用到了序列0的通道,所以配置成0表示只轉換Sqr0序列
ADC_SerialChStructure.ADC_SqrEns = ADC_SqrEns0;
ADC_SerialChStructure.ADC_Sqr0Chmux = ADC_SqrCh9;//配置ADC序列,PB01是ADC的第9通道
ADC_SerialChStructure.ADC_InitStruct = ADC_InitStructure; //ADC初始化
ADC_SerialChContinuousModeCfg(&ADC_SerialChStructure); //ADC序列連續轉換模式配置
ADC_ClearITPendingAll(); //清除ADC所有中斷狀態
ADC_Enable(); // ADC使能
ADC_SoftwareStartConvCmd(ENABLE); //ADC轉換軟件啟動命令
}
void Get_ADC_Value(void) //取得ADC采樣的值傳給全局變量Volt_Buffer
{
ADC_GetSqr0Result(&Volt_Buffer);
}
在主函數中初始化ADC后在BTIM1的中斷服務程序中調用 Get_ADC_Value 得到ADC采樣的值,再在主函數的 while 循環中調用數碼管顯示函數 Display 將ADC采樣值顯示到數碼管上。下圖為數字電壓電流表接入5V電壓時的采樣顯示圖。可以看到接入5V時ADC采樣得到669,我們可以計算:
(669/4096)* [(1.5/10)*(200+10)] = 5.145 V
其中4096代表CW32的ADC采樣精度12位為2^12=4096,由于我們的測試樣品中220KΩ的電阻被替換成了200KΩ,所以計算公式如上,與萬用表測量數值相符。(各位學員最終收到的版本是220KΩ的電阻)
圖6-3 ADC采樣顯示
圖6-4 萬用表測量5V
6.5. ADC采樣計算
根據上文,ADC所采樣的值雖然準確地顯示在數碼管上,但采樣值仍需要轉換成標準值。計算思路與上述公式類似,只是顯示到數碼管上需要將數值擴大100倍。因此采樣計算的思路為:將采樣得到的值(比如在5V輸入的情況下ADC采樣得到668)用上述計算公式計算得到的結果后乘以100:
(668/4096)* [(1.5/10)*(200+10)] * 100 = 513.7 V
由于變量為整形,最終輸入給顯示函數 Display 的值為513,在 Display 函數里對輸入的值進行判定,如果輸入值大于1000,則數碼管只能顯示xx.x V,所以我們只取輸入值的千百十位;如果輸入值小于1000,比如現在輸入值為513,則數碼管可顯示x.xx V,分別將513的百十個位存入 Seg_Reg 數組中。
最終需要添加一個 Cal_Buffer 變量來存儲 Volt_Buffer 的值、一個電壓計算函數,再修改 Display 函數見下文:
uint16_t Cal_Buffer; //存儲 Volt_Buffer 的值
#define ADC_REF_VALUE (1500) //擴大1000倍 1.5 * 1000 = 1500
#define R2 (200) //單位:KΩ
#define R1 (10)
void Volt_Cal(void) //將ADC采樣值轉化為標準值
{
Cal_Buffer = Volt_Buffer; //存儲中斷服務程序中取得的ADC采樣值
Cal_Buffer = (Cal_Buffer * ADC_REF_VALUE > > 12) * (R2 + R1)/R1;//計算得到的值為標準值的1000倍
if(Cal_Buffer % 10 >= 5) // 四舍五入
{
Cal_Buffer = Cal_Buffer / 10 + 1;
}
else
{
Cal_Buffer = Cal_Buffer / 10; //此時的值為標準值的100倍
}
}
在while循環中調用數碼管顯示函數Display之前先調用Volt_Cal函數。
int main()
{
RCC_Configuration();
Seg_Init();
Btim1_Init();
ADC_init();
while(1)
{
Volt_Cal();
Display(Cal_Buffer);
}
}
Display函數的更新如下:
void Display(uint32_t value)
{
uint8_t Thousands; //千位
uint8_t Hundreds; //百位
uint8_t Tens; //十位
uint8_t Units; //個位
Thousands = value / 1000; //如果輸入值大于1000,只取輸入值的千百十位
if(Thousands > 0) //大于0則說明輸入值的千位有值
{
Units = value % 10;
value = Units > 5 ? (value + 10) : value; // 根據后一位四舍五入
Thousands = value / 1000 % 10; //只取千百十位
Hundreds = value / 100 % 10;
Tens = value / 10 % 10;
// 顯示xx.x伏
Seg_Reg[0] = Thousands;
Seg_Reg[1] = Hundreds + 10; // 加dp顯示
Seg_Reg[2] = Tens;
}
else //如果輸入值的千位沒有值,則取百十個位
{
Units = value % 10;
Tens = value / 10 % 10;
Hundreds = value / 100 % 10;
// 顯示x.xx伏
Seg_Reg[0] = Hundreds + 10; // 加dp顯示
Seg_Reg[1] = Tens;
Seg_Reg[2] = Units;
}
}
最終顯示效果如下圖(輸入接5V):
圖6-5 采樣計算后顯示值
此時萬用表測得電壓如下:
圖6-6 萬用表測量值(5V)
審核編輯 黃宇
-
差分放大器
+關注
關注
8文章
449瀏覽量
52160 -
ADC
+關注
關注
0文章
110瀏覽量
16845 -
電壓電流表
+關注
關注
0文章
25瀏覽量
2074 -
CW32
+關注
關注
1文章
203瀏覽量
626
發布評論請先 登錄
相關推薦
評論