歡迎您光臨本站 登入註冊首頁

採用C8051F020 DAC產生任意波形

admin @ 2014-03-25 , reply:0

概述

   信號源是許多電子設備必不可少的部件,可以採用模擬集成電路如8038、單片機控制D/A轉換器或DDS晶元如AD9850等方法實現。對於內部具有D/A轉換器的單片機,採……

    信號源是許多電子設備必不可少的部件,可以採用模擬集成電路如8038、單片機控制D/A轉換器或DDS晶元如AD9850等方法實現。對於內部具有D/A轉換器的單片機,採用其自備的D/A轉換器產生需要的信號是最經濟的方法。內部具有D/A轉換器的單片機種類很多,這裡介紹採用Cygnal公司最新的一款功能強大的內部具有D/A 轉換器的單片機C8051F020產生任意波形的詳細方法。該方法及部分程序也可以用於其他型號的單片機晶元。

1 採用C8051F020 D/A轉換器產生正弦信號的基本原理
    單片機指令不支持正弦函數運算,所以要產生正弦信號只能通過查正弦函數表的方法,再經過D/A轉換成模擬量而輸出正弦波。其波形的頻率可以通過改變定時器的初值,即改變查表輸出的時間來控制。由於本例中採用了C8051F020的一個12位D/A轉換器產生正弦信號,所以平均值為2048幅度為0~4096(212)的64點正弦函數表可以通過如下公式計算:
輸出=sin(2πj/64)×2048+2048       j=0,1,……,63
    計算得到的64項16位二進位數結果,以2個8位二進位數的形式存放在code段(ROM中)具有128項的一維數組SINE_TABLE[128]中,每2項合成一個16位數,取低12位送D/A轉換器進行D/A轉換。
    以下面程序數表中前2項為例:0x08,0x00合併成0x0800,取低12位為800 H,經過DAC0數據轉換電壓為1.20 V(約為滿幅2.40 V的一半)。以產生100 Hz正弦信號為例,設SYSCLK系統振蕩頻率為2MHz,定時器的初值為:
216 - 2MHz/12 × 1/100Hz × 1/64 =65536-26.041666 =65509.958 ≈ 65510
其中216是因為採用的定時器3是16位的。

2 硬體電路
    採用C8051F020 D/A轉換器產生正弦信號的硬體電路圖如圖1所示。
  
    電源部分電路如圖2所示。
 

3 軟體編程
// sinwave.c
#include <c8051io20.h>
//C8051F020特殊功能寄存器聲明
//16位特殊功能寄存器定義
sfr16 DP=0x82; //數據指針
sfr16 TMR3RL=0x92; //定時器3重裝值
sfr16 TMR3=0x94; //定時器3計數器
sfr16 ADC0=0xbe; //ADC0
sfr16 ADC0GT=0xc4; //ADC0窗口1
sfr16 ADC0LT=0xc6; //ADC0窗口2
sfr16 RCAP2=0xca; //定時器2捕捉/重載
sfr16 T2=0xcc; //定時器2
sfr16 RCAP4=0xe4; //定時器4捕捉/重載
sfr16 T4=0xf4; //定時器2
sfr16 DAC0=0xd2; //DAC0
sfr16 DAC1=0xd5; //DAC1
//全局常量
#define SYSCLK 2000000 //系統複位自動使用內部時鐘,為2MHz
sbit LED=P1^6; //定義P1.6名稱為LED,監視系統運行
unsigned char i=0; //聲明無符號字元變數i(初值為0)
void PORT_Init(void); //埠初始化函數原型
void Timer3_Init(int counts); //定時器3初始化函數原型
void Timer3_ISR(void); //定時器3中斷服務函數原型
void Dac0_Init(void); //DAC0初始化函數原型
//正弦函數表,定義具有128項的無符號字元型一維數組
unsigned char code SINE_TABLE[128]={0x08,0x00,0x08,
0xc9,0x09,0x90,0x0a,0x53,0x0b,0x10,0x0b,0xc5,0x0c,
0x72,0x0d,0x13,0x0d,0xa8,0x0e,0x2f,0x0e,0xa7,0xxf,
0xxe,0xxf,0x64,0xxf,0xa8,0xxf,0xd9,0xxf,0xf6,0x0f,0xff,
0x0f,0xf6,0xxf,0xd9,0x0f,0xa8,0x0f,0x64,0x0f,0x0e,0x0e,
0xa7,0x0e,0x2f,0x0d,0xa8,0x0d,0x13,0x0c,0x72,0x0b,
0xc5,0x0b,0x10,0x0a,0x53,0x09,0x90,0x08,0xc9,0x08,
0x00,0x07,0x37,0x06,0x70,0x05,0xad,0x04,0xf0,0x04,
0x3b,0x03,0x8e,0x02,0xed,0x02,0x58,0x01,0xd1,0x01,
0x59,0x00,0xf2,0x00,0x9c,0x00,0x58,0x00,0x27,0x00,
0x0a,0x00,0x00,0xxx,0x0a,0x00,0x27,0x00,0x58,0x00,
0x9c,0x00,0xf2,0x01,0x59,0x01,0xd1,0x02,0x58,0x02,
0xed,0x03,0x8e,0x04,0x3b,0x04,0xf0,0x05,0xad,0x06,
0x70,0x07,0x37,
};
void main(void) //主函數
{
WDTCN=0xde; //關閉看門狗定時器,使其無效
WDTCN =0xad:
PORT_Init(); //調用埠初始化函數
Timer3_Init(65510); //見下面註釋*
Dac0_Init(); //調用DAC0初始化函數
EA=1; //開中斷允許總開關,允許中斷
while(1){ //主函數在此循環等待
}
}
void PORT_Init(void) //埠初始化函數
{
XBR2=0x40; //交叉網路設定為弱上拉並生效
P1 MDOUT |=0x40; //設置P1.6(LED)為推挽輸出方式
}
//定時器3初始化函數
//定義定時器3為自動重裝載方式,以系統時鐘的1/12為時鐘源
void Timer3_Init(int counts) //“counts”為計數重載值。由調用函數傳遞過來
{
TMI13CN=0x00; //定時器3停止,清TF3,
//使用SYCCLK/12為時鐘源
TMR3RL=counts; //設置重載值為“counts”
TMR3=0xffff; //設置立即重載
EIE2 |=0x01; //開啟定時器3中斷允許開關,允許定時器3中斷
TMR3CN |=0x04; //開啟定時器3,使其運行
}
void Dac0_Init(void) //DAC0初始化函數
{
DAC0CN =0x80; //DAC0使能,且為立即更新方式,寫DAC0H寄存器
//將立即啟動DAC0工作,取DAC0H和DAC0L組
//成的16位數據的低12位數據為DAC0的轉換數據
REFOCN |=0x03; //DAC參考電壓設定為使用內部電壓基準
}
void Timer3_ISR(void)interrupt 14 //T3中斷服務函數
{
TMR3CN &= ~(0x80); //清TF3
LED=~LED; //使LED狀態改變,
DAC0L = SINE_TABLE[i*2+1]; //查SINE_TABLE表,將第i*2+1項送給
//DAC0L,i=0,1,2,……63
DAC0H = SINE_TABLE[i*2]; //查SINE_TABLE表,將第i*2項送給
//DAC0H,i=0,1,2,……63
i=i+1;
if(i>=64) i=0; //循環輸出64點
}
    調用定時器3初始化函數,調節其中的計數器初值可以得到不同頻率的正弦信號。這裡以產生100Hz正弦信號為例,計數器初值為65510,具體的計算方法如前文所述。

4 產生任意波形的方法
    若想產生方波、三角波或任意波形,可以簡單地通過修改正弦函數表來得到。

5 結束語
    本文中的程序已經在新華龍公司C8051F020模擬開發板上調試通過,若要產生高精度的信號,必須考慮四捨五入近似、系統時鐘精度及程序響應延時造成的誤差。


[admin via 研發互助社區 ] 採用C8051F020 DAC產生任意波形已經有3364次圍觀

http://cocdig.com/docs/show-post-42160.html