搜索
bottom↓
回复: 2

pcf8591AD转换代码

[复制链接]

出0入0汤圆

发表于 2010-10-2 15:31:48 | 显示全部楼层 |阅读模式
#include<reg52.h>
#include<intrins.h>
#define Uchar unsigned char
#define Uint unsigned int
#define Dalay(); {_nop_();_nop_();_nop_();_nop_();};//延时函数
#define Num 4
Uint data Dis[3]={0x00,0x00,0x00};//ASCII码存放数组
Uchar data Buffer[Num];//四路数据的缓存器
Uchar LCD_Line_1[]={"1- .  V 2- .  V "};//第一行显示字符
Uchar LCD_Line_2[]={"3- .  V 4- .  V "};//第二行显示字符
bit   askflag;
bit   bdata IIC_Error;                //从机错误标志位
sbit SCL=P1^2;
sbit SDA=P1^3;
/*************************************
   IIC总线启动子函数
**************************************/
void IIC_Start(void)
{
  SDA=1;
  SCL=1;
  Dalay();
  SDA=0;
  Dalay();
  SCL=0;
}
/*************************************
   IIC总线关闭子函数
**************************************/
void IIC_Stop()
{

  SCL=1;
  SDA=0;
  Dalay();
  SDA=1;
  Dalay();
  SCL=0;
}
/*************************************
   IIC从机响应
**************************************/
void Slav_Ack()
{
  SDA=0;
  SCL=1;
  Dalay();
  SCL=0;

}
/*************************************
   IIC从机非响应函数
**************************************/
void Slav_Noack()
{
   SDA=1;
   SCL=1;
   Dalay();
   SCL=0;
   SDA=0;
}
/*************************************
   延时函数:延时n毫秒
   参数入口:Ms
**************************************/
void DalaynMs(int Ms)       
{
   
   while(Ms--)
        {
      Uchar i;
          for(i=0;i<250;i++)  
           {
            _nop_();                          
                _nop_();
                _nop_();
                _nop_();
           }
        }
}
/*************************************
   IIC发送一个字节数据的子函数
   参数入口:dat
**************************************/
void IIC_Sendbyte(Uchar dat)
{
   Uchar idata  i=8;
   while(i--)
   {
             SDA=(bit)(dat&0x80);//强制转换为bit,将dat最高位送至SDA
          SCL=1;
          Dalay();
          SCL=0;//在SCL下降沿将数据读走
          dat<<=1;//左移一位,为下次读取最高位做好准备
   }
   Dalay();
   SDA=1; // 此处为检测响应
   SCL=1;        //将SDA和SCL拉高
   Dalay();         //若无响应则IIC_Error为1,反正为零
   if(SDA==1)
    IIC_Error=1;
        else
        IIC_Error=0;
        SCL=0;
   
}
/*************************************
   IIC接收一个字节数据的子函数
   返回参数:dat
**************************************/
Uchar IIC_Revbyte()
{
   Uchar i=8,dat;
   while(i--)
   {
      SDA=1;//此处一定要先将SDA拉高
          SCL=1;
          dat<<=1;
          dat|=SDA;
          Dalay();
          SCL=0;//下降沿读走数据
        }
return dat;
  Dalay();
}
/*************************************
  pcf8591进行AD转换
   参数入口:control控制字
**************************************/
void ADC_PCF8591(Uchar control)
{
  Uchar i,Temp;
  IIC_Start();
  IIC_Sendbyte(0x90); // 写入器件地址并声明下一步为写操作
  if(IIC_Error==1)return;//检测响应,若无响应则出错返回
  IIC_Sendbyte(control);
  if(IIC_Error==1)return;
   IIC_Start();
  IIC_Sendbyte(0x91);//写入器件地址并声明下一步为读操作
   if(IIC_Error==1)return;
  IIC_Revbyte();//先空读一个字节,此时读得的字节为上一次AD转换数据,这样就可以在以下的while循环中读得实时转换数据了
  Slav_Ack();//每读一个字节,器件产生一个应答
  while(i<4)
  {
    Temp=IIC_Revbyte();
         Buffer[i++]=Temp;
         Slav_Ack();
  }
  Slav_Noack();
  IIC_Stop();
}
/*************************************
  pcf8591进行DA转换
   参数入口:control控制字,dat数据字
**************************************/
void DAC_PCF8591(Uchar control,Uchar dat)
{
     IIC_Start();Dalay();
        IIC_Sendbyte(0x90);
     if(IIC_Error==1)return;
    IIC_Sendbyte(control);
   if(IIC_Error==1)return;
        IIC_Sendbyte(dat); //对pcf8591进行写操作时,第三个字节数据便是需要DA转换的数据
   if(IIC_Error==1)return;
        IIC_Stop();
          Dalay();
}
/********************
  将读出的16进制AD转换值转化为ASCII码
************************/
AD_Convert(Uchar Buffer )
{
   
    Uchar Tmp; //最大值为255,对应5V,255/5=51
    Dis[2]=Buffer/51+'0';//整数部分,相当于Buffer/51+0x30
    Tmp=Buffer%51*10;// 第一位小数
    Dis[1]=Tmp/51+'0';//第二位小数
    Tmp=Tmp%51*10;
    Dis[0]=Tmp/51+'0'; //第三位小数

       
}
/**********************
以下是对1602液晶操作
**************/
sbit Rs=P2^0;
sbit Rw=P2^1;
sbit e=P2^2;
/*************************
    1602液晶忙碌检测
*************************/
bit LCD_Busy_Check()
{
bit Result;
Rs=0;Rw=1;
e=1;Dalay();Result=(bit)(P0&0x80);
e=0;
return (Result);
}

void Write_Com(Uchar dat) //LCD写入指令
{
    while(LCD_Busy_Check());
    Rs=0;
        _nop_();
        Rw=0;
   _nop_();
        e=0;
        _nop_();
        P0=dat;
    Dalay();
    e=1;
    Dalay();
        e=0;

}
void Write_Data(Uchar dat) //LCD写入数据
{
   while(LCD_Busy_Check());
    Rs=1;
        _nop_();
        Rw=0;
   _nop_();
        e=1;
        _nop_();
        P0=dat;
   Dalay();
    e=1;
    Dalay();
        e=0;
}
void Lcd_pos(Uchar dat)//光标指示的地址
{
  Write_Com(0x80|dat);
}
void  Display_line(Uchar pos,Uchar s[])        //整行显示
{
   Uchar i;
   Lcd_pos(pos);
   for(i=0;i<16;i++)
   Write_Data(s);
}
void Init_1602()//1602初始化
{
  Write_Com(0x38);
  DalaynMs(5);
  Write_Com(0x38);
  DalaynMs(5);
  Write_Com(0x0c);
  DalaynMs(5);
  Write_Com(0x01);
  DalaynMs(5);
  Write_Com(0x06);
  DalaynMs(5);
}
void main()
{

  Init_1602();
  DalaynMs(5);
   while(1)
  {          
   
     ADC_PCF8591(0x04);
     AD_Convert(Buffer[0]);        //将0路输入信号转化为ASCII码
         LCD_Line_1[2]=Dis[2];
         LCD_Line_1[4]=Dis[1];
     LCD_Line_1[5]=Dis[0];

          AD_Convert(Buffer[1]);
         LCD_Line_1[10]=Dis[2];
         LCD_Line_1[12]=Dis[1];
     LCD_Line_1[13]=Dis[0];

          AD_Convert(Buffer[2]);
         LCD_Line_2[2]=Dis[2];
         LCD_Line_2[4]=Dis[1];
     LCD_Line_2[5]=Dis[0];

         AD_Convert(Buffer[3]);
         LCD_Line_2[10]=Dis[2];
         LCD_Line_2[12]=Dis[1];
     LCD_Line_2[13]=Dis[0];

         Display_line(0x00,LCD_Line_1); //显示第一行
         Display_line(0x40,LCD_Line_2); //显示第二行

         DAC_PCF8591(0x40,Buffer[0]); //将四路DA转换全部打开,也可只打开其中几路或一路
         DAC_PCF8591(0x40,Buffer[1]); //
         DAC_PCF8591(0x40,Buffer[2]); //
         DAC_PCF8591(0x40,Buffer[3]);
         
    }   
     
      
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2011-12-21 11:13:45 | 显示全部楼层
顶,写得很详细

出0入0汤圆

发表于 2012-8-26 12:38:16 | 显示全部楼层
楼主的寄存器转化貌似有问题,虽然原理上没看出什么错误,但我这样转化后,小数点后第一位(十分位)上的数字随电压增大,并不是单调增大的,还可能会减小;我是直接数码管显示的,转化程序这样:
uint16 temp = (uint16)value0;
        temp = temp * 100 / 51;
        showBuffer[0] = 0;
        showBuffer[1] = temp / 100;  
        showBuffer[2] = temp % 100 / 10;
        showBuffer[3] = temp % 10;

        temp = (uint16)value1;
        temp = temp * 100 / 51;
        showBuffer[4] = 0;
        showBuffer[5] = temp / 100;  
        showBuffer[6] = temp % 100 / 10;
        showBuffer[7] = temp % 10;
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 00:24

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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