注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
825cow的个人空间 https://home.eeworld.com.cn/space-uid-449920.html [收藏] [复制] [分享] [RSS]
日志

PCF8591芯片以及AD学习(一)

已有 4277 次阅读2015-12-29 00:12 |个人分类:51单片机| 单片机, PCF8591, PCF8591

一.AD的主要参数:
1、AD的位数:表明这个AD共有2^n个刻度,8位AD,输出的刻度是0~255。 (255=2^8-1)
2、分辨率:就是AD能够分辨的最小的模拟量变化,假设5.10V的系统用8位的AD采样,那么它能分辨的最小电压就是5.10/255=0.02V。
3、INL:Interger NONliner 积分非线性度,表示了ADC器件在所有的数值点上对应的模拟值,和真实值之间误差最大的那一点的误差值。也就是,输出数值偏离线性最大的距离。单位是LSB(即最低位所表示的量)。比如12位ADC:TLC2543,INL值为1LSB。那么,如果基准4.095V,测某电压得的转换结果是1000,那么,真实电压值可能分布在0.999~1.001V之间。这里是这样这样计算得来的,12位ADC最小分辨率是1/4095。在这里即为4.095*(1/4095)=0.001V。那么1LSB就为0.001V,。转换结果为1000即为1V。
4、DNL:Differencial NonLiner-差分非线性度,理论上说,模数器件相邻量个数据之间,模拟量的差值都是一样的。就相一把疏密均匀的尺子。但实际并不如此。一把分辨率1毫米的尺子,相邻两刻度之间也不可能都是1毫米整。那么,ADC相邻两刻度之间最大的差异就叫差分非线性值(Differencial NonLiner)。DNL值如果大于1,那么这个ADC甚至不能保证是单调的,输入电压增大,在某个点数值反而会减小。这种现象在SAR(逐位比较)型ADC中很常见。
5、基准源:有内部基准源、外部基准源等等。
6、转换速率:也就是转换周期的倒数,转换周期就是完成一次AD转换所需的时间
二.PCF8591芯片
1.电路连接图和引脚功能如下:
PCF8591芯片以及AD学习(一) - 元宝 - 元宝的世界

(1).PCF8591是具有I2C总线借口的8位AD/DA转换芯片,内部为单一电源供电(2.5~6V),典型值为5V,CMOS工艺。PCF8591有4路AD输入,属逐次比较型,内含采样保持电路;1路8位DA输出,内含DAC数据寄存器。AD/DA转换的最大速率约为11KHz。
(2).Philips规定AD器件高四位地址为1001,低三位地址为引脚地址A0,A1,A2,由硬件电路决定。
(3).控制寄存器:

3.控制流程。
 看器件手册可以知道:
      在IICa总线中,器件地址必须是起始条件后作为第一个字节发送。发送给PCF8591的第二个字节被存储在控制寄存器,用于控制寄存器的功能。发送给PCF8591的第三个字节被存储到DAC数据寄存器。并使用片上D/A转换成相应的模拟电压。
 
    一个A/D转换周期总是开始于发送一个有效读模式地址给PCF8591之后。A/D转换周期在应答时钟脉冲的后沿被触发。
操作分四步:
(1)、发送地址字节,选择该器件。
(2)、发送控制字节,选择相应通道。               //
(3)、重新发送地址字节,选择该器件。
(4)、接收目标通道的数据。
这次的程序流程是:AD采样,循环执行。
程序如下:
  1. <span style="font-size:18px;">/* 
  2. 项目名称:PCF8591实现AD转换 
  3. 项目内容:A/D转换,并把转换的数字信号送给P0口控制LED灯 
  4. ,调节电位器时观察LED的变化 
  5. 作者:YUAN 
  6. */  
  7.   
  8. #include <reg52.h>  
  9. #include <intrins.h>  //_nop_()延时头文件  
  10. typedef unsigned char uChar8;  
  11. typedef unsigned int uInt16;  
  12. sbit SDA = P1^0;  
  13. sbit SCL = P1^1;  
  14. #define PCF8591Add 0x90 //PCF8591的器件地址和写操作  
  15.   
  16. //延时函数  
  17. void DelayMS(uInt16 lValMS);  
  18. void Delay5us(void);  
  19. //IIC操作的几个函数  
  20. void IICInit(void);     //IIC初始化  
  21. void IICStart(void);    //起始信号  
  22. void IICStop(void);     //停止信号  
  23. void IICAck(void);      //应答信号  
  24. void IICReadAck(void);  //读应答信号  
  25. void IICWriteOneByte(uChar8 lByteVal);                  //写一个字节  
  26. uChar8 IICReadOneByte(void);        //读一个字节  
  27. void PCF8591WriteRegulate(uChar8 lREGVal);  //Regulate控制器,这里写控制函数  
  28. uChar8  ReadDataPCF8591(void);   
  29.                                   
  30. void main()  
  31. {  
  32.     IICInit();  
  33.     while(1)  
  34.     {      
  35.         /*写入控制字00,即模拟量输出关闭,选择通道0, 
  36.         不自动增加通道,模拟量输入围方式0*/  
  37.          PCF8591WriteRegulate(0x00);  
  38.          P0 = ReadDataPCF8591();   
  39.          DelayMS(10);  
  40.     }  
  41. }  
  42.   
  43. void DelayMS(uInt16 lValMS) //延时函数  
  44. {  
  45.     uInt16 luiVal,lujVal;  
  46.     for(luiVal = 0; luiVal < lValMS; luiVal++)  
  47.         for(lujVal = 0; lujVal < 113; lujVal++);  
  48. }  
  49. void Delay5us(void)  
  50. {  
  51.     _nop_();_nop_();_nop_();  
  52.     _nop_();_nop_();_nop_();  
  53. }  
  54. //IIC总线空闲时均为高电平  
  55. void IICInit(void)      //IIC初始化  
  56. {  
  57.     SCL = 0;  
  58.     SDA=1;  
  59.     Delay5us();  
  60.     SCL=1;  
  61. }  
  62. //SCL高电平期间SDA由高到低的变化为起始信号  
  63. void IICStart(void//起始信号  
  64. {  
  65.     SCL = 0;  
  66.     Delay5us();  
  67.     SDA = 1;  
  68.     Delay5us();  
  69.     SCL = 1;  
  70.     Delay5us();  
  71.     SDA = 0;  
  72.     Delay5us();  
  73.     //防止接下来SDA数据变化导致IIC总线误判   
  74.     SCL = 0;       
  75. }  
  76. //SCL高电平期间SDA由低到高的变化为终止信号  
  77. void IICStop(void)      //停止信号  
  78. {  
  79.     SCL = 0;  
  80.     Delay5us();  
  81.     SDA = 0;  
  82.     Delay5us();  
  83.     SCL = 1;  
  84.     Delay5us();  
  85.     SDA = 1;  
  86.     Delay5us();  
  87.     //防止接下来SDA数据变化导致IIC总线误判   
  88.     SCL = 0;  
  89. }  
  90. //一个脉冲期间,SDA为低电平为应答  
  91. void IICAck(void)       //应答信号  
  92. {  
  93.     SCL = 0;  
  94.     Delay5us();  
  95.     SDA = 0;  
  96.     Delay5us();  
  97.     SCL = 1;  
  98.     Delay5us();  
  99.     SCL = 0;          
  100. }  
  101. /*cpu读应答信号,如果应答了则 
  102. 继续传输数据,否则在一定时间里, 
  103. 默认已经应答,继续传数据 
  104. */  
  105. void IICReadAck(void)   //读应答信号  
  106. {  
  107.     uChar8 li = 0;  
  108.     SCL = 0;  
  109.     SDA = 1;  //确保读出的值为0,因此先送1  
  110.     Delay5us();  
  111.     SCL = 1;  
  112.     Delay5us();  
  113.     //如果没有应答或时间没有超过预定时间则停在此处  
  114.     while((1 == SDA)&&(li<255))li++;  
  115.     SCL = 0;  
  116.     Delay5us();       
  117.     SDA = 1;              
  118. }  
  119. /* 
  120.     写1个字节,先写高位。 
  121. */  
  122. void IICWriteOneByte(uChar8 lByteVal)                   //写一个字节  
  123. {  
  124.     uChar8 li,liVal;  
  125.     liVal = lByteVal;  
  126.   
  127.     for(li=0;li<8;li++)      
  128.     {  
  129.           
  130.         SCL = 0;   
  131.         Delay5us();   
  132.         SDA = (bit)(liVal&0x80);    //把数据准备好等待传送  
  133.         Delay5us();   
  134.         SCL = 1;  
  135.         Delay5us();  
  136.         liVal <<= 1;  
  137.     }   
  138.     SCL = 0;   
  139.     Delay5us();   
  140.     SDA = 1;  
  141. }  
  142. /* 
  143. 读取一个字节并把读到的值返回 
  144. */  
  145. uChar8 IICReadOneByte(void)  
  146. {  
  147.     uChar8 li,liVal;  
  148.     SCL = 0;  
  149.     SDA = 1;  
  150.     for(li=0;li<8;li++)  
  151.     {  
  152.         liVal <<= 1;  
  153.         SCL = 0;  
  154.         Delay5us();  
  155.         SCL = 1;  
  156.         Delay5us();  
  157.         liVal = (liVal|SDA);  
  158.     }  
  159.     SCL = 0;   
  160.     return liVal;  
  161. }     
  162. //Regulate控制器,这里写控制函数  
  163. void PCF8591WriteRegulate(uChar8 lREGVal)  
  164. {  
  165.     IICStart();  
  166.     IICWriteOneByte(PCF8591Add);    //PCF8591的地址,写控制  
  167.     IICReadAck();  
  168.     IICWriteOneByte(lREGVal);       //写入控制字  
  169.     IICReadAck();  
  170.     IICStop();  
  171. }     
  172. uChar8  ReadDataPCF8591(void)  
  173. {  
  174.     uChar8 liVal;  
  175.     IICStart();  
  176.     IICWriteOneByte(PCF8591Add|0x01);   //PCF8591的地址,读控制      
  177.     liVal = IICReadOneByte();  
  178.     IICAck();  
  179.     IICStop();  
  180.     return liVal;     
  181. }   
  182. </span>  

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章