zzzkkkyyy1 发表于 2010-10-2 15:31:48

pcf8591AD转换代码

#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={0x00,0x00,0x00};//ASCII码存放数组
Uchar data Buffer;//四路数据的缓存器
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 idatai=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=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=Buffer/51+'0';//整数部分,相当于Buffer/51+0x30
    Tmp=Buffer%51*10;// 第一位小数
    Dis=Tmp/51+'0';//第二位小数
    Tmp=Tmp%51*10;
    Dis=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);
}
voidDisplay_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路输入信号转化为ASCII码
       LCD_Line_1=Dis;
       LCD_Line_1=Dis;
   LCD_Line_1=Dis;

          AD_Convert(Buffer);
       LCD_Line_1=Dis;
       LCD_Line_1=Dis;
   LCD_Line_1=Dis;

          AD_Convert(Buffer);
       LCD_Line_2=Dis;
       LCD_Line_2=Dis;
   LCD_Line_2=Dis;

       AD_Convert(Buffer);
       LCD_Line_2=Dis;
       LCD_Line_2=Dis;
   LCD_Line_2=Dis;

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

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

wheneverGCC 发表于 2011-12-21 11:13:45

顶,写得很详细

changqing 发表于 2012-8-26 12:38:16

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

        temp = (uint16)value1;
        temp = temp * 100 / 51;
        showBuffer = 0;
        showBuffer = temp / 100;
        showBuffer = temp % 100 / 10;
        showBuffer = temp % 10;
页: [1]
查看完整版本: pcf8591AD转换代码