【PROTEUS仿真】AT89C51实现PCF8591的AD采样及DA输出

原理图及运行演示

源代码

#include<reg52.h>
#include <stdio.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int

sbit I2C_SCL=P1^7;                            //I2C时钟引脚
sbit I2C_SDA=P1^6;                            //I2C数据输入输出引脚
sbit KEY=P2^0;

unsigned char ADC_Value;
char DispBuf[30];		//用来存放打印的数据

void delay(unsigned int t)
{
    while(t--);
}

串口函数及定义区域
void InitUART(void)
{
    TMOD = 0x20;
    SCON = 0x40;
    TH1 = 0xFD;
    TL1 = TH1;
    PCON = 0x00;
    TR1 = 1;
}

void SendOneByte(unsigned char c)
{
    SBUF = c;
    while(!TI);
    TI = 0;
}

void SendStr(unsigned char *p)
{
    while(*p!= '\0')
    {
        SendOneByte(*p);
        p++;
    }
}

IIC 函数定义区域

#define DELAY()	 {_nop_();_nop_();_nop_();}
#define TRUE	1
#define FALSE	0
char I2CErr=0;

/*--------------------------------------------------------------------
函数名称:I2C Stop
--------------------------------------------------------------------*/
void I2C_Stop(void)
{
    I2C_SCL=0;
    I2C_SDA=0;
    DELAY();
    I2C_SCL=1;
    DELAY();
    I2C_SDA=1;
    //EA=1;
}
/*--------------------------------------------------------------------
函数名称:I2C Wait Ack
--------------------------------------------------------------------*/
char  I2C_WaitAck(void)
{
    unsigned char  times=255;			//避免故障,设定错误次数

    I2C_SDA=1;
    I2C_SCL=1;
    while(I2C_SDA)
    {
        times--;
        if(!times)				//超时值为255
        {
            I2C_Stop();
            I2CErr=TRUE;
            return FALSE;
        }
    }
    I2C_SCL=0;
    I2CErr=FALSE;
    return TRUE;
}
/*--------------------------------------------------------------------
函数名称:I2C Start
--------------------------------------------------------------------*/
void I2C_Start(void)
{
    //EA=0;
    I2C_SDA=1;
    I2C_SCL=1;
    DELAY();
    I2C_SDA=0;
    DELAY();
    I2C_SCL=0;
}
/*--------------------------------------------------------------------
函数名称:I2C Send Ack
--------------------------------------------------------------------*/
void I2C_SendAck(void)
{
    I2C_SDA=0;
    DELAY();
    I2C_SCL=1;
    DELAY();
    I2C_SCL=0;
}
/*--------------------------------------------------------------------
函数名称:I2C Send No Ack
--------------------------------------------------------------------*/
void I2C_SendNoAck(void)
{
    I2C_SDA=1;
    DELAY();
    I2C_SCL=1;
    DELAY();
    I2C_SCL=0;
}
/*--------------------------------------------------------------------
函数名称:I2C发送数据
--------------------------------------------------------------------*/
void I2C_SendByte(unsigned char  dat)
{
    unsigned char  i;

    for(i=0; i<=7; i++)
    {
        if((dat&0x80)==0x80)
            I2C_SDA=1;
        else
            I2C_SDA=0;
        dat<<=1;
        I2C_SCL=1;
        DELAY();
        I2C_SCL=0;
    }
    I2C_WaitAck();
}
/*--------------------------------------------------------------------
函数名称:I2C接收数据
--------------------------------------------------------------------*/
void I2C_RcvDat(unsigned char  *pRdDat)
{
    unsigned char  i;

    I2C_SDA=1;
    for(i=0; i<=7; i++)
    {
        I2C_SCL=1;
        DELAY();
        *pRdDat<<=1;
        *pRdDat|=I2C_SDA;
        I2C_SCL=0;
        DELAY();
    }
}
/*--------------------------------------------------------------------
函数名称:I2C接收数据且不产生应答
--------------------------------------------------------------------*/
void I2C_RcvAckDat(unsigned char  *pRdDat)
{
    I2C_RcvDat(pRdDat);
    I2C_SendAck();
}
/*--------------------------------------------------------------------
函数名称:I2C接收数据且产生应答
--------------------------------------------------------------------*/
void I2C_RcvNAckDat(unsigned char  *pRdDat)
{
    I2C_RcvDat(pRdDat);
    I2C_SendNoAck();
}
/*--------------------------------------------------------------------
函数名称:I2C写器件,写一个数据
--------------------------------------------------------------------*/
void I2C_Write(unsigned char  wrDAdr,unsigned char  wordAdr,unsigned char  dat)
{
    I2C_Start();
    I2C_SendByte(wrDAdr);
    I2C_SendByte(wordAdr);
    I2C_SendByte(dat);
    I2C_Stop();
}

/*--------------------------------------------------------------------
函数名称:I2C读器件,读一个数据
--------------------------------------------------------------------*/
void I2C_Read(unsigned char  wrDAdr,unsigned char  wordAdr,
              unsigned char  rdDAdr,unsigned char  *pRdDat)
{
    unsigned char  i;
    I2C_Start();
    I2C_SendByte(wrDAdr);
    I2C_SendByte(wordAdr);
    I2C_Start();
    I2C_SendByte(rdDAdr);
    I2C_RcvNAckDat(pRdDat+i);
    I2C_Stop();
}

/PCF8591定义
#define WR_DADR		0x90	//write device-address
#define RD_DADR		0x91	//read device-address
#define MODE0 	0x00	//Channel0 = AIN0;
//Channel1 = AIN1;
//Channel2 = AIN2;
//Channel3 = AIN3;
#define MODE1 	0x10	//Channel0 = AIN3-AIN0;
//Channel1 = AIN3-AIN1
//Channel2 = AIN3-AIN2;
#define MODE2 	0x20	//Channel0 = AIN0;
//Channel1 = AIN1;
//Channel2 = AIN3-AIN2;
#define MODE3 	0x30	//Channel0 = AIN1-AIN0;
//Channel1 = AIN3-AIN2;

#define CHNL0 	0		//Using Channel0
#define CHNL1 	1		//Using Channel1
#define CHNL2 	2		//Using Channel2
#define CHNL3 	3		//Using Channel3

#define DAouputEn	0x40


void PCF8591_getAD(unsigned char mode,unsigned char chan,unsigned char *pRdDat)
{
    I2C_Read(WR_DADR,mode|chan,RD_DADR,pRdDat);
}

void PCF8591_setDA(unsigned char val)
{
    I2C_Write(WR_DADR,DAouputEn,val);
}

//主程序
void main()
{
    uchar i;
    InitUART();
    if(KEY==1)
    {
        while(1)
        {
            for(i=0; i<255; i++)
                PCF8591_setDA(i);
            for(i=255; i>0; i--)
                PCF8591_setDA(i);
        }
    }
    else
    {
		PCF8591_getAD(MODE0,CHNL0,&ADC_Value);
		sprintf(DispBuf,"ADC:%d Voltage:%d mV\r\n",(unsigned int)ADC_Value,(unsigned int)196*ADC_Value/10);
		SendStr(DispBuf);
        delay(40000);
    }
}


  • 6
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值