基于51单片机的AD和DA

本讲内容:

      介绍AD/DA芯片PCF8591,通过例程讲解AD和DA过程。

AD和DA的概念:

      AD转换的功能是把模拟量电压转换为数字量电压。

      DA转换的功能正好相反,就是讲数字量转换位模拟量。

分辨率的概念:

      一位数字量所表示的电压值。对于5V的满量程,采用8位的DAC时,分辨率为5V/256=19.5mV。

PCF8591简介:

      PCF8591是单片、单电源低功耗8位CMOS数据采集器件,具有4个模拟输入、一个模拟输出和一个串行IIC总线接口。3个地址引脚A0、A1和A2用于编程硬件地址,允许将最多8个器件连接至IIC总线而不需要额外硬件。

PCF8591管脚图:

 

PCF8591接口电路图:

PCF8591的控制寄存器:

 

D1、D0AD通道选择00通道0;01通道1;10通道2;11通道3
D2自动增益选择(有效位为1)
D5、D4输入模式选择:00四路单数输入;01三路差分输入;10单端与差分配合输入;11为模拟输入有效
D6模拟输出使能位。(时能为1)

例程:

AD程序

/**********************AD转换*********************     

*单片机型号:STC89C52RC

*开发环境:KEIL

*功能:IIC协议 PCF8591 AD转换

***************************************************/

#include<reg52.h>   

#include <intrins.h>

#define LCD_Data P0

#define Busy 0x80

#define uchar unsigned char

#define delay0;_nop_();

#define AddWr 0x90

#define AddRd 0x91

 

sbit RST=P2^4;   

sbit Sda=P2^0;     

sbit Scl=P2^1;                             

sbit LCD_RS=P1^0;

sbit LCD_RW=P1^1;

sbit LCD_E =P2^5;

bit ADFlag;

uchar code table0[]={"     SL-51A     "};

uchar code table1[]={"   AD CONVERT   "};

uchar code table2[]={"CH1: . V"};

uchar code table3[]={"CH2: . V"};

uchar code table4[]={"CH3: . V"};

uchar code table5[]={"CH4: . V"};

uchar TempData[8];

void Delay5Ms(void);

void delay(int In,int Out);                                                      

void WriteDataLCD(unsigned char WDLCD);

void WriteCommandLCD(unsigned char WCLCD,BuysC);

uchar ReadDataLCD(void);

uchar ReadStatusLCD(void);

void LCDInit(void);

void DisplayOneChar(unsigned char X,unsigned char Y,unsigned char DData);

void DisplayListChar(unsigned char X,unsigned char Y,unsigned char code *DData);

void Init_Timer1(void);

void Start(void);

void Stop(void);

void Ack(void);

void NoAck(void);

void Send(unsigned char Data);

uchar Read(void);

void DAC(unsigned char Data);

uchar ReadADC(unsigned char Chl);

void info_disp(void);

/**********5ms延时函数***************************/

void Delay5Ms(void)

{unsigned int TempCyc=3552;while(TempCyc--);}

/********************延迟函数********************/

void delay(int In,int Out)                                                                             

{

 int i,j;

 for(i=0;i<In;i++)

 {for(j=0;j<Out;j++){;}}

}

/*------------------------------------------------

                    初始化定时器1     

------------------------------------------------*/

void Init_Timer1(void)

{TMOD|=0x10;TH1=0xff;TL1=0x00;EA=1;ET1=1;TR1=1;}

/*------------------------------------------------

                    启动IIC总线         

------------------------------------------------*/

void Start(void)

{Sda=1;delay0;Scl=1;delay0;Sda=0;delay0;Scl=0;}

/*------------------------------------------------

                    停止IIC总线       

------------------------------------------------*/

void Stop(void)

{Sda=0;delay0;Scl=1;delay0;Sda=1;delay0;Scl=0;}

/*------------------------------------------------

                   应答IIC总线    

------------------------------------------------*/

void Ack(void)

{Sda=0;delay0;Scl=1;delay0;Scl=0;delay0;}

/*------------------------------------------------

                 非应答IIC总线    

------------------------------------------------*/

void NoAck(void)

{Sda=1;delay0;Scl=1;delay0;Scl=0;delay0;}

/*------------------------------------------------

              发送一个字节    

------------------------------------------------*/

void Send(unsigned char Data)

{

 uchar BitCounter=8;uchar temp;

 do

 {

  temp=Data;

  Scl=0;delay0;

  if((temp&0x80)==0x80){Sda=1;}

  else{Sda=0;}

  Scl=1;

  temp=Data<<1;

  Data=temp;

  BitCounter--;

 }

 while(BitCounter);

 Scl=0;

}

/*------------------------------------------------

               读入一个字节并返回      

------------------------------------------------*/

uchar Read(void)

{

 uchar temp=0;uchar temp1=0;uchar BitCounter=8;

 Sda=1;   

 do

 {

  Scl=0;delay0;

  Scl=1;delay0;

  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);   

 Ack();Send(Data);

 Ack();Stop();     

}

/*------------------------------------------------

                 读取AD模数转换的值,有返回值

------------------------------------------------*/

uchar ReadADC(unsigned char Chl)

{

 uchar Data;

 Start();    

 Send(AddWr);Ack();

 Send(0x40|Chl);Ack();

 Start();Send(AddRd);    

 Ack();Data=Read();

 Scl=0;

 NoAck();Stop();

 return Data; 

}

/*******************写数据函数*******************/

void WriteDataLCD(unsigned char WDLCD)

{

 ReadStatusLCD();

 LCD_Data=WDLCD;

 LCD_RS=1;

 LCD_RW=0;

 LCD_E=0;

 LCD_E=0; 

 LCD_E=1;

}

/*******************写指令函数*******************/

void WriteCommandLCD(unsigned char WCLCD,BuysC)

{

 if(BuysC)ReadStatusLCD();

 LCD_Data=WCLCD;

 LCD_RS=0;

 LCD_RW=0;

 LCD_E=0;

 LCD_E=0;

 LCD_E=1;

}

/*******************读数据函数*******************/

unsigned char ReadDataLCD(void)

{

 LCD_RS=1;

 LCD_RW=1;

 LCD_E=0;

 LCD_E=0;

 LCD_E=1;

 return(LCD_Data);

}

/*******************读状态函数*******************/

unsigned char ReadStatusLCD(void)

{

 LCD_Data=0xFF;

 LCD_RS=0;

 LCD_RW=1;

 LCD_E=0;

 LCD_E=0;

 LCD_E=1;

 while (LCD_Data&Busy);

 return(LCD_Data);

}

/********************LCD初始化*******************/

void LCDInit(void)

{

 LCD_Data=0;

 WriteCommandLCD(0x38,0);Delay5Ms();

 WriteCommandLCD(0x38,0);Delay5Ms();

 WriteCommandLCD(0x38,0);Delay5Ms();

 WriteCommandLCD(0x38,1); 

 WriteCommandLCD(0x08,1);

 WriteCommandLCD(0x01,1);

 WriteCommandLCD(0x06,1);

 WriteCommandLCD(0x0C,1);

}

/********************清屏 函数********************/

void LCD_Clear(void){WriteCommandLCD(0x01,1);Delay5Ms();}

/**************按指定位置显示一个字符*************/

void DisplayOneChar(unsigned char X,unsigned char Y,unsigned char DData)

{

 Y&=0x1;X&=0xF;    

 if(Y)X|=0x40;

 X|=0x80;

 WriteCommandLCD(X, 0);

 WriteDataLCD(DData);

}

/**************按指定位置显示一串字符*************/

void DisplayListChar(unsigned char X,unsigned char Y,unsigned char code *DData)

{

 unsigned char ListLength;ListLength=0;

 Y&=0x1;X&=0xF;

 while(DData[ListLength]>=0x20) 

 {

  if(X<=0xF)

  {

   DisplayOneChar(X, Y, DData[ListLength]); 

   ListLength++;

   X++;

  }

 }

}

/********************系统初始化*******************/

void sys_init(void)

{

 LCDInit(); 

 delay(5,100);

 Init_Timer1();

 DisplayListChar(0,0,table0);

 DisplayListChar(0,1,table1);

}

/*------------------------------------------------

                      显示

------------------------------------------------*/

void info_disp(void)

{

 DisplayListChar(0,0,table2);

 DisplayOneChar(4,0,(0x30+TempData[0]));

 DisplayOneChar(6,0,(0x30+TempData[1]));

 DisplayListChar(8,0,table3);

 DisplayOneChar(12,0,(0x30+TempData[2]));

 DisplayOneChar(14,0,(0x30+TempData[3]));

 DisplayListChar(0,1,table4);

 DisplayOneChar(4,1,(0x30+TempData[4]));

 DisplayOneChar(6,1,(0x30+TempData[5]));

 DisplayListChar(8,1,table5);

 DisplayOneChar(12,1,(0x30+TempData[6]));

 DisplayOneChar(14,1,(0x30+TempData[7]));

}

/*------------------------------------------------

                   主程序

------------------------------------------------*/

void main()

{

 uchar num;uchar ADtemp;      

 sys_init();delay(100,1000);

 LCD_Clear();                               

 while(1)

 {

  DAC(num);num++;delay(5,100);   

  if(ADFlag)  

  {

   ADFlag=0;

   ADtemp=ReadADC(0);

   TempData[0]=(ReadADC(0))/50;TempData[1]=((ReadADC(0))%50)/10;

   ADtemp=ReadADC(1);

   TempData[2]=(ReadADC(1))/50;TempData[3]=((ReadADC(1))%50)/10;   

   ADtemp=ReadADC(2);

   TempData[4]=(ReadADC(2))/50;TempData[5]=((ReadADC(2))%50)/10;

   ADtemp=ReadADC(3);

   TempData[6]=(ReadADC(3))/50;TempData[7]=((ReadADC(4))%50)/10;

   info_disp();

  }

 }

}

/*------------------------------------------------

                   定时器中断程序

------------------------------------------------*/

void Timer1_isr(void) interrupt 3 using 1

{

 static unsigned int j;

 TH1=0xfb;TL1=0x00;

 j++;

 if(j==200){j=0;ADFlag=1;}         

}

DA程序

/******************DA转换LED输出******************    

*单片机型号:STC89C52RC

*开发环境:KEIL

*功能:此程序通过IIC协议对DAAD芯片操作, 并输出模拟量,用LED亮度渐变指示

*******************************************************/

#include<reg52.h>        

#include <intrins.h>  

#define delay0; _nop_();

#define uchar unsigned char

#define AddWr 0x90

#define AddRd 0x91  

sbit RST=P2^4;

sbit Sda=P2^0; 

sbit Scl=P2^1;

sbit Fm=P2^3;

sbit LE1=P2^6;

sbit LE2=P2^7;

bit ADFlag;

uchar code Datatab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

data uchar  Display[8];      

/*------------------------------------------------

                    延时程序     

------------------------------------------------*/

void mDelay(uchar j)

{

 unsigned int i;

 for(;j>0;j--)

 {for(i=0;i<125;i++){;}}

}

/*------------------------------------------------

                    初始化定时器1      

------------------------------------------------*/

void Init_Timer1(void)

{TMOD|=0x10;TH1=0xff;TL1=0x00;EA=1;ET1=1;TR1=1;}

/*------------------------------------------------

                    启动IIC总线          

------------------------------------------------*/

void Start(void)

{Sda=1;delay0;Scl=1;delay0;Sda=0;delay0;Scl=0;}

/*------------------------------------------------

                    停止IIC总线           

------------------------------------------------*/

void Stop(void)

{Sda=0;delay0;Scl=1;delay0;Sda=1;delay0;Scl=0;}

/*------------------------------------------------

                   应答IIC总线        

------------------------------------------------*/

void Ack(void)

{Sda=0;delay0;Scl=1;delay0;Scl=0;delay0;}

/*------------------------------------------------

                 非应答IIC总线        

------------------------------------------------*/

void NoAck(void)

{Sda=1;delay0;Scl=1;delay0;Scl=0;delay0;}

/*------------------------------------------------

              发送一个字节    

------------------------------------------------*/

void Send(uchar Data)

{

 uchar BitCounter=8;

 uchar buffer;

 do

 {

  buffer=Data;

  Scl=0;delay0;

  if((buffer&0x80)==0x80)Sda=1;

  else Sda=0;

  Scl=1;

  buffer=Data<<1;

  Data=buffer;

  BitCounter--;

 }

 while(BitCounter);

 Scl=0;

}

/*------------------------------------------------

               读入一个字节并返回      

------------------------------------------------*/

uchar Read(void)

{

 uchar buffer=0;

 uchar buffer1=0;

 uchar BitCounter=8;

 Sda=1;

 do

 {

  Scl=0;delay0;

  Scl=1;delay0;

  if(Sda)buffer=buffer|0x01;

  else buffer=buffer&0xfe;

  if(BitCounter-1)

  {

   buffer1=buffer<<1;

   buffer=buffer1;

  }

  BitCounter--;

 }

 while(BitCounter);

 return(buffer);

}

/*------------------------------------------------

                    写入DA数模转换值      

------------------------------------------------*/

void DAC(uchar Data)

{

 Start();Send(AddWr); 

 Ack();Send(0x40);        

 Ack();Send(Data);

 Ack();Stop();     

}

/*------------------------------------------------

                 读取AD模数转换的值,有返回值     

------------------------------------------------*/

uchar ReadADC(uchar Chl)

{

 uchar Data;

 Start();Send(AddWr);

 Ack();Send(0x40|Chl);        

       

 Ack();

 Start();Send(AddRd);  

 Ack();Data=Read(); 

 Scl=0;NoAck();

 Stop();

 return Data;

}

void fmg(void){Fm=1;}

void cmg(void)

{

 LE1=1;

 P0=0x00;

 LE1=0;LE2=1;

 P0=0x00;

 LE2=0;RST=0; 

}

/*------------------------------------------------

                   主程序     

------------------------------------------------*/

void main()

{

 uchar num;  

 uchar ADbuffer; 

 Init_Timer1();

 cmg();

 fmg();

 while(1)

 {     

  DAC(num);         

  num++;            

  mDelay(20); 

  if(ADFlag)           

  {

   ADFlag=0;

   ADbuffer=ReadADC(0);

   Display[0]=Datatab[(ReadADC(0))/50]|0x80;

   Display[1]=Datatab[((ReadADC(0))%50)/10];

   

   ADbuffer=ReadADC(1);

   Display[2]=Datatab[((ReadADC(1))/50)]|0x80;

   Display[3]=Datatab[((ReadADC(1))%50)/10];

       

   ADbuffer=ReadADC(2);

   Display[4]=Datatab[((ReadADC(2))/50)]|0x80;

   Display[5]=Datatab[((ReadADC(2))%50)/10];

       

   ADbuffer=ReadADC(3);

   Display[6]=Datatab[((ReadADC(3))/50)]|0x80;

   Display[7]=Datatab[((ReadADC(3))%50)/10];

  }

 }

}

最后,求求看到的此文的小伙伴点赞关注支持一下下哦。毕竟,码字不容易哦,您的支持是我最大的动力呀!!!呜呜呜~~~

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式硬件与代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值