以下是補充(能想到的范圍有限有沒想到的還請諒解)
DA工作原理
基于PCF8591芯片
DA是什么?
n DA指數(shù)模轉換(Digital to Analog),顧名思義,就是把數(shù)字信號轉換成模擬信號。與DA
相對應,AD是把模擬信號轉換為數(shù)字信號,便于計算機等數(shù)字控制器處理。
DA有什么作用?
n 1、將數(shù)字量轉換成模擬量,以便操縱控制對象。n 2、用數(shù)字化來控制各種對象。
n 3、可以在單片機中輸入數(shù)字,來控制輸出壓力計力的大小。
串行DA芯片與單片機連接方法(兩種):
HL-1連接方法
HJ-c52連接方法
D/A轉換器的主要性能指標
1、分辨率
分辨率是指輸入數(shù)字量的最低有效位(LSB)發(fā)生變化時,所對應的輸出模擬量(電壓或電流)的變化量。它反映了
輸出模擬量的最小變化值。
分辨率與輸入數(shù)字量的位數(shù)有確定的關系,可以表示成FS /2的n方 。FS表示滿量程輸入值,n為二進制位數(shù)。對于5V
的滿量程,采用8位的DAC時,分辨率為5V/256=19.5mV;當采用12位的DAC時,分辨率則為5V/4096=1.22mV。顯然,
位數(shù)越多分辨率就越高。
2、線性度
線性度(也稱非線性誤差)是實際轉換特性曲線與理想直線特性之間的最大偏差。常以相對于滿量程的百分數(shù)
表示。如±1%是指實際輸出值與理論值之差在滿刻度的±1%以內。
3、絕對精度和相對精度
絕對精度(簡稱精度)是指在整個刻度范圍內,任一輸入數(shù)碼所對應的模擬量實際輸出值與理論值之
間的最大誤差。絕對精度是由DAC的增益誤差(當輸入數(shù)碼為全1時,實際輸出值與理想輸出值之差)、
零點誤差(數(shù)碼輸入為全0時,DAC的非零輸出值)、非線性誤差和噪聲等引起的。絕對精度(即
最大誤差)應小于1個LSB。 相對精度與絕對精度表示同一含義,用最大誤差相對于滿刻度的百分比表示。
4、建立時間
建立時間是指輸入的數(shù)字量發(fā)生滿刻度變化時,輸出模擬信號達到滿刻度值的±1/2LSB所需的時間。
是描述D/A轉換速率的一個動態(tài)指標。電流輸出型DAC的建立時間短。電壓輸出型DAC的
建立時間主要決定于運算放大器的響應時間。根據(jù)建立時間的長短,可以將DAC分成超高速(<1μ
S)、高速(10~1μS)、中速(100~10μS)、低速(≥100μS)幾檔。
應當注意,精度和分辨率具有一定的聯(lián)系,但概念不同。DAC的位數(shù)多時,分辨率會提高,對
應于影響精度的量化誤差會減小。但其它誤差(如溫度漂移、線性不良等)的影響仍會使DAC
的精度變差。
附帶三個說明
一,HL-1的AD/DA模塊和DS1302時鐘模塊原理圖
二,HJ-C52的AD/DA原理圖
三,一個AD/DA單獨模塊(PCF8951)的說明
AD/DA獨立模塊接線說明
1. 可以自己用杜邦線接到你自己的最小系統(tǒng)上,也可以接到慧凈HJ-C51智能小車核心板上,接線方法參考源理圖接,VCC接學
習板上的VCC,GND接學習板上的GND 其他的信號輸入可以自己定義。
AD/DA獨立模塊簡單說明
1. 本板采用全新AD/DA芯片PCF8591,設計合理,性能非常穩(wěn)定,提供原理圖及配套示例代碼。
模塊說明:
2. 該模塊A/D輸入和D/A輸出定義,模塊有4路A/D輸入,1路D/A輸出:
3. A/D輸入通道0:連接外部測試;
4.A/D輸入通道1:一路電位器可測變阻器分壓;連接外部測試;
5. A/D輸入通道2:一路熱敏電阻可測溫度;連接外部測試;
6. A/D輸入通道3:一路光敏電阻可測光強;連接外部測試;
7. D/A輸出通道0:一路LED通過亮度顯示。
------------------------------------------------(因為有些東西電腦沒備份..所以找不到了)-----------------------------------------------------
- /*-----------------------------------------------
- 內容:scl=P3^0;//IIC的時鐘線 sda=P3^1;//IIC的數(shù)據(jù)線分別接J26-7和J26-6上。
- J23-5接J26-5上
- LED會逐漸變亮后有逐漸變暗
- ------------------------------------------------*/
- #include<reg51.h>
- #include<intrins.h>
- #define uc unsigned char
- #define ui unsigned int
- sbit scl=P3^0;//IIC的時鐘線
- sbit sda=P3^1;//IIC的數(shù)據(jù)線
- uc code shuju[]={
- 0x0f,0x1e,0x2d,0x3c,0x4b,0x5a,0x69,0x78,0x87,0x96,0xa5,0xb4,0xc3,0xd2,0xe1,0xf0,0xff,//讓電壓逐漸升高的數(shù)據(jù)
- 0xff,0xf0,0xe1,0xd2,0xc3,0xb4,0xa5,0x96,0x87,0x78,0x69,0x5a,0x4b,0x3c,0x2d,0x1e,0x0f,//讓電壓逐漸下降的數(shù)據(jù)
- };
- void delayus(void)
- {
- ;;
- }
- void delay(ui m)
- {
- ui i,j;
- for(i=0;i<120;i++)
- for(j=0;j<m;j++);
- }
- void init(void)//IIC的初始化
- {
- scl=1;
- delayus();
- sda=1;
- delayus();
- }
- void start(void)//IIC的起始信號
- {
- scl=1;
- delayus();
- sda=1;
- delayus();
- sda=0;
- delayus();
- }
- void stop(void)//IIC的停止信號
- {
- sda=0;
- delayus();
- scl=1;
- delayus();
- sda=1;
- delayus();
- }
- void ack(void)//IIC的應答信號
- {
- uc i;
- scl=1;
- delayus();
- while((sda==1)&(i<255))i++;
- scl=0;
- delayus();
- }
- void write_byte(uc date)//向IIC寫一個字節(jié)的數(shù)據(jù)
- {
- uc i,temp;
- temp=date;
- for(i=0;i<8;i++)
- {
- temp=temp<<1;
- scl=0;
- delayus();
- sda=CY;
- delayus();
- scl=1;
- delayus();
- }
- scl=0;
- delayus();
- sda=1;
- delayus();
- }
- void write(uc add,uc sda,uc date)
- {
- start();
- write_byte(add);//0x90表示器件地址為000的寫操作
- ack();
- write_byte(sda);//0x40表示四路單數(shù)入00通道無增益的器件控制指令
- ack();
- write_byte(date);//表示DA數(shù)據(jù)
- ack();
- stop();
- }
- void main(void)
- { uc i;
- init();//I2C總線初始化
- while(1)
- {
- for(i=0;i<34;i++)
- {
- write(0x90,0x40,shuju[ i]);//向PCF8591里寫入數(shù)據(jù)(即電壓量的數(shù)據(jù));
- delay(100);
- }
- }
- }
復制代碼 以上是一個DA轉換例子[我也是也是補充的(上傳不了附件....就只能直接上碼了 )
附帶兩種使LED輸出顯示DA
1,HJ-52
/*-----------------------------------------------
名稱:IIC協(xié)議 PCF8591ADDA轉換
內容:此程序通過IIC協(xié)議對DAAD芯片操作, 并輸出模擬量,用LED亮度漸變指示
------------------------------------------------*/
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
#include <intrins.h> //包含NOP空指令函數(shù)_nop_();
#define AddWr 0x90 //寫數(shù)據(jù)地址
#define AddRd 0x91 //讀數(shù)據(jù)地址
sbit Sda=P1^2; //定義總線連接端口
sbit Scl=P1^7;
sbit dula=P2^0;
sbit wela=P2^1;
bit ADFlag; //定義AD采樣標志位
unsigned char code Datatab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//7段數(shù)共陰碼管段碼表
data unsigned char Display[8];//定義臨時存放數(shù)碼管數(shù)值
/*------------------------------------------------
延時程序
------------------------------------------------*/
void mDelay(unsigned char j)
{
unsigned int i;
for(;j>0;j--)
{
for(i=0;i<125;i++)
{;}
}
}
/*------------------------------------------------
初始化定時器1
------------------------------------------------*/
void Init_Timer1(void)
{
TMOD |= 0x10;
TH1=0xff; /* Init value */
TL1=0x00;
//PT1=1; /* 優(yōu)先級 */
EA=1; /* interupt enable */
ET1=1; /* enable timer1 interrupt */
TR1=1;
}
/*------------------------------------------------
啟動IIC總線
------------------------------------------------*/
void Start(void)
{
Sda=1;
_nop_();
Scl=1;
_nop_();
Sda=0;
_nop_();
Scl=0;
}
/*------------------------------------------------
停止IIC總線
------------------------------------------------*/
void Stop(void)
{
Sda=0;
_nop_();
Scl=1;
_nop_();
Sda=1;
_nop_();
Scl=0;
}
/*------------------------------------------------
應答IIC總線
------------------------------------------------*/
void Ack(void)
{
Sda=0;
_nop_();
Scl=1;
_nop_();
Scl=0;
_nop_();
}
/*------------------------------------------------
非應答IIC總線
------------------------------------------------*/
void NoAck(void)
{
Sda=1;
_nop_();
Scl=1;
_nop_();
Scl=0;
_nop_();
}
/*------------------------------------------------
發(fā)送一個字節(jié)
------------------------------------------------*/
void Send(unsigned char Data)
{
unsigned char BitCounter=8;
unsigned char temp;
do
{
temp=Data;
Scl=0;
_nop_();
if((temp&0x80)==0x80)
Sda=1;
else
Sda=0;
Scl=1;
temp=Data<<1;
Data=temp;
BitCounter--;
}
while(BitCounter);
Scl=0;
}
/*------------------------------------------------
讀入一個字節(jié)并返回
------------------------------------------------*/
unsigned char Read(void)
{
unsigned char temp=0;
unsigned char temp1=0;
unsigned char BitCounter=8;
Sda=1;
do
{
Scl=0;
_nop_();
Scl=1;
_nop_();
if(Sda)
temp=temp|0x01;
else
temp=temp&0xfe;
if(BitCounter-1)
{
temp1=temp<<1;
temp=temp1;
}
BitCounter--;
}
while(BitCounter);
return(temp);
}
/*------------------------------------------------
寫入DA數(shù)模轉換值
------------------------------------------------*/
void DAC(unsigned char Data)
{
Start();
Send(AddWr); //寫入芯片地址
Ack();
Send(0x40); //寫入控制位,使能DAC輸出
Ack();
Send(Data); //寫數(shù)據(jù)
Ack();
Stop();
}
/*------------------------------------------------
讀取AD模數(shù)轉換的值,有返回值
------------------------------------------------*/
unsigned char ReadADC(unsigned char Chl)
{
unsigned char Data;
Start(); //寫入芯片地址
Send(AddWr);
Ack();
Send(0x40|Chl);//寫入選擇的通道,本程序只用單端輸入,差分部分需要自行添加
//Chl的值分別為0、1、2、3,分別代表1-4通道
Ack();
Start();
Send(AddRd); //讀入地址
Ack();
Data=Read(); //讀數(shù)據(jù)
Scl=0;
NoAck();
Stop();
return Data; //返回值
}
void cmg(void)//數(shù)碼管鎖存函數(shù) 關時鐘DS1302
{
dula=1;
P0=0x00;
dula=0;
wela=1;
P0=0x00;
wela=0;
}
/*------------------------------------------------
主程序
------------------------------------------------*/
void main()
{
unsigned char num; //DA數(shù)模輸出變量
unsigned char ADtemp; //定義中間變量
Init_Timer1();
cmg();//關數(shù)碼管函數(shù)
while(1)
{
DAC(num); //DA輸出,可以用LED模擬電壓變化
num++; //累加,到256后溢出變?yōu)?,往復循環(huán)。顯示在LED上亮度逐漸變化
mDelay(20); //延時用于清晰看出變化
if(ADFlag) //定時采集輸入模擬量
{
ADFlag=0;
}
}
}
2,HL-1
/*-----------------------------------------------
名稱:IIC協(xié)議 PCF8591ADDA轉換
內容:此程序通過IIC協(xié)議對DAAD芯片操作, 并輸出模擬量,用LED亮度漸變指示
------------------------------------------------*/
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
#include <intrins.h> //包含NOP空指令函數(shù)_nop_();
#define AddWr 0x90 //寫數(shù)據(jù)地址
#define AddRd 0x91 //讀數(shù)據(jù)地址
sbit RST=P2^4; //關掉時鐘芯片輸出
sbit Sda=P2^0; //定義總線連接端口
sbit Scl=P2^1;
sbit Fm=P2^3; //FM
sbit dula=P2^6;
sbit wela=P2^7;
bit ADFlag; //定義AD采樣標志位
unsigned char code Datatab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//7段數(shù)共陰碼管段碼表
data unsigned char Display[8];//定義臨時存放數(shù)碼管數(shù)值
/*------------------------------------------------
延時程序
------------------------------------------------*/
void mDelay(unsigned char j)
{
unsigned int i;
for(;j>0;j--)
{
for(i=0;i<125;i++)
{;}
}
}
/*------------------------------------------------
初始化定時器1
------------------------------------------------*/
void Init_Timer1(void)
{
TMOD |= 0x10;
TH1=0xff; /* Init value */
TL1=0x00;
//PT1=1; /* 優(yōu)先級 */
EA=1; /* interupt enable */
ET1=1; /* enable timer1 interrupt */
TR1=1;
}
/*------------------------------------------------
啟動IIC總線
------------------------------------------------*/
void Start(void)
{
Sda=1;
_nop_();
Scl=1;
_nop_();
Sda=0;
_nop_();
Scl=0;
}
/*------------------------------------------------
停止IIC總線
------------------------------------------------*/
void Stop(void)
{
Sda=0;
_nop_();
Scl=1;
_nop_();
Sda=1;
_nop_();
Scl=0;
}
/*------------------------------------------------
應答IIC總線
------------------------------------------------*/
void Ack(void)
{
Sda=0;
_nop_();
Scl=1;
_nop_();
Scl=0;
_nop_();
}
/*------------------------------------------------
非應答IIC總線
------------------------------------------------*/
void NoAck(void)
{
Sda=1;
_nop_();
Scl=1;
_nop_();
Scl=0;
_nop_();
}
/*------------------------------------------------
發(fā)送一個字節(jié)
------------------------------------------------*/
void Send(unsigned char Data)
{
unsigned char BitCounter=8;
unsigned char temp;
do
{
temp=Data;
Scl=0;
_nop_();
if((temp&0x80)==0x80)
Sda=1;
else
Sda=0;
Scl=1;
temp=Data<<1;
Data=temp;
BitCounter--;
}
while(BitCounter);
Scl=0;
}
/*------------------------------------------------
讀入一個字節(jié)并返回
------------------------------------------------*/
unsigned char Read(void)
{
unsigned char temp=0;
unsigned char temp1=0;
unsigned char BitCounter=8;
Sda=1;
do
{
Scl=0;
_nop_();
Scl=1;
_nop_();
if(Sda)
temp=temp|0x01;
else
temp=temp&0xfe;
if(BitCounter-1)
{
temp1=temp<<1;
temp=temp1;
}
BitCounter--;
}
while(BitCounter);
return(temp);
}
/*------------------------------------------------
寫入DA數(shù)模轉換值
------------------------------------------------*/
void DAC(unsigned char Data)
{
Start();
Send(AddWr); //寫入芯片地址
Ack();
Send(0x40); //寫入控制位,使能DAC輸出
Ack();
Send(Data); //寫數(shù)據(jù)
Ack();
Stop();
}
/*------------------------------------------------
讀取AD模數(shù)轉換的值,有返回值
------------------------------------------------*/
unsigned char ReadADC(unsigned char Chl)
{
unsigned char Data;
Start(); //寫入芯片地址
Send(AddWr);
Ack();
Send(0x40|Chl);//寫入選擇的通道,本程序只用單端輸入,差分部分需要自行添加
//Chl的值分別為0、1、2、3,分別代表1-4通道
Ack();
Start();
Send(AddRd); //讀入地址
Ack();
Data=Read(); //讀數(shù)據(jù)
Scl=0;
NoAck();
Stop();
return Data; //返回值
}
void fmg(void)//fm關
{
Fm=1; // 關 fm
}
void cmg(void)//數(shù)碼管鎖存函數(shù) 關時鐘DS1302
{
dula=1;
P0=0x00;
dula=0;
wela=1;
P0=0x00;
wela=0;
RST=0; // 關時鐘DS1302
}
/*------------------------------------------------
主程序
------------------------------------------------*/
void main()
{
unsigned char num; //DA數(shù)模輸出變量
unsigned char ADtemp; //定義中間變量
Init_Timer1();
cmg();//數(shù)碼管鎖存
fmg();
while(1)
{
DAC(num); //DA輸出,可以用LED模擬電壓變化
num++; //累加,到256后溢出變?yōu)?,往復循環(huán)。顯示在LED上亮度逐漸變化
mDelay(20); //延時用于清晰看出變化
if(ADFlag) //定時采集輸入模擬量
{
ADFlag=0;
}
}
}
|