微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 基于AT89s52单片机和PCF8591为基础的数模模数转换

基于AT89s52单片机和PCF8591为基础的数模模数转换

时间:10-02 整理:3721RD 点击:
请教各位高手,怎么是实现52单片机控制PCF8591数模/模数转换芯片?哪位高手前辈用过这个数模转换芯片写过程序,麻烦你能传几个例子程序给我参考下!

我也正在写这个

这个好像用到了I2C总线

正在挣扎中呢

好东东

/*----------------------------------------------
  内容:使用4路AD中的1路检测外部模拟量输入
------------------------------------------------*/  
#include <reg52.h>
#include "intrins.h"               
#define uint unsigned int
#define uchar unsigned char
uchar tempdata[8];
uchar ReadADC(uchar Chl);//读数据函数                        
bit ack;                      //应答标志位
sbit SDA=P2^0;//数据线
sbit SCL=P2^1;//时钟线
sbit duan=P2^2;//数码管段锁存
sbit wei=P2^3; //数码管位锁存
uchar code dula[]=
{
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
};//0-f,
uchar code wela[]=
{
0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,
}; //0-7
/*void delay2(uint t)
{   
while(--t);
}
void delay1(uint t)
{
     
while(t--)
{
     //大致延时1mS
     delay2(500);
}
}*/
void delay5us(void)   //误差 0us
{
    _nop_();  //if Keil,require use intrins.h
}
void delay1(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*------------------------------------------------
                    启动总线
------------------------------------------------*/
void Start_I2c()
{
  SDA=1;   //发送起始条件的数据信号
  SCL=1;
  delay5us(); // 时序必要的延时>5us
  SDA=0;     //发送起始信号,SDA下降沿为起始标志
   delay5us(); //时序必要的延时>4us      
  SCL=0;    //钳住I2C总线,准备发送或接收数据(必不可少)
}
/*----------------------------------------------
                    结束总线
------------------------------------------------*/
void Stop_I2c()
{
  SDA=0;    //发送结束条件的数据信号
  SCL=1;    //结束条件建立时间大于4μ
   delay5us();//SDA上升沿决定结束信号
  SDA=1;    //发送I2C总线结束信号
  SCL=1;
  delay5us();
  SDA=0;
}
/*----------------------------------
   字节数据传送函数              
------------------------------------*/
void  send_byte(uchar byte)
{
uchar i;

for(i=0;i<8;i++)  //要传送的数据长度为8位
    {
     if((byte<<i)&0x80)
         {SDA=1;}   
     else
         {SDA=0;}   //判断发送的8位分别是“0”还是“1”            
     SCL=1;    //置时钟线为高,通知被控器开始接收数据位
       delay5us();//数据只有在SCL高电平时有效         
     SCL=0;//允许数据变化
    }
    SCL=1;
    delay5us();
/*    if(SDA==1) //判断地址后的一位0、1
        {ack=0;}  //决定主机对从机的读写   
    else
        {ack=1;}        
    SCL=0;//允许数据变化 */
}
/*--------------------------------
     字节数据接收函数                 
----------------------------------*/       
uchar rec_byte()
{
  uchar rec=0;
  uchar i;
  for(i=0;i<8;i++)
      {           
        SCL=0;       //置时钟线为低,准备接收数据位
         delay5us();
        SCL=1;       //置时钟线为高使数据线上数据有效
        rec=rec<<1;        //起始rec=0;默认8位全0;只需判断哪一位是1;
        if(SDA==1)rec=rec+1; //读数据位,接收的数据位放入rec中
         delay5us();          //0000 0000;将从最右侧向左逐位判断
      }
  SCL=0;//必不可少,允许数据变化   
  return(rec);
}
/*--------------------------------
     应答子函数
----------------------------------*/
void ack_I2c(void)
{
  SDA=0;     
  SCL=1;
   delay5us();
  SCL=0;                //清时钟线,钳住I2C总线以便继续接收  
// SDA=0;
}
/*--------------------------------
     非应答子函数
----------------------------------*/
void noack_I2c(void)
{
  SDA=1;     
  SCL=1;
   delay5us();
  SCL=0;                //清时钟线,钳住I2C总线以便继续接收  
// SDA=0;
}
/******显示函数*******/
void display()
{
      static uchar i=0;
          
           P0=0;   //清空数据,防止有交替重影
       duan=1;     //段锁存
       duan=0;
       P0=wela[i]; //取位码
       wei=1;     //位锁存
       wei=0;
       P0=tempdata[i]; //取显示数据,段码
       duan=1;     //段锁存
       duan=0;
      
           i++;
       if(i==8)
              i=0;
}
/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
TMOD |= 0x01;          //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响                     
EA=1;            //总中断打开
ET0=1;           //定时器中断打开
TR0=1;           //定时器开关打开
}
/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/
void Timer0() interrupt 1
{
TH0=(65536-1000)/256;                  //重新赋值 2ms
TL0=(65536-1000)%256;
display();
}
/*------------------------------------------------
              主程序
------------------------------------------------*/
void main()
{
uchar num;
Init_Timer0();
while (1)         //主循环
  {  
num=ReadADC(0);//范围:0-3;
tempdata[0]=dula[num/100];//   
tempdata[1]=dula[(num%100)/10];
tempdata[2]=dula[(num%100)%10];
delay1(100);
  }
}
/*------------------------------------------------
             读AD转值程序
输入参数 Chl 表示需要转换的通道,范围从0-3
返回值范围0-255
------------------------------------------------*/
uchar ReadADC(uchar Chl)
{
   uchar Val;
   Start_I2c();            //启动总线
   send_byte(0x90);         //发送器件地址(写0x90)
   ack_I2c();
     //if(ack==0)return(0);        //主机向从机发送数据
   send_byte(0x44|Chl);     //发送器件子地址(命令)
   ack_I2c();
     //if(ack==0)return(0);  //模拟量输入
   Start_I2c();
   send_byte(0x91);//读(0x91)
   ack_I2c();
    //if(ack==0)return(0);
   Val=rec_byte();//将接收到的数据赋给val
   noack_I2c();                 //发送非应答位
   Stop_I2c();                  //结束总线
  return(Val);
}

楼上的好人啊....

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top