这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » AD转换芯片PCF8591驱动的一个问题

共3条 1/1 1 跳转至

AD转换芯片PCF8591驱动的一个问题

菜鸟
2014-05-23 21:15:15     打赏
俺的51开发板上的AD芯片是PCF8591,IIC总线的,想将AD转换的值实时显示在数码管上,同时还想利用LED灯亮度的变换来反映DA效果。结果数码管值总是不变化,LED灯也不亮,请大家帮忙找找问题,下面上图上代码
#include 
#include 
sbit SDA=P2^0;
sbit SCL=P2^1;
sbit DU=P2^6;
sbit WE=P2^7;
#define uchar unsigned char
#define uint  unsigned int
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
                        0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void delayms(uchar ms)
{
	uchar i;
	while(ms--)
	{
		for(i=0;i<120;i++);
	}
}
void display(uint k)
{
	P0=table[k/1000];
	DU=1;
	DU=0;
	P0=0xfb;
	WE=1;
	WE=0;
	delayms(1);
	
	P0=table[k%1000/100];
	DU=1;
	DU=0;
	P0=0xf7;
	WE=1;
	WE=0;
	delayms(1);
	
	P0=table[k%100/10];
	DU=1;
	DU=0;
	P0=0xef;
	WE=1;
	WE=0;
	delayms(1);
	
	P0=table[k%10];
	DU=1;
	DU=0;
	P0=0xdf;
	WE=1;
	WE=0;
	delayms(1);
}
void delayus(void)
{
	_nop_();_nop_();
	_nop_();_nop_();
	_nop_();_nop_();
	_nop_();_nop_();
}

void IIC_Start(void)
{
	SDA=1;
	delayus();
	SCL=1;
	delayus();
	SDA=0;
	delayus();
}
void IIC_Stop(void)
{
	SDA=0;
	delayus();
	SCL=1;
	delayus();
	SDA=1;
	delayus();
}
void IIC_Ack(void)
{
	uchar i=0;
	SCL=1;
	delayus();
	while((SDA==1)&&(i<250))
	{
		i++;
	}
	SCL=0;
	delayus();
}
void IIC_NoAck(void)
{
	SDA=1;
	delayus();
	SCL=1;
	delayus();
	SCL=0;
	delayus();
}
void IIC_WriteOneByte(uchar dat)
{
	uchar i;
	for(i=0;i<8;i++)
	{
		SCL=0;
		delayus();
		if(dat&0x80)
		{
			SDA=1;
		}
		else
		{
			SDA=0;
		}
		dat=dat<<1;
		SCL=1;
		delayus();
	}
	SCL=0;
	delayus();
	SDA=1;
	delayus();
}
uchar IIC_ReadOneByte(void)
{
	uchar i,dat;
	SCL=0;
	delayus();
	SDA=1;
	delayus();
	for(i=0;i<8;i++)
	{
		SCL=1;
		delayus();
		dat<<=1;
		dat|=(uchar)SDA;
		SCL=0;
		delayus();
	}
	return dat;
}
void DAC(uchar dat)
{
	IIC_Start();
	IIC_WriteOneByte(0x90);
	IIC_Ack();
	IIC_WriteOneByte(0x40);
	IIC_Ack();
	IIC_WriteOneByte(dat);
	IIC_Ack();
	IIC_Stop();
}
uchar ReadADC(unsigned char Chl)
	  {
       unsigned char Data;
		   IIC_Start();        //写入芯片地址
		   //Send(AddWr);
			IIC_WriteOneByte(0x90);
		   IIC_Ack();
 		   IIC_WriteOneByte(0x40|Chl);//写入选择的通道,本程序只用单端输入,差分部分需要自行添加
		                  //Chl的值分别为0、1、2、3,分别代表1-4通道
		   IIC_Ack();
		   IIC_Start();
		   IIC_WriteOneByte(0X91);    //读入地址
		   IIC_Ack();
		   Data=IIC_ReadOneByte();    //读数据
		   SCL=0;
		   IIC_NoAck();
		   IIC_Stop();
		   return Data;   //返回值
	  }
		
void main()
{
	uchar temp,ad;
	DAC(temp);
	while(1)
	{
		ad=ReadADC(2);
		display(ad);
	}
}

 


高工
2014-05-25 11:15:00     打赏
2楼
代码还没有看,从描述上猜猜,I2C总线没通,楼主看一下

高工
2014-05-25 11:27:19     打赏
3楼

楼主,这有个I2C驱动,你看看


/*************************此部分为I2C总线的驱动程序*************************************/

#include<reg52.h>
#include <intrins.h>
#include <I2C.H>

#define  NOP()   _nop_()   /* 定义空指令 */
#define  _Nop()  _nop_()   /*定义空指令*/

 
sbit     SCL=P2^1;       //I2C  时钟
sbit     SDA=P2^0;       //I2C  数据
bit ack;                 /*应答标志位*/
  

/*******************************************************************
                     起动总线函数              
函数原型: void  Start_I2c(); 
功能:     启动I2C总线,即发送I2C起始条件. 
********************************************************************/
void Start_I2c()
{
  SDA=1;         /*发送起始条件的数据信号*/
  _Nop();
  SCL=1;
  _Nop();        /*起始条件建立时间大于4.7us,延时*/
  _Nop();
  _Nop();
  _Nop();
  _Nop();   
  SDA=0;         /*发送起始信号*/
  _Nop();        /* 起始条件锁定时间大于4μs*/
  _Nop();
  _Nop();
  _Nop();
  _Nop();      
  SCL=0;       /*钳住I2C总线,准备发送或接收数据 */
  _Nop();
  _Nop();
}

/*******************************************************************
                      结束总线函数              
函数原型: void  Stop_I2c(); 
功能:     结束I2C总线,即发送I2C结束条件. 
********************************************************************/
void Stop_I2c()
{
  SDA=0;      /*发送结束条件的数据信号*/
  _Nop();       /*发送结束条件的时钟信号*/
  SCL=1;      /*结束条件建立时间大于4μs*/
  _Nop();
  _Nop();
  _Nop();
  _Nop();
  _Nop();
  SDA=1;      /*发送I2C总线结束信号*/
  _Nop();
  _Nop();
  _Nop();
  _Nop();
}

/*******************************************************************
                 字节数据发送函数              
函数原型: void  SendByte(UCHAR c);
功能:     将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
          此状态位进行操作.(不应答或非应答都使ack=0)    
           发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
********************************************************************/
void  SendByte(unsigned char  c)
{
 unsigned char  BitCnt;
 
 for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8位*/
    {
     if((c<<BitCnt)&0x80)SDA=1;   /*判断发送位*/
       else  SDA=0;               
     _Nop();
     SCL=1;               /*置时钟线为高,通知被控器开始接收数据位*/
      _Nop();
      _Nop();             /*保证时钟高电平周期大于4μs*/
      _Nop();
      _Nop();
      _Nop();        
     SCL=0;
    }
   
    _Nop();
    _Nop();
    SDA=1;                /*8位发送完后释放数据线,准备接收应答位*/
    _Nop();
    _Nop();  
    SCL=1;
    _Nop();
    _Nop();
    _Nop();
    if(SDA==1)ack=0;    
       else ack=1;        /*判断是否接收到应答信号*/
    SCL=0;
    _Nop();
    _Nop();
}

/*******************************************************************
                 字节数据接收函数              
函数原型: UCHAR  RcvByte();
功能:        用来接收从器件传来的数据,并判断总线错误(不发应答信号),
          发完后请用应答函数应答从机。 
********************************************************************/   
unsigned char   RcvByte()
{
  unsigned char  retc;
  unsigned char  BitCnt;
 
  retc=0;
  SDA=1;                     /*置数据线为输入方式*/
  for(BitCnt=0;BitCnt<8;BitCnt++)
      {
        _Nop();          
        SCL=0;                  /*置时钟线为低,准备接收数据位*/
        _Nop();
        _Nop();                 /*时钟低电平周期大于4.7μs*/
        _Nop();
        _Nop();
        _Nop();
        SCL=1;                  /*置时钟线为高使数据线上数据有效*/
        _Nop();
        _Nop();
        retc=retc<<1;
        if(SDA==1)retc=retc+1;  /*读数据位,接收的数据位放入retc中 */
        _Nop();
        _Nop();
      }
  SCL=0;   
  _Nop();
  _Nop();
  return(retc);
}

/********************************************************************
                     应答子函数
函数原型:  void Ack_I2c(bit a);
功能:      主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)
********************************************************************/
void Ack_I2c(bit a)
{
 
  if(a==0)SDA=0;              /*在此发出应答或非应答信号 */
  else SDA=1;
  _Nop();
  _Nop();
  _Nop();     
  SCL=1;
  _Nop();
  _Nop();                    /*时钟低电平周期大于4μs*/
  _Nop();
  _Nop();
  _Nop(); 
  SCL=0;                     /*清时钟线,钳住I2C总线以便继续接收*/
  _Nop();
  _Nop();   
}

 


 

 


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]