⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 softi2c.c

📁 周立功的EasyARM1138互联I2C的例程
💻 C
字号:
/*************************************************************************************************
    SoftI2C.C
    模拟I2C总线程序(主模式,通用)
*************************************************************************************************/


#include  "SoftI2C.H"
#include  "SoftI2C_CFG.H"


/*************************************************************************************************
功能:I2C总线初始化,使总线处于空闲状态
参数:无
返回:无
说明:在main()函数的开始处,应当执行一次本函数
*************************************************************************************************/
void  I2C_Init(void)
{
    I2C_PinEnableSCL();
    I2C_PinEnableSDA();

    I2C_PinTypeOutSCL();
    I2C_PinTypeOutSDA();

    I2C_PinWriteSCL(1);     I2C_TimeDelay();
    I2C_PinWriteSDA(1);     I2C_TimeDelay();
}


/*************************************************************************************************
功能:产生I2C总线的起始条件
参数:无
返回:无
说明:SCL处于高电平期间,当SDA出现下降沿时启动I2C总线
      本函数也用来产生重复起始条件
*************************************************************************************************/
void  I2C_Start(void)
{
    I2C_PinWriteSDA(1);     I2C_TimeDelay();
    I2C_PinWriteSCL(1);     I2C_TimeDelay();
    I2C_PinWriteSDA(0);     I2C_TimeDelay();
    I2C_PinWriteSCL(0);     I2C_TimeDelay();
}


/*************************************************************************************************
功能:向I2C总线写1个字节的数据
参数:dat是要写到总线上的数据
返回:无
*************************************************************************************************/
void  I2C_Write(unsigned char  dat)
{
    unsigned int  t  =  8;

    do
    {
        if ( (dat & 0x80)  ==  0x00 )
        {
            I2C_PinWriteSDA(0);
        }
        else
        {
            I2C_PinWriteSDA(1);
        }

        dat  <<=  1;

        I2C_PinWriteSCL(1);     I2C_TimeDelay();
        I2C_PinWriteSCL(0);     I2C_TimeDelay();
    } while ( --t != 0 );
}


/*************************************************************************************************
功能:从从机读取1个字节的数据
参数:无
返回:读取的1个字节数据
*************************************************************************************************/
unsigned char  I2C_Read(void)
{
    unsigned char  ucData;
    unsigned int   t  =  8;

    I2C_PinTypeInSDA();

    do
    {
        I2C_PinWriteSCL(1);     I2C_TimeDelay();
        ucData <<= 1;
        if ( I2C_PinReadSDA() ) ucData++;
        I2C_PinWriteSCL(0);     I2C_TimeDelay();
    } while ( --t != 0 );

    I2C_PinTypeOutSDA();

    return(ucData);
}


/*************************************************************************************************
功能:读取从机应答位(应答或非应答),用于判断:从机是否成功接收主机数据
参数:无
返回:0-从机应答
      1-从机非应答
说明:从机在收到每一个字节后都要产生应答位,主机如果收到非应答则应当终止传输
*************************************************************************************************/
bool  I2C_GetAck(void)
{
    bool  bAck;

    I2C_PinWriteSDA(1);     I2C_TimeDelay();
    I2C_PinWriteSCL(1);     I2C_TimeDelay();

    I2C_PinTypeInSDA();
    bAck = I2C_PinReadSDA();
    I2C_PinTypeOutSDA();

    I2C_PinWriteSCL(0);     I2C_TimeDelay();

    return(bAck);
}


/*************************************************************************************************
功能:主机产生应答位(应答或非应答),用于通知从机:主机是否成功接收从机数据
参数:Ack = 0:主机应答
      Ack = 1:主机非应答
返回:无
说明:主机在收到每一个字节后都要产生应答,在收到最后一个字节时,应当产生非应答
*************************************************************************************************/
void I2C_PutAck(bool  bAck)
{
    I2C_PinWriteSDA(bAck);      I2C_TimeDelay();
    I2C_PinWriteSCL(1);         I2C_TimeDelay();
    I2C_PinWriteSCL(0);         I2C_TimeDelay();
}


/*************************************************************************************************
功能:产生I2C总线的停止条件
参数:无
返回:无
说明:SCL处于高电平期间,当SDA出现上升沿时停止I2C总线
*************************************************************************************************/
void  I2C_Stop(void)
{
    I2C_PinWriteSDA(0);     I2C_TimeDelay();
    I2C_PinWriteSCL(1);     I2C_TimeDelay();
    I2C_PinWriteSDA(1);     I2C_TimeDelay();
}


/*************************************************************************************************
功能:启动I2C总线收发数据
参数:ucMode    操作模式,决定I2C总线的收发格式,取下列值之一:
                I2C_MODE_RECV     接收模式
                I2C_MODE_SEND     发送模式
                I2C_MODE_SrRECV   带重复起始条件的接收模式
      ucSLA     从机地址
      ucAddr    子地址(在从机内部,寄存器的编址或数据的存储地址)
      pucBuf    发送或接收的数据缓冲区
      uiSize    发送或接收的数据长度(以字节计)
返回:0-正常
      1-异常(无应答)
*************************************************************************************************/
int  I2C_On(unsigned char   ucMode,
            unsigned char   ucSLA,
            unsigned char   ucAddr,
            unsigned char  *pucBuf,
            unsigned int    uiSize)
{
    //  启动I2C总线
    I2C_Start();

    if ( ucMode  !=  I2C_MODE_RECV )                        //  如果不是接收模式
    {
        //  发送SLA+W
        I2C_Write(ucSLA & 0xFE);
        if ( I2C_GetAck() )
        {
            I2C_Stop();
            return(1);
        }

        //  发送子地址
        I2C_Write(ucAddr);
        if ( I2C_GetAck() )
        {
            I2C_Stop();
            return(1);
        }

        if ( ucMode  ==  I2C_MODE_SEND )                    //  如果是发送模式
        {
            //  发送数据
            do
            {
                I2C_Write(*pucBuf++);

                if ( I2C_GetAck() )
                {
                    I2C_Stop();
                    return(1);
                }
            } while ( --uiSize != 0 );

            //  发送完毕,正常结束
            I2C_Stop();
            return(0);
        }
        else
        {
            I2C_Start();                                    //  发送重复起始条件
        }
    }

    //  发送SLA+R
    I2C_Write(ucSLA | 0x01);
    if ( I2C_GetAck() )
    {
        I2C_Stop();
        return(1);
    }

    //  接收数据
    for (;;)
    {
        *pucBuf++ = I2C_Read();

        if ( --uiSize == 0 )
        {
            I2C_PutAck(1);                                  //  接收完最后一个数据时发送NACK
            break;
        }

        I2C_PutAck(0);
    }

    //  接收完毕,正常结束
    I2C_Stop();
    return(0);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -