以下是补充(能想到的范围有限有没想到的还请谅解)
DA工作原理
基于PCF8591芯片
DA是什么?
n DA指数模转换(Digital to Analog),顾名思义,就是把数字信号转换成模拟信号。与DA
相对应,AD是把模拟信号转换为数字信号,便于计算机等数字控制器处理。
DA有什么作用?
n 1、将数字量转换成模拟量,以便操纵控制对象。n 2、用数字化来控制各种对象。
n 3、可以在单片机中输入数字,来控制输出压力计力的大小。
串行DA芯片与单片机连接方法(两种):
HL-1连接方法
HJ-c52连接方法
D/A转换器的主要性能指标
1、分辨率
分辨率是指输入数字量的最低有效位(LSB)发生变化时,所对应的输出模拟量(电压或电流)的变化量。它反映了
输出模拟量的最小变化值。
分辨率与输入数字量的位数有确定的关系,可以表示成FS /2的n方 。FS表示满量程输入值,n为二进制位数。对于5V
的满量程,采用8位的DAC时,分辨率为5V/256=19.5mV;当采用12位的DAC时,分辨率则为5V/4096=1.22mV。显然,
位数越多分辨率就越高。
2、线性度
线性度(也称非线性误差)是实际转换特性曲线与理想直线特性之间的最大偏差。常以相对于满量程的百分数
表示。如±1%是指实际输出值与理论值之差在满刻度的±1%以内。
3、绝对精度和相对精度
绝对精度(简称精度)是指在整个刻度范围内,任一输入数码所对应的模拟量实际输出值与理论值之
间的最大误差。绝对精度是由DAC的增益误差(当输入数码为全1时,实际输出值与理想输出值之差)、
零点误差(数码输入为全0时,DAC的非零输出值)、非线性误差和噪声等引起的。绝对精度(即
最大误差)应小于1个LSB。 相对精度与绝对精度表示同一含义,用最大误差相对于满刻度的百分比表示。
4、建立时间
建立时间是指输入的数字量发生满刻度变化时,输出模拟信号达到满刻度值的±1/2LSB所需的时间。
是描述D/A转换速率的一个动态指标。电流输出型DAC的建立时间短。电压输出型DAC的
建立时间主要决定于运算放大器的响应时间。根据建立时间的长短,可以将DAC分成超高速(<1μ
S)、高速(10~1μS)、中速(100~10μS)、低速(≥100μS)几档。
应当注意,精度和分辨率具有一定的联系,但概念不同。DAC的位数多时,分辨率会提高,对
应于影响精度的量化误差会减小。但其它误差(如温度漂移、线性不良等)的影响仍会使DAC
的精度变差。
附带三个说明
一,HL-1的AD/DA模块和DS1302时钟模块原理图
二,HJ-C52的AD/DA原理图
三,一个AD/DA单独模块(PCF8951)的说明
AD/DA独立模块接线说明
1. 可以自己用杜邦线接到你自己的最小系统上,也可以接到慧净HJ-C51智能小车核心板上,接线方法参考源理图接,VCC接学
习板上的VCC,GND接学习板上的GND 其他的信号输入可以自己定义。
AD/DA独立模块简单说明
1. 本板采用全新AD/DA芯片PCF8591,设计合理,性能非常稳定,提供原理图及配套示例代码。
模块说明:
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的数据线分别接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的数据线
- uc code shuju[]={
- 0x0f,0x1e,0x2d,0x3c,0x4b,0x5a,0x69,0x78,0x87,0x96,0xa5,0xb4,0xc3,0xd2,0xe1,0xf0,0xff,//让电压逐渐升高的数据
- 0xff,0xf0,0xe1,0xd2,0xc3,0xb4,0xa5,0x96,0x87,0x78,0x69,0x5a,0x4b,0x3c,0x2d,0x1e,0x0f,//让电压逐渐下降的数据
- };
- 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写一个字节的数据
- {
- 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表示四路单数入00通道无增益的器件控制指令
- ack();
- write_byte(date);//表示DA数据
- ack();
- stop();
- }
- void main(void)
- { uc i;
- init();//I2C总线初始化
- while(1)
- {
- for(i=0;i<34;i++)
- {
- write(0x90,0x40,shuju[ i]);//向PCF8591里写入数据(即电压量的数据);
- delay(100);
- }
- }
- }
复制代码 以上是一个DA转换例子[我也是也是补充的(上传不了附件....就只能直接上码了 )
附带两种使LED输出显示DA
1,HJ-52
/*-----------------------------------------------
名称:IIC协议 PCF8591ADDA转换
内容:此程序通过IIC协议对DAAD芯片操作, 并输出模拟量,用LED亮度渐变指示
------------------------------------------------*/
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <intrins.h> //包含NOP空指令函数_nop_();
#define AddWr 0x90 //写数据地址
#define AddRd 0x91 //读数据地址
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段数共阴码管段码表
data unsigned char Display[8];//定义临时存放数码管数值
/*------------------------------------------------
延时程序
------------------------------------------------*/
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; /* 优先级 */
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_();
}
/*------------------------------------------------
发送一个字节
------------------------------------------------*/
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;
}
/*------------------------------------------------
读入一个字节并返回
------------------------------------------------*/
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数模转换值
------------------------------------------------*/
void DAC(unsigned char Data)
{
Start();
Send(AddWr); //写入芯片地址
Ack();
Send(0x40); //写入控制位,使能DAC输出
Ack();
Send(Data); //写数据
Ack();
Stop();
}
/*------------------------------------------------
读取AD模数转换的值,有返回值
------------------------------------------------*/
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(); //读数据
Scl=0;
NoAck();
Stop();
return Data; //返回值
}
void cmg(void)//数码管锁存函数 关时钟DS1302
{
dula=1;
P0=0x00;
dula=0;
wela=1;
P0=0x00;
wela=0;
}
/*------------------------------------------------
主程序
------------------------------------------------*/
void main()
{
unsigned char num; //DA数模输出变量
unsigned char ADtemp; //定义中间变量
Init_Timer1();
cmg();//关数码管函数
while(1)
{
DAC(num); //DA输出,可以用LED模拟电压变化
num++; //累加,到256后溢出变为0,往复循环。显示在LED上亮度逐渐变化
mDelay(20); //延时用于清晰看出变化
if(ADFlag) //定时采集输入模拟量
{
ADFlag=0;
}
}
}
2,HL-1
/*-----------------------------------------------
名称:IIC协议 PCF8591ADDA转换
内容:此程序通过IIC协议对DAAD芯片操作, 并输出模拟量,用LED亮度渐变指示
------------------------------------------------*/
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <intrins.h> //包含NOP空指令函数_nop_();
#define AddWr 0x90 //写数据地址
#define AddRd 0x91 //读数据地址
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段数共阴码管段码表
data unsigned char Display[8];//定义临时存放数码管数值
/*------------------------------------------------
延时程序
------------------------------------------------*/
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; /* 优先级 */
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_();
}
/*------------------------------------------------
发送一个字节
------------------------------------------------*/
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;
}
/*------------------------------------------------
读入一个字节并返回
------------------------------------------------*/
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数模转换值
------------------------------------------------*/
void DAC(unsigned char Data)
{
Start();
Send(AddWr); //写入芯片地址
Ack();
Send(0x40); //写入控制位,使能DAC输出
Ack();
Send(Data); //写数据
Ack();
Stop();
}
/*------------------------------------------------
读取AD模数转换的值,有返回值
------------------------------------------------*/
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(); //读数据
Scl=0;
NoAck();
Stop();
return Data; //返回值
}
void fmg(void)//fm关
{
Fm=1; // 关 fm
}
void cmg(void)//数码管锁存函数 关时钟DS1302
{
dula=1;
P0=0x00;
dula=0;
wela=1;
P0=0x00;
wela=0;
RST=0; // 关时钟DS1302
}
/*------------------------------------------------
主程序
------------------------------------------------*/
void main()
{
unsigned char num; //DA数模输出变量
unsigned char ADtemp; //定义中间变量
Init_Timer1();
cmg();//数码管锁存
fmg();
while(1)
{
DAC(num); //DA输出,可以用LED模拟电压变化
num++; //累加,到256后溢出变为0,往复循环。显示在LED上亮度逐渐变化
mDelay(20); //延时用于清晰看出变化
if(ADFlag) //定时采集输入模拟量
{
ADFlag=0;
}
}
}
|