找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4898|回复: 1
打印 上一主题 下一主题
收起左侧

51单片机PCF8591的DA转换程序详解[含HL-1与HJ-c52 DA代码AD/DA原理图](可直接复...

[复制链接]
跳转到指定楼层
楼主

以下是补充(能想到的范围有限有没想到的还请谅解)
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通过亮度显示。
------------------------------------------------(因为有些东西电脑没备份..所以找不到了)-----------------------------------------------------
  1. /*-----------------------------------------------
  2.   内容:scl=P3^0;//IIC的时钟线  sda=P3^1;//IIC的数据线分别接J26-7和J26-6上。
  3.         J23-5接J26-5上
  4.         LED会逐渐变亮后有逐渐变暗
  5. ------------------------------------------------*/
  6. #include<reg51.h>
  7. #include<intrins.h>
  8. #define uc unsigned char
  9. #define ui unsigned int

  10. sbit scl=P3^0;//IIC的时钟线
  11. sbit sda=P3^1;//IIC的数据线
  12. uc code shuju[]={
  13. 0x0f,0x1e,0x2d,0x3c,0x4b,0x5a,0x69,0x78,0x87,0x96,0xa5,0xb4,0xc3,0xd2,0xe1,0xf0,0xff,//让电压逐渐升高的数据
  14. 0xff,0xf0,0xe1,0xd2,0xc3,0xb4,0xa5,0x96,0x87,0x78,0x69,0x5a,0x4b,0x3c,0x2d,0x1e,0x0f,//让电压逐渐下降的数据
  15. };

  16. void delayus(void)
  17. {
  18.   ;;
  19. }


  20. void delay(ui m)
  21. {
  22. ui i,j;
  23. for(i=0;i<120;i++)
  24.   for(j=0;j<m;j++);
  25. }


  26. void init(void)//IIC的初始化
  27. {
  28.    scl=1;
  29.    delayus();
  30.    sda=1;
  31.    delayus();
  32. }

  33. void start(void)//IIC的起始信号
  34. {
  35.    scl=1;
  36.    delayus();
  37.    sda=1;
  38.    delayus();
  39.    sda=0;
  40.    delayus();
  41. }

  42. void stop(void)//IIC的停止信号
  43. {
  44.    sda=0;
  45.    delayus();
  46.    scl=1;
  47.    delayus();
  48.    sda=1;
  49.    delayus();
  50. }

  51. void ack(void)//IIC的应答信号
  52. {
  53.    uc i;
  54.    scl=1;
  55.    delayus();
  56.    while((sda==1)&(i<255))i++;
  57.    scl=0;
  58.    delayus();
  59. }

  60. void write_byte(uc date)//向IIC写一个字节的数据
  61. {
  62.         uc i,temp;
  63.         temp=date;
  64.         for(i=0;i<8;i++)
  65.         {
  66.                 temp=temp<<1;
  67.                 scl=0;
  68.             delayus();
  69.                 sda=CY;
  70.                 delayus();
  71.                 scl=1;
  72.                 delayus();
  73.         }
  74.         scl=0;
  75.         delayus();
  76.         sda=1;
  77.         delayus();
  78. }

  79. void write(uc add,uc sda,uc date)
  80. {
  81.    start();
  82.    write_byte(add);//0x90表示器件地址为000的写操作
  83.    ack();
  84.    write_byte(sda);//0x40表示四路单数入00通道无增益的器件控制指令
  85.    ack();
  86.    write_byte(date);//表示DA数据
  87.    ack();
  88.    stop();
  89. }

  90. void main(void)
  91. { uc i;
  92.   init();//I2C总线初始化
  93.   while(1)
  94.   {
  95.    for(i=0;i<34;i++)
  96.    {
  97.    write(0x90,0x40,shuju[ i]);//向PCF8591里写入数据(即电压量的数据);
  98.    delay(100);
  99.    }
  100.   }
  101. }
复制代码
以上是一个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;
                   }
           }
        }



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1 发表于 2019-8-1 17:46 | 只看该作者
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表