单片机 通过串口控制DA变换器的输出程序

作者&投稿:韶永 (若有异议请与网页底部的电邮联系)
关于单片机向串口发送AD转换结果的程序~

兄弟:不知道你玩不玩32 ,有个32 的在工程上用过,直接刷程序,串口连接电脑就可以输出AD 转换的结果。如果不玩32 的话。
首先第一步排查: 排查单片机能不能正确显示 你测试到的 AD 信号,显示正确不?
比如给他 3V 电压 ,用数码管显示出来。
第二: 串口发送,找个能正确发送数据的代码 ,直接把 ,你检查的数值给这个变量,让串口发送,
一步一步找问题,你绝对能解决的。我把AD0809 的代码给你用数码管测试

#include
#define uint unsigned int
#define uchar unsigned char
uchar code LEDData[]=
{
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
};
sbit OE = P1^0;
sbit EOC = P1^1;
sbit ST = P1^2;
sbit CLK = P1^3;
void DelayMS(uint ms)
{
uchar i;
while(ms--)
{
for(i=0;i<120;i++);
}
}
void Display_Result(uchar d)
{
P2 = 0xf7;
P0 = LEDData[d%10];
DelayMS(5);
P2 = 0xfb;
P0 = LEDData[d%100/10];
DelayMS(5);
P2 = 0xfd;
P0 = LEDData[d/100];
DelayMS(5);
}
void main()
{
TMOD = 0x02;
TH0 = 0x14;
TL0 = 0x00;
IE = 0x82;
TR0 = 1;
P1 = 0x3f;
while(1)
{
ST = 0;
ST = 1;
ST = 0;
while(EOC == 0);
OE = 1;
Display_Result(P3);
OE = 0;
}
}
void Timer0_INT() interrupt 1
{
CLK = !CLK;
}

看看我这个 adc0808 测电压 然后串口发送,另一边数码管显示

DA,AD都在里面。。DA芯片是PCF8591ADDA
IIC协议 PCF8591ADDA转换
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <intrins.h> //包含NOP空指令函数_nop_();

#define AddWr 0x90 //写数据地址
#define AddRd 0x91 //读数据地址

sbit Sda=P1^2; //定义总线连接端口
sbit Scl=P1^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 main()
{
unsigned char num; //DA数模输出变量
unsigned char ADtemp; //定义中间变量
Init_Timer1();

while(1)
{
DAC(num); //DA输出,可以用LED模拟电压变化
num++; //累加,到256后溢出变为0,往复循环。显示在LED上亮度逐渐变化
mDelay(20); //延时用于清晰看出变化
if(ADFlag) //定时采集输入模拟量
{
ADFlag=0;

ADtemp=ReadADC(0);
Display[0]=Datatab[(ReadADC(0))/50]|0x80;//处理0通道电压显示
Display[1]=Datatab[((ReadADC(0))%50)/10];

ADtemp=ReadADC(1);
Display[2]=Datatab[((ReadADC(1))/50)]|0x80;//处理1通道电压显示 此通道暂时屏蔽,可以自行添加
Display[3]=Datatab[((ReadADC(1))%50)/10];

ADtemp=ReadADC(2);
Display[4]=Datatab[((ReadADC(2))/50)]|0x80;//处理1通道电压显示 此通道暂时屏蔽,可以自行添加
Display[5]=Datatab[((ReadADC(2))%50)/10];

ADtemp=ReadADC(3);
Display[6]=Datatab[((ReadADC(3))/50)]|0x80;//处理1通道电压显示 此通道暂时屏蔽,可以自行添加
Display[7]=Datatab[((ReadADC(3))%50)/10];

}
}
}

/*------------------------------------------------
定时器中断程序
------------------------------------------------*/
void Timer1_isr(void) interrupt 3 using 1//定时器1执行数码管动态扫描
{

static unsigned int count,j;
TH1=0xfb; //重新赋值
TL1=0x00;
j++;
if(j==300)
{j=0;ADFlag=1;} //定时置位AD采样标志位

P0=Display[count];//用于动态扫描数码管
P2=count;
count++;
if(count==8) //表示扫描8个数码管
count=0;

}

建议 去 我的领地 5d6d 的 proteus 论坛看看

那里有很多 单片机仿真实例,包括仿真图 和 源码