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

📄 i2c.c

📁 IIC总线的c语言程序
💻 C
字号:
/*
Name:   I2C.h
Date:   2003.10.13
Note:   I2C Bus Basic Functions
*/

#include "Define.h"
#include "Fun.h"

////////////////////////////////////////////////////////////////////////////////
// Sending I2C START condition:
//      a HIGH to LOW transition on the SDA line while SCL is HIGH
// SDA: ________
//              \__________
// SCL: _____________
//                   \_____
void i2c_start(void)
{
    SDA_P = 1;      //4.75
    SCL_P = 1;
    _nop_();                                     // keep the output value stable
    SDA_P = 0;       //0.50
    _nop_();
    SCL_P = 0;
}

////////////////////////////////////////////////////////////////////////////////
// Sending I2C STOP condition:
//      a LOW to HIGH transition on the SDA line while SCL is HIGH
// SDA:             ________
//      ___________/
// SCL:      _______________
//      ____/
void i2c_stop(void)
{
    SDA_P = 0;
    _nop_();
    SCL_P = 1;
    _nop_();
    SDA_P = 1;
}

////////////////////////////////////////////////////////////////////////////////
// Send a BYTE to I2C Bus
// SDA:      _____ _____ _ _ _ _____ _____       ______
//      ____/_____X_____X_ _ _X_____X_____\_____/
// SCL:       __    __          __    __    __
//      _____/  \__/  \__ _ _ _/  \__/  \__/  \________
//             1     2    ...   7     8     ACK
BOOL i2c_tx_byte(BYTE TxData)
{
    BYTE i;
    BOOL ack;

    for(i=0; i<8; i++)
    {
        // Data is transferred with MSB first
        if(TxData & 0x80)
        {
            SDA_P = 1;
        }
        else
        {
            SDA_P = 0;
        }
        TxData <<= 1;
        _nop_();

        // set a SCL clock pulse
        SCL_P = 1;
        _nop_();
        SCL_P = 0;
        _nop_();
    } // end for

    // get ack from slave
    // set SDA = HIGH in order to release the line
    SDA_P = 1;
    _nop_();
    // set a SCL clock pulse
    SCL_P = 1;
    _nop_();
    // get ack
    ack = SDA_P;
    SCL_P = 0;
    _nop_();

    return ack;
}

////////////////////////////////////////////////////////////////////////////////
// receive a byte from I2C BUS
// SDA: ____ _____ _____ _ _ _ _____ _____ ______
//          \_____X_____X_ _ _X_____X_____/
// SCL:       __    __          __    __
//      _____/  \__/  \__ _ _ _/  \__/  \________
//             1     2    ...   7     8
BYTE i2c_rx_byte(void)
{
    BYTE i, RecvData = 0xFF;

   // we will get the MSB first
    for(i=0; i<8; i++)
    {
        // set a SCL clock pulse
        SCL_P = 1;
        _nop_();
        RecvData <<= 1;
        if(SDA_P)
        {
            RecvData |= 0x01;
        }
        SCL_P = 0;
        _nop_();
    }// end for

    return RecvData;
}

////////////////////////////////////////////////////////////////////////////////
// send ack to slave
// Note that ack = "0" while non-ack = "1"
//
// SDA: _________________ not acknowledge
//          \________/    acknowledge
// SCL:        ____
//      ______/    \____
void i2c_tx_ack(BOOL ack)
{
    SDA_P = ack;
    SCL_P = 1;
    _nop_();
    SCL_P = 0;
}

////////////////////////////////////////////////////////////////////////////////
// set a register in a chip use i2c, using Address, Subaddress, and Data
// +---+---------+---+---+------------+---+------+---+---+
// | S | Address | W | A | Subaddress | A | Data | A | P |
// +---+---------+---+---+------------+---+------+---+---+
//     |<- 8 bits  ->|   |<- 8 bits ->|   |8 bits|
void i2c_setreg(BYTE Addr, BYTE Subaddr, BYTE aData)
{
    while(1)
    {
        // Start i2c
        i2c_start();

        // send Slave Address with WRITE mark
        if(NACK == i2c_tx_byte((BYTE)(Addr&0xFE)))
        {
            i2c_stop();
            continue;
        }

        // send Slave Subaddress
        if(NACK == i2c_tx_byte((BYTE)Subaddr))
        {
            i2c_stop();
            continue;
        }

        // send Data on i2c
        if(NACK == i2c_tx_byte(aData))
        {
            i2c_stop();
            continue;
        }

        // transmit success, Stop i2c
        i2c_stop();
        break;
    } // end while(1)
}

////////////////////////////////////////////////////////////////////////////////
// set a register in a chip use i2c, using Address, Subaddress, and return data
//+---+---------+---+---+------------+---+----+---------+---+---+------+----+--+
//| S | Address | W | A | Subaddress | A | Sr | Address | R | A | Data | NA | P|
//+---+---------+---+---+------------+---+----+---------+---+---+------+----+--+
//    |<- 8 bits  ->|   |<- 8 bits ->|        |<-  8 bits ->|   |8 bits|
BYTE i2c_getreg(BYTE Addr, BYTE Subaddr)
{
    BYTE Recv = 0xFF;

    while(1)
    {
        // Start i2c
        i2c_start();

        // send the Slave Address with the WRITE mark
        if(NACK == i2c_tx_byte((BYTE)(Addr&0xFE)))
        {
            i2c_stop();
            continue;
        }

        // send the Slave Subaddress
        if(NACK == i2c_tx_byte((BYTE)Subaddr))
        {
            i2c_stop();
            continue;
        }

        // Repeat Start i2c
        i2c_start();

        // send the Slave Address with READ mark
        if(NACK == i2c_tx_byte((BYTE)(Addr|0x01)))
        {
            i2c_stop();
            continue;
        }

        // receive 8 bits data
        Recv = i2c_rx_byte();

        // send non-acknowledge singal to end receiver
        i2c_tx_ack(NACK);

        // Stop i2c
        i2c_stop();
        break;
    } // end while(1)

    return Recv;
}

/************************************(EOF)*************************************/

⌨️ 快捷键说明

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