找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3724|回复: 1
收起左侧

51单片机PCF8591 AD采集电压0-5v,数码管显示,精确到小数点后3位

[复制链接]
ID:370205 发表于 2018-7-12 14:50 | 显示全部楼层 |阅读模式
这个是我做的课设,虽然不是很高级的程序,但是想分享给那些需要的小伙伴。

单片机源程序如下:
  1. #include<reg52.h>
  2. #include<intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. sbit sda=P2^0;        //I2C串行数据  
  6. sbit scl=P2^1;        ////I2C串行时钟
  7. sbit dula=P2^6;
  8. sbit wela=P2^7;
  9. uchar code table[]={

  10.                 0x3F,  //"0"
  11.                 0x06,  //"1"
  12.                 0x5B,  //"2"
  13.                 0x4F,  //"3"
  14.                 0x66,  //"4"
  15.                 0x6D,  //"5"
  16.                 0x7D,  //"6"
  17.                 0x07,  //"7"
  18.                 0x7F,  //"8"
  19.                 0x6F,  //"9"
  20.                 0x77,  //"A"
  21.                 0x7C,  //"B"
  22.                 0x39,  //"C"
  23.                 0x5E,  //"D"
  24.                 0x79,  //"E"
  25.                 0x71,  //"F"
  26.                          };       
  27. uchar code table1[]={ 0xbf,0x86,0xdb,0xcf,0xe6,0xed };        //带小数点的0-5
  28. void delay()  //5us
  29. {_nop_();}
  30. void delay1(uint z)//1ms
  31. {
  32.         uint x,y;
  33.         for(x=z;x>0;x--)
  34.                 for(y=114;y>0;y--);       
  35. }
  36. void display(uchar value)
  37. {   uchar a,b,c,d;
  38.    
  39.        
  40.     a=value*196/10000; // 个位
  41.         b=value*196/1000%10;  //小数点后一位
  42.         c=value*196/100%10;          //小数点后两位
  43.         d=value*196/10%10;         //小数点后三位

  44.         dula=1;
  45.         P0=table1[a];  //显示带小数点的个位
  46.         dula=0;
  47.         P0=0xff;
  48.         wela=1;
  49.         P0=0xfe;
  50.         wela=0;
  51.         delay1(1);

  52.         dula=1;
  53.         P0=table[b];
  54.         dula=0;
  55.         P0=0xff;
  56.         wela=1;
  57.         P0=0xfd;
  58.         wela=0;
  59.         delay1(1);

  60.         dula=1;
  61.         P0=table[c];
  62.         dula=0;
  63.         P0=0xff;
  64.         wela=1;
  65.         P0=0xfb;
  66.         wela=0;
  67.         delay1(1);

  68.         dula=1;
  69.         P0=table[d];
  70.         dula=0;
  71.         P0=0xff;
  72.         wela=1;
  73.         P0=0xf7;
  74.         wela=0;
  75.         delay1(1);
  76. }
  77. void start()   //I2C起始信号,线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;
  78. {
  79.         scl=1;
  80.         _nop_();
  81.         sda=1;
  82.         delay();
  83.         sda=0;
  84.         delay();
  85.         scl=0;
  86.         _nop_();
  87. }
  88. void stop()        //SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。  
  89. {
  90.         scl=1;
  91.         _nop_();
  92.         sda=0;
  93.         delay();
  94.         sda=1;
  95.         delay();
  96. }
  97. void respons() //I2C主机发送应答
  98. {
  99.         scl=1;//拉高时钟总线 让从机从SDA线上读走 主机的应答信号                  
  100.         _nop_();
  101.         sda=0;//应答为0
  102.         delay();
  103.         scl=0; //释放SDA数据总线。
  104.         _nop_();
  105. }
  106. void norespons()  //I2C检测从机应非答
  107. {
  108.         scl=1;//时钟总线为高电平期间可以读取从机应答信号          
  109.         _nop_();
  110.         sda=1;        //非应答为1
  111.         delay();
  112. }
  113. void init()         //初始化
  114. {
  115.         scl=1;
  116.         _nop_();
  117.         sda=1;
  118.         _nop_();
  119. }
  120. void write_byte(uchar dat)          //I2C发送一个字节         
  121. {
  122.         uchar i,temp;
  123.         temp=dat;
  124.         for(i=0;i<8;i++)
  125.         {
  126.                 scl=0;        //释放sda数据总线
  127.                 _nop_();
  128.                 if((temp&0x80)==0x80)        //1000 0000 高位发送
  129.                         sda=1;         
  130.                 else
  131.                         sda=0;          
  132.                 scl=1; //从机从SDA线上读走信号,就是已发送          
  133.                 _nop_();
  134.                 temp<<=1; //高位移除
  135.         }
  136.         scl=0;
  137.         _nop_();
  138. }
  139. uchar read_byte()           //I2C读一个字节
  140. {
  141.         uchar dat,i;
  142.         sda=1;
  143.         _nop_();
  144.         scl=0;
  145.         _nop_();
  146.         for(i=0;i<8;i++)
  147.         {
  148.                 scl=1; //时钟总线为高电平期间可以读取从机应答信号          
  149.                 _nop_();
  150.                 if(sda)
  151.                         dat|=0x01; //0000 0001         主机读取 高位信号存入dat的低位
  152.                 if(i<7)
  153.                          dat<<=1;        //左移一位,方便下一次读取数据
  154.                 scl=0;
  155.                 _nop_();       
  156.         }
  157.         return dat;
  158. }
  159. void DAC_write(uchar dat)        // DAT,发送给PCF8591转换的数字量
  160. {
  161.         start();          //I2C总线起始
  162.         write_byte(0x90); //发送PCF8591地址加读写方向位0(写)
  163.         respons();                   //发送成功(应答)                 
  164.         write_byte(0x40);  //发送控制字节DAC输出使能
  165.         respons();                   //发送成功(应答)
  166.         write_byte(dat);   //发送数字量交由PCF8591转为模拟量AOUT脚输出                  
  167.         respons();                   //发送成功(应答)
  168.         stop();                          // //I2C总线停止

  169. }
  170. uchar ADC_read(uchar com)
  171. {
  172.         uchar dat;
  173.         dat=com;
  174.         start();
  175.         write_byte(0x90); //地址选择字 10010000 写 ,发送第一字节
  176.         respons();
  177.         write_byte(com);   //发送控制字节
  178.         respons();           //发送应答
  179.         start();
  180.         write_byte(0x91);  //改变读写方向(读)
  181.         respons();
  182.         dat=read_byte();  //把读取的值赋给形参
  183.         norespons();
  184.         stop();
  185.         return dat;
  186. }
  187. void main()
  188. {
  189.         uchar i=0,ad_value;
  190.         init();
  191.         while(1)
  192.         {
  193.                
  194.                 ad_value=ADC_read(0x40);
  195.                
  196.        
  197.                 display(ad_value);
  198.                
  199.                 delay1(1);
  200.         }
  201. }
复制代码

所有资料51hei提供下载:
AD电压采集.zip (16.28 KB, 下载次数: 76)
回复

使用道具 举报

ID:381414 发表于 2018-8-3 10:41 | 显示全部楼层
没有锁存器怎么办呢?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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