找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2928|回复: 0
收起左侧

分享一个 PCF8591 AD转换文件

[复制链接]
ID:344053 发表于 2018-6-18 13:08 | 显示全部楼层 |阅读模式
用12864显示,AD芯片采用IIC通讯方式,需要用多路时要做小许修改。
  1. #include<reg52.h>
  2. #include<intrins.h>
  3. //P0口为12864数据输出口
  4. #define uchar unsigned char
  5. #define uint unsigned int
  6. #define Delay4us(){_nop_();_nop_();_nop_();_nop_();}

  7. sbit LCD_RS=P2^6;
  8. sbit LCD_RW=P2^5;
  9. sbit LCD_EN=P2^7;

  10. sbit PM=P1^0;
  11. sbit SCL=P1^1; //I2C时钟引脚
  12. sbit SDA=P1^2;//I2C数据输入输出引脚

  13. uchar Recv_Buffer[4];//数据接收缓冲
  14. uint Voltage[]={'0','0','0'};//数据分解为电压x.xx
  15. bit bdata IIC_ERROR; //I2C错误标志位
  16. uchar LCD_Line_1[]={"1- .  V  2- .  V"};
  17. uchar LCD_Line_2[]={"3- .  V  4- .  V"};

  18. //延时
  19. void delay(int ms)
  20. {
  21.         uchar i;
  22.         while(ms--) for(i=0;i<250;i++) Delay4us();
  23. }

  24. //LCD忙检测
  25. bit LCD_Busy_Check()
  26. {
  27.         bit Result;
  28.         LCD_RS=0;LCD_RW=1;
  29.         LCD_EN=1;Delay4us();Result=(bit)(P0&0x80);
  30.         LCD_EN=0;
  31.         return Result;
  32. }

  33. //写指令
  34. void LCD_Write_Command(uchar cmd)
  35. {
  36.         while(LCD_Busy_Check());
  37.         LCD_RS=0;LCD_RW=0;LCD_EN=0;_nop_();_nop_();
  38.         P0=cmd;Delay4us();
  39.         LCD_EN=1;Delay4us();LCD_EN=0;
  40. }

  41. // 写数据
  42. void LCD_Write_Data(uchar dat)
  43. {
  44.         while(LCD_Busy_Check());
  45.         LCD_RS=1;LCD_RW=0;LCD_EN=0;P0=dat;Delay4us();
  46.         LCD_EN=1;Delay4us();LCD_EN=0;
  47. }

  48. //初始化
  49. void LCD_Initialise()
  50. {
  51.         LCD_Write_Command(0x38);delay(5);
  52.         LCD_Write_Command(0x0c);delay(5);
  53.         LCD_Write_Command(0x06);delay(5);
  54.         LCD_Write_Command(0x01);delay(5);
  55. }
  56. //设置显示位置
  57. void LCD_Set_Position(uchar pos)
  58. {
  59.         //LCD_Write_Command(pos|0x80);
  60.         LCD_Write_Command(pos);
  61. }

  62. //显示一行
  63. void LCD_Display_A_Line(uchar Line_Addr,uchar s[])
  64. {
  65.         uchar i;
  66.         LCD_Set_Position(Line_Addr);
  67.         for(i=0;i<16;i++)LCD_Write_Data(s[i]);
  68. }

  69. // 将模数转换后得到的值分解存入缓存
  70. void Convert_To_Voltage(uchar val)
  71. {
  72.         uchar Tmp; //最大值为255,对应5V,255/5=51
  73.         Voltage[2]=val/51+'0';//整数部分
  74.         Tmp=val%51*10;// 第一位小数
  75.         Voltage[1]=Tmp/51+'0';
  76.         Tmp=Tmp%51*10;
  77.         Voltage[0]=Tmp/51+'0';
  78. }

  79. //启动I2C总线
  80. void IIC_Start()
  81. {
  82.         SDA=1;
  83.         SCL=1;
  84.         Delay4us();
  85.         SDA=0;
  86.         Delay4us();
  87.         SCL=0;
  88. }

  89. //停止I2C总线
  90. void IIC_Stop()
  91. {
  92.         SDA=0;
  93.         SCL=1;
  94.         Delay4us();
  95.         SDA=1;
  96.         Delay4us();
  97.         SCL=0;
  98. }

  99. // 从机发送应答位
  100. void Slave_ACK()
  101. {
  102.         SDA=0;
  103.         SCL=1;
  104.         Delay4us();
  105.         SCL=0;
  106.         SDA=1;
  107. }

  108. // 从机发送非应答位
  109. void Slave_NOACK()
  110. {
  111.         SDA=1;
  112.         SCL=1;
  113.         Delay4us();
  114.         SCL=0;
  115.         SDA=0;
  116. }

  117. //发送一字节
  118. void IIC_SendByte(uchar wd)
  119. {
  120.         uchar i;
  121.         for(i=0;i<8;i++) //循环移入8位
  122.         {
  123.                 SDA=(bit)(wd&0x80);_nop_();_nop_();
  124.                 SCL=1;Delay4us();SCL=0;wd<<=1;
  125.         }
  126.         Delay4us();
  127.         SDA=1; //释放总线并准备读取应答
  128.         SCL=1;
  129.         Delay4us();
  130.         IIC_ERROR=SDA;//IIC_ERROR=1表示无应答
  131.         SCL=0;
  132.         Delay4us();
  133. }

  134. //接收一字节
  135. uchar IIC_ReceiveByte()
  136. {
  137.         uchar i,rd=0x00;
  138.         for(i=0;i<8;i++)
  139.         {
  140.                 SCL=1;
  141.                 rd<<=1;
  142.                 rd|=SDA;
  143.                 Delay4us();
  144.                 SCL=0;
  145.                 Delay4us();
  146.         }
  147.         SCL=0;
  148.         Delay4us();
  149.         return rd;
  150. }

  151. //连续读入4路通道的A/D转换结果并保存到Recv_Buffer
  152. void ADC_PCF8591(uchar CtrlByte)
  153. {
  154.         uchar i;
  155.         IIC_Start();
  156.         //PCF8591地址定义1001****,高四位固定1001
  157.         //第3,2,1位对应A2,A1,A0第0位为读写标志位,1为读0为写
  158.         //下面代码中0x90,0x91分别为10010000,10010001
  159.         
  160.         IIC_SendByte(0x90);// 发送写地址
  161.         if(IIC_ERROR==1)return;
  162.         // IIC_SendByte(CtrlByte);//发送控制字节
  163.         //if(IIC_ERROR==1)return;
  164.         //屏蔽上面两行会产生警告
  165.         IIC_Start();//重新发送开始命令
  166.         IIC_SendByte(0x91);// 发送读地址
  167.         if(IIC_ERROR==1)return;
  168.         IIC_ReceiveByte();//空读一次,调整读顺序
  169.         Slave_ACK(); //收到一字节后发送一个应答位
  170.         /*------------------------------
  171.         个人认为下面句子有问题,但是不知道怎么改,如果把
  172.         Recv_Buffer[i++]=IIC_ReceiveByte();中的++去掉,整个四组都是一个结果
  173.         但是加上好像有些重复,并且13组相同,还是不很好啊
  174.         */
  175.         for(i=0;i<4;i++)
  176.         {
  177.                 Recv_Buffer[i++]=IIC_ReceiveByte();
  178.                 Slave_ACK();//收到一个字节后发送一个应答位
  179.         }
  180.         Slave_NOACK();
  181.         IIC_Stop();//收到一个字节后发送一个非应答位
  182. }

  183. // 向 PCF8591发送1字节进行AD转换
  184. void DAC_PCF8591(uchar CtrlByte,uchar dat)
  185. {
  186.         IIC_Start();
  187.         Delay4us();//启动I2C
  188.         IIC_SendByte(0x90); //发送地址字节
  189.         if(IIC_ERROR==1)return;
  190.         IIC_SendByte(CtrlByte); //发送控制字节
  191.         if(IIC_ERROR==1)return;
  192.         IIC_SendByte(dat);//发送待转换为模拟量的数值
  193.         
  194.         if(IIC_ERROR==1)return;
  195.         IIC_Stop();
  196.         Delay4us();
  197.         Delay4us();
  198. }

  199. void timer0init()
  200. {
  201.         PM=0;//传感器的输入信号
  202.         TMOD=0x11;//设置定时器0为工作方式1
  203.         TH0=(65536-40)/256;
  204.         TL0=(65536-40)%256;
  205.         ET0=1;//开定时器0中断
  206.         TR0=1;//启动定时器0
  207.         EA=0; //开总中断
  208. }
  209. //主程序
  210. /*
  211. PCF8591控制字节定义:0***0***,第3,7位固定为0
  212. 第6位取0时为模拟输入,取1时为模拟输出
  213. 第4,5位为00表示4路单端的模拟输入
  214. 第二位为自动递增标志,取1时自动递增
  215. 第0,1位取值为00,01,10,11分别表示通道0,1,2,3
  216. 调用ADC_PCF8591时参数为00000100,即0x04
  217. 调用DAC_PCF8591时参数为01000000,即0x40
  218. */

  219. void main()
  220. {
  221.         LCD_Initialise();
  222.         timer0init();
  223.         while(1)
  224.         {
  225.                 ADC_PCF8591(0x04);
  226.                 Convert_To_Voltage(Recv_Buffer[0]);
  227.                 LCD_Line_1[2]=Voltage[2];
  228.                 LCD_Line_1[4]=Voltage[1];
  229.                 LCD_Line_1[5]=Voltage[0];
  230.                 Convert_To_Voltage(Recv_Buffer[1]);
  231.                 LCD_Line_1[11]=Voltage[2];
  232.                 LCD_Line_1[13]=Voltage[1];
  233.                 LCD_Line_1[14]=Voltage[0];
  234.                 Convert_To_Voltage(Recv_Buffer[2]);
  235.                 LCD_Line_2[2]=Voltage[2];
  236.                 LCD_Line_2[4]=Voltage[1];
  237.                 LCD_Line_2[5]=Voltage[0];
  238.                 Convert_To_Voltage(Recv_Buffer[3]);
  239.                 LCD_Line_2[11]=Voltage[2];
  240.                 LCD_Line_2[13]=Voltage[1];
  241.                 LCD_Line_2[14]=Voltage[0];
  242.                 // 液晶两行显示四个通道的转换结果
  243.                 LCD_Display_A_Line(0x80, LCD_Line_1);
  244.                 LCD_Display_A_Line(0x90, LCD_Line_2);
  245.                 // 将0通道模拟转换后的数值重新转换为模拟量并从Aout输出
  246.                
  247.                 //通过LED亮度表现出来
  248. //                DAC_PCF8591(0x40,Recv_Buffer[0]);
  249.         }
  250. }

  251. void timer0() interrupt 1
  252. {
  253.    int N;
  254.    TH0=(65536-40)/256;  
  255.    TL0=(65536-40)%256;
  256.    N++;  
  257.    //if(N==7)
  258.    //PM=1;  
  259.    if(N==8)
  260.    PM=0;
  261.    if(N>=250)
  262.    {  
  263.       PM=1;
  264.       N=0;
  265.      }
  266. }


复制代码


pcf8591.zip

2.4 KB, 下载次数: 12, 下载积分: 黑币 -5

主要文件,工程需自建

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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