📄 i2c.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 + -