……

IIC驱动源码程序---STC89C52实时用PCF8591采集温度LCD显示

一、创建头文件i2c.h代码如下:

#ifndef __I2C_H_
#define __I2C_H_

#include <reg52.h>

sbit SCL=P2^1;
sbit SDA=P2^0;

void I2cStart(); //    I2c启动
void I2cStop(); //    I2c停止
unsigned char I2cSendByte(unsigned char dat);  // I2c发送字节
unsigned char I2cReadByte(); //    I2c读取字节
void I2cAck(unsigned char ackbit); // I2c响应
bit I2cWaitAck(void); // I2c等待响应
void At24c02Write(unsigned char addr,unsigned char dat);
unsigned char At24c02Read(unsigned char addr);

#endif

二、创建编译文件i2c.c代码如下:

#include"i2c.h"

/*******************************************************************************
* 函数名         : Delay10us()
* 函数功能           : 延时10us
* 输入           : 无
* 输出              : 无
*******************************************************************************/

void Delay10us()
{
    unsigned char a,b;
    for(b=1;b>0;b--)
        for(a=2;a>0;a--);

}
/*******************************************************************************
* 函数名         : I2cStart()
* 函数功能         : 起始信号:在SCL时钟信号在高电平期间SDA信号产生一个下降沿
* 输入           : 无
* 输出              : 无
* 备注           : 起始之后SDA和SCL都为0
*******************************************************************************/

void I2cStart()
{
    SDA=1;
    Delay10us();
    SCL=1;
    Delay10us();//建立时间是SDA保持时间>4.7us
    SDA=0;
    Delay10us();//保持时间是>4us
    SCL=0;            
    Delay10us();        
}
/*******************************************************************************
* 函数名         : I2cStop()
* 函数功能         : 终止信号:在SCL时钟信号高电平期间SDA信号产生一个上升沿
* 输入           : 无
* 输出              : 无
* 备注           : 结束之后保持SDA和SCL都为1;表示总线空闲
*******************************************************************************/

void I2cStop()
{
    SDA=0;
    Delay10us();
    SCL=1;
    Delay10us();//建立时间大于4.7us
    SDA=1;
    Delay10us();        
}
/*******************************************************************************
* 函数名         : I2cSendByte(unsigned char dat)
* 函数功能         : 通过I2C发送一个字节。在SCL时钟信号高电平期间,保持发送信号SDA保持稳定
* 输入           : num
* 输出              : 0或1。发送成功返回1,发送失败返回0
* 备注           : 发送完一个字节SCL=0,SDA=1
*******************************************************************************/

void I2cAck(unsigned char ackbit) //当ackbit为1时,表示单片机对从设备发送来数据的应答

{ //当ackbit为0时,表示主机接收了最后一个字节,因此不再应答,结束通信
    if(ackbit)
    {
    SDA = 0;
    }
    else
    {
    SDA = 1;
    }
    Delay10us();
    SCL = 1;
    Delay10us();
    SCL = 0;
    SDA = 1;
    Delay10us();
}

void delay()        //短暂5us延时
{
    ;;
}

void ack()
{
    unsigned char i = 0;
    SCL = 1;
    delay();
    while(SDA == 1 && i < 250)i++;
    SCL = 0;            //SCL=0,SDA可以改变
    delay();
}
    
bit I2cWaitAck(void)
    {
    SDA = 1;
    Delay10us();
    SCL = 1;
    Delay10us();
    if(SDA) //在SCL为高电平期间,因为接收设备未将SDA拉低,所以默认未接收到应答,结束IIC通信
    {
    SCL = 0;
    I2cStop();
    return 0;
    }
    else //接收到应答,返回1,继续下一个数据字节的传输
    {
    SCL = 0;
    return 1;
    }

}

unsigned char I2cSendByte(unsigned char dat)
{
    unsigned char a=0,b=0;//最大255,一个机器周期为1us,最大延时255us。        
    for(a=0;a<8;a++)//要发送8位,从最高位开始
    {
        SDA=dat>>7;     //起始信号之后SCL=0,所以可以直接改变SDA信号
        dat=dat<<1;
        Delay10us();
        SCL=1;
        Delay10us();//建立时间>4.7us
        SCL=0;
        Delay10us();//时间大于4us        
    }
    SDA=1;
    Delay10us();
    SCL=1;
    while(SDA)//等待应答,也就是等待从设备把SDA拉低
    {
        b++;
        if(b>200)     //如果超过2000us没有应答发送失败,或者为非应答,表示接收结束
        {
            SCL=0;
            Delay10us();
            return 0;
        }
    }
    SCL=0;
    Delay10us();
     return 1;        
}
/*******************************************************************************
* 函数名         : I2cReadByte()
* 函数功能           : 使用I2c读取一个字节
* 输入           : 无
* 输出              : dat
* 备注           : 接收完一个字节SCL=0,SDA=1.
*******************************************************************************/

unsigned char I2cReadByte()
{
    unsigned char a=0,dat=0;
    SDA=1;            //起始和发送一个字节之后SCL都是0
    Delay10us();
    for(a=0;a<8;a++)//接收8个字节
    {
        SCL=1;
        Delay10us();
        dat<<=1;
        dat|=SDA;
        Delay10us();
        SCL=0;
        Delay10us();
    }
    return dat;        
}


/*******************************************************************************
* 函数名         : void At24c02Write(unsigned char addr,unsigned char dat)
* 函数功能           : 往24c02的一个地址写入一个数据
* 输入           : 无
* 输出              : 无
*******************************************************************************/

void At24c02Write(unsigned char addr,unsigned char dat)
{
    I2cStart();
    I2cSendByte(0xa0);//发送写器件地址
    I2cSendByte(addr);//发送要写入内存地址
    I2cSendByte(dat);    //发送数据
    I2cStop();
}
/*******************************************************************************
* 函数名         : unsigned char At24c02Read(unsigned char addr)
* 函数功能           : 读取24c02的一个地址的一个数据
* 输入           : 无
* 输出              : 无
*******************************************************************************/

unsigned char At24c02Read(unsigned char addr)
{
    unsigned char dat;
    I2cStart();
    I2cSendByte(0xa0); //发送写器件地址
    I2cSendByte(addr); //发送要读取的地址
    I2cStart();
    I2cSendByte(0xa1); //发送读器件地址
    dat=I2cReadByte(); //读取数据
    I2cStop();
    return dat;    
}

三、主程序见:https://www.cnblogs.com/wlei5206/p/13023977.html

 

posted @ 2020-06-01 11:14  十零  阅读(1371)  评论(0编辑  收藏  举报