【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);
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章