前言
今天介紹下STC8A8K64S4A12系列單片機DAC數模轉換原理及RC積分電路原理,掌握掌握STC8A8K64S4A12系列單片機實現DAC功能的硬件和軟件設計。
一、硬件設計
1.DAC概念介紹
DAC
(全稱是DigitaltoAnalogConvertor)數模轉換器是一種將數字信號轉換為模擬信號(以電流、電壓或電荷的形式)的設備,在很多數字系統(tǒng)中(例如計算機、單片機),信號以數字方式(0或者1)存儲和傳輸,而數模轉換器DAC可以將這樣的信號轉換為模擬信號,從而使得他們能夠被外界(人或其他非數字系統(tǒng))識別。
數模轉換器DAC的常見用法是在音樂播放器中將數字形式存儲的音頻信號輸出為模擬的聲音。有的電視機的顯像也有類似的過程。數模轉換器DAC有時會降低原有模擬信號的精度,因此轉換細節(jié)常常需要篩選,使得誤差可以忽略。
DAC有幾個常見且重要的性能參數,如分辨率、線性度、建立時間、絕對精度和相對精度等。這里簡單說下分辨率和線性度的概念。DAC的分辨率是輸入數字量的最低有效位(LSB)發(fā)生變化時,所對應的輸出模擬量(電壓或電流)的變化量。其反映了輸出模擬量的最小變化值。DAC的線性度(也稱非線性誤差)是實際轉換特性曲線與理想直線特性之間的最大偏差。常以相對于滿量程的百分數表示。
現市場上越來越多的MCU芯片內部會集成DAC外設,也有專用DAC芯片,包括一些音頻芯片都屬于DAC芯片,比如PCM5102A等。說到單片機DAC外設,一定會給出這個DAC外設是多少位的,比如單片機片內有16位DAC,就意味著數字信號的范圍是065535,假設該DAC輸出是03.3V的電壓型模擬信號,那DAC轉換可分辨的最小電壓(分辨率)就是3300mV/65535=0.05mV,這也就意味DAC數字信號輸出有1bit的抖動,那么實際輸出的模擬信號就有0.05mV的偏差。
DAC核心部分是由R-2R電阻網絡(也稱倒T型電阻網絡)、模擬開關和運算放大器所組成。這里之所以說核心部分是因為有些專用DAC芯片,比如音頻芯片可能還有I2S接口相關的外圍電路等。下面簡單介紹下倒T型電阻網絡。解析這個原理圖時我們必須知道戴維南等效電源定理,然后從右側向左去等效可分析出I7是I的1/2,I6是I的1/4,I5是I的1/8,I4是I的1/16,I3是I的1/32,I2是I的1/64,I1是I的1/128,I0是I的1/256,如此每一位都發(fā)揮了有效的位權,輸出電壓有256種變化,該T型電阻網絡等效輸出表達式為D0Vref/256+D1Vref/128+D2Vref/64+D3Vref/32+D4Vref/16+D5Vref/8+D6Vref/4+D7Vref/2。
圖1:T型電阻網絡示意圖
☆注:本T型電阻網絡是8位DAC舉例,若是10位、12位、16位依次按此方法增加R電阻和2R電阻電路部分。
2.開發(fā)板DAC硬件電路介紹
STC8A8K64S4A12系列單片機內部沒有集成DAC外設,所以STC8A8K64S4A12開發(fā)板實現DAC轉換是基于將高速PWM信號通過RC電路整合成比較平緩的電壓信號作為模擬輸出,而改變高速PWM信號的占空比可改變輸出電平信號的幅值。為了達到比較理想的電壓信號輸出,P7.0口輸出的PWM信號經2級RC電路整合,如下圖。
圖2:開發(fā)板DAC轉換電路
☆注:開發(fā)板J27端子需使用短路帽短接P06||DAC_O和P70||DAC_I,并且將J27端子的P06||ADC和P70||DHT11短路帽去掉。
DAC電路占用的單片機的引腳如下表:
表1:DAC電路引腳分配
注:非獨立GPIO表示開發(fā)板有其他的電路使用這個GPIO。
RC積分電路簡介
由電阻R和電容C構成的電路稱為阻容電路,簡稱RC電路。RC電路是電子電路中非常常見的一種電路,但RC電路的種類和變化很多,首先我們介紹下RC積分電路。
在RC電路分析中,有時要用到時間常數這一概念。時間常數為電容量與電阻值的乘積。在電容量大小不變時,電阻值決定了時間常數的大小。電阻值不變時,電容量的大小決定了時間常數的大小。輸入信號加在電阻R1上,輸出信號取自電容C1。輸入信號是矩形脈沖,在積分電路中,要求RC電路中的時間常數遠大于脈沖寬度。
圖3:RC積分電路分析示意圖
☆注:RC積分電路的作用是:消減變化量,突出不變量。故RC積分電路可將矩形脈沖波轉換為鋸齒波或三角波,還可將鋸齒波轉換為拋物波。
RC積分電路的條件是時間常數遠大于輸入信號的脈沖寬度,STC8A8K64S4A12開發(fā)板的RC電路中,R1取值3.3K、C1取值100nF,可計算時間常數為R1C1=3.3KΩ10010-9F=3.310-4。如果時間常數遠大于輸入信號的脈沖周期,則也一定滿足RC積分電路的條件。換句話說如果時間常數的倒數遠小于輸入信號的頻率,則也一定滿足RC積分電路的條件。時間常數的倒數可計算出為3.3*10-4的倒數約為3030,所以輸入信號的頻率只要遠大于3.03KHZ即可滿足積分電路的條件(一般按照10倍來作為基本條件)。
STC8A8K64S4A12開發(fā)板控制P7.0口輸出PWM信號的頻率約是43.2KHZ(具體不詳述),該頻率滿足RC積分電路的條件,所以可將P7.0口輸出的PWM信號整合成比較平緩的電壓信號(可使用示波器輔助測量之)。又因為單片機控制P7.0口輸出的PWM信號頻率不變、占空比變化,所以最后整合出的電壓信號的幅值會不同,從而實現輸出不同模擬量的目的。
RC微分電路簡介
RC微分電路和RC積分電路在電路形式上相近,RC微分電路輸出電壓取自電阻,而且RC時間常數與積分電路不同。RC微分電路中,要求RC時間常數遠小于輸入信號的脈沖寬度。如下圖所示。
圖4:RC微分電路分析示意圖
注:RC微分電路的作用是:消減不變量,突出變化量。故RC微分電路可把矩形波轉換為尖脈沖波,電路的輸出波形只反映輸入波形的突變,即只有輸入波形發(fā)生突變的瞬間才有輸出。而對恒定部分則沒有輸出。
除了上面描述的RC微分電路和RC積分電路,RC電路還有很多不同應用,比如RC耦合電路、RC脈沖分壓器以及RC濾波電路等。
二、軟件設計
1.DAC檢測 - 串口調試助手實驗
1.1.工程需要用到的c文件
本例需要用到的c文件如下表所示,工程需要添加下表中的c文件。
表2:實驗需要用到的c文件
1.2.頭文件引用和路徑設置
需要引用的頭文件
#include "delay.h"
#include "uart.h"
#include "adc.h"
#include "pca.h"
需要包含的頭文件路徑
本例需要包含的頭文件路徑如下表:
表3:頭文件包含路徑
MDK中點擊魔術棒,打開工程配置窗口,按照下圖所示添加頭文件包含路徑。
圖5:添加頭文件包含路徑
1.3.編寫代碼
首先,在adc.c文件中編寫操作ADC外設會用到的函數,如下表所示。
表4:ADC操作函數匯集
關于上面2個ADC基本操作函數,下面詳細給出代碼。
程序清單:ADC口初始化函數
/**************************************************************************
功能描述:ADC口初始化
入口參數:無
返回值:無
*************************************************************************/
void ADC_config(void)
{
ADC_CONTR|=0x80; //開AD轉換電源
delay_ms(10); //適當延時等待AD轉換供電穩(wěn)定
ADC_CONTR|=0x0E; //選擇P0.6作為模擬功能AD使用
ADC_CONTR&=0xFE; //選擇P0.6作為模擬功能AD使用
ADCCFG&=0xFC; //AD轉換速度為416個時鐘數轉換一次
ADCCFG|=0x0C; //AD轉換速度為416個時鐘數轉換一次
ADC_CONTR&=0xDF; //清AD轉換完成標志
EADC=0; //禁止ADC轉換中斷
ADCCFG|=0x20; //ADC轉換結果ADC_RES存高4位,ADC_RESL存低8位
ADC_CONTR|=0x40; //啟動AD轉換,ADC_START=1
}
程序清單:讀取ADC轉換原始值函數
/**************************************
功能描述:ADC口檢測AD轉換值函數
入口參數:無
返回值:ADC 12位數據
***************************************/
uint16 Get_ADC12bitResult(void)
{
uint16 AD_Dat=0;
ADC_CONTR&=0xDF; // 將ADC_FLAG清0
ADC_CONTR&=0xBF; //關閉AD轉換,ADC_START=0
//12位AD結果的高4位放ADC_RES的低4位,低8位在ADC_RESL
AD_Dat = ADC_RES; //將ADC_RES低4位移到應在的第9位至第12位
AD_Dat <= 8;
AD_Dat|= ADC_RESL; //將ADC_RESL的8位移到應在的低8位
ADC_CONTR|=0x40; //啟動AD轉換,ADC_START=1
return AD_Dat;
}
程序清單:PCA初始化函數
/**************************************************************************
功能描述:PCA初始化
入口參數:無
返回值:無
*************************************************************************/
void PCAInit(void)
{
P_SW1 &= 0xEF; //選擇PCA模塊0為引腳P7.0,選擇PCA模塊1為引腳P7.1
P_SW1 |= 0x20; //選擇PCA模塊2為引腳P7.2,選擇PCA模塊3為引腳P7.3
CCON = 0x00; //CF、CR、CCF1、CCF0位均清零
CMOD &= 0x7F; //CIDL位置0,空閑模式下PCA計數器仍然工作
CMOD &= 0xF1; //CP2、CP1、CP0設置為100,PCA時鐘源選擇為系統(tǒng)時鐘
CMOD |= 0x08; //CP2、CP1、CP0設置為100,PCA時鐘源選擇為系統(tǒng)時鐘
CMOD &= 0xFE; //ECF位置0,禁止寄存器CCON中CF位中斷(禁止PCA計時中斷)
CL = 0x00; //PCA計數器賦初值
CH = 0x00; //PCA計數器賦初值
//PCA模塊0初始化部分
CCAPM0 |= 0x40; //ECOM0位置1,允許比較器功能
CCAPM0 &= 0xDF; //CAPP0位置0,禁止上升沿捕獲
CCAPM0 &= 0xEF; //CAPN0位置0,禁止下降沿捕獲
CCAPM0 &= 0xF7; //MAT0位置0,禁止匹配控制位
CCAPM0 &= 0xFB; //TOG0位置0,禁止翻轉控制位
CCAPM0 |= 0x02; //PWM0位置1,開啟PWM模式
CCAPM0 &= 0xFE; //ECCF0位置0,禁止CCF0中斷
PCA_PWM0 &= 0x3F; //PCA模塊0工作于8位PWM功能
PCA_PWM0 &= 0xFC; //EPC0H位和EPC0L位置0
CCAP0L = 0x00; //PCA比較值寄存器賦初值
CR = 1; //啟動PCA計數器陣列計數
}
最后,在主函數中對串口1進行初始化,主循環(huán)中每200ms通過串口1發(fā)送讀取的端口P06的ADC原始值信息。
代碼清單:主函數
int main()
{
uint16 TempData=0;
P3M1 &= 0xFE; P3M0 &= 0xFE; //設置P3.0為準雙向口
P3M1 &= 0xFD; P3M0 |= 0x02; //設置P3.1為推挽輸出
PCAInit(); //PCA初始化
ADC_config(); //ADC初始化
Uart1_Init(); //串口1初始化
EA = 1; //使能總中斷
delay_ms(10); //初始化后延時
while (1)
{
TempData++;
CCAP0H = (uint8)(256 - TempData); //P7.0引腳輸出頻率不變但占空比不斷變化的脈沖信號
if(TempData>138) //占空比達到很大時重新設定占空比
TempData=1;
delay_ms(20);
printf("\r\n ADC_P06端口原始值: %d\r\n",Get_ADC12bitResult()); //串口打印上傳的采集的原始值
delay_ms(200);
}
}
1.4.硬件連接
圖6:開發(fā)板連接圖
總結
以上是今天要講的內容,希望對大家有幫助,如果有啥不明白的,歡迎討論哦!
-
單片機
+關注
關注
6023文章
44376瀏覽量
628385 -
dac
+關注
關注
43文章
2226瀏覽量
190439 -
轉換電路
+關注
關注
2文章
205瀏覽量
30416 -
數模轉換器
+關注
關注
13文章
966瀏覽量
82922 -
積分電路
+關注
關注
11文章
84瀏覽量
36776
發(fā)布評論請先 登錄
相關推薦
評論