92. /*************************************************************************************
* @fn I2C_WriteByte
* @brief Write 1-byte data to the bus.
* _ _ _ _ _ _
SCL: |_| |_| |_| |_| |_| |_| |__
SDA: DDDDDDDDDDDDDDDDDDDDDD
* @param output_data: The data byte to write on the bus (include R/W bit as D0!)
* @return Response (ACK, acknowledgement)
************************************************************************************/
uint8 I2C_WriteByte(uint8 output_data)
{
uint8 index;
/*---- Begin to send 8-bits data to the bus ----*/
for(index = 0; index < 8; index++)
{
// The last step of I2C_Start() is SCL = HIGH
// The end of this loop is also SCL = HIGH,
// thus the loop is started with SCL = LOW to toggle the clock
SCL = LOW;
delay_time(I2CDELAY);
if(output_data & 0x80) // Check MSB bit
SDA = 1;
else
SDA = 0;
delay_time(I2CDELAY);
output_data <<= 1; // shift the data 1-bit left
SCL = HIGH;
delay_time(I2CDELAY);
}
// The end of above loop is SCL = HIGH
// Thus, here SCL should toggle to LOW
SCL = LOW;
delay_time(I2CDELAY);
/*---- End of sending 8-bits data to the bus ----*/
/*---- Begin to check ACK response ----*/
SDA = HIGH; // SDA = HIGH for Slave
delay_time(I2CDELAY); // to pull it LOW
SCL = HIGH; // Toggle SCL to HIGH
delay_time(I2CDELAY);
if (SDA == 0) { // Slave return ACK bit
SCL = LOW; // Toggle SCL to LOW
delay_time(I2CDELAY);
return(1); // ACK YES
}else{ // Slave return NO ACK bit
SCL = LOW; // Toggle SCL to LOW
delay_time(I2CDELAY);
return(0); // ACK NO
}
/*---- End of checking ACK response ----*/
}
92
93. 93
/*************************************************************************************
* @fn I2C_ReadByte
* @brief Read data from the bus.
* _ _ _ _ _ _
SCL: |_| |_| |_| |_| |_| |_| |__
____________ _____
SDA: |xxx_|
* @param send_ack = 0: No ACK send / send_ack = 1: Send ACK to end data transfer
* @return The read-in data byte
************************************************************************************/
uint8 I2C_ReadByte(uint8 send_ack)
{
uint8 index;
uint8 input_data = 0x00; // Creat a new variable for reading 1-byte data in
// Before reading data, writing address to the bus must be done first.
// The last step of I2C_WriteByte() is SCL = LOW and SDA = HIGH/LOW
// No matter what SDA is, just make it HIGH to get the bus ready
SDA = HIGH;
delay_time(I2CDELAY);
/*---- Begin to read 8-bits data from the bus ----*/
for(index = 0; index < 8; index++) { // 8-bits, Read MSB first
input_data <<= 1; // shift the data 1-bit left
SCL = HIGH; // Toggle SCL to HIGH
delay_time(I2CDELAY);
input_data = input_data | SDA; // Put the read-in bit at LSB
SCL = LOW; // Toggle SCL to LOW
delay_time(I2CDELAY);
}
/*---- End of reading 8-bits data from the bus ----*/
/*---- Begin to return ACK response ----*/
if (send_ack)
SDA = LOW; // ACK on SDA goes LOW if required
else
SDA = HIGH; // otherwise, goes HIGH
/*---- End of returning ACK response ----*/
delay_time(I2CDELAY);
SCL = HIGH;
delay_time(I2CDELAY);
SCL = LOW;
// delay_time(I2CDELAY);
// SDA = HIGH;
// delay_time(I2CDELAY);
return(input_data);
}
94. /***************************************************************************************************
* @fn I2C_Write
* @brief Write data to the register on a specific device.
* (1) Addressing the device
* (2) Addressing the register on that device
* (3) Writing data to that register
* @param I2C_Addr: Slave device address, Reg_Addr: Regiter address, Reg_Data: Data to write-to
* @return None
***************************************************************************************************/
void I2C_Write(uint8 I2C_Addr, uint8 Reg_Addr, uint8 Reg_Data)
{
I2C_Start(); // Start bit
I2C_WriteByte(I2C_Addr); // Slave Address
I2C_WriteByte(Reg_Addr); // Register Address
I2C_WriteByte(Reg_Data); // Register Data
I2C_Stop(); // Stop bit
} /****************************************************************************************
* @fn I2C_Read
* @brief Read data from the register on a specific device.
* @param I2C_Addr: Slave device address, Reg_Addr: Regiter address
* @return Reg_Data: Data to read-in
****************************************************************************************/
uint8 I2C_Read(uint8 I2C_Addr, uint8 Reg_Addr)
{
uint8 Data;
I2C_Start();
I2C_WriteByte(I2C_Addr); // Slave Address
I2C_WriteByte(Reg_Addr); // Locate the register address to read
I2C_Stop(); // Stop bit
I2C_Start();
I2C_Addr = I2C_Addr | 0x01; // Device Address uses 7-bits (A7~A1), A0=1=Read
I2C_WriteByte(I2C_Addr); // Locate the address to read
Data = I2C_ReadByte(0); // Read data and send ACK to end up the transfer
I2C_Stop(); // Stop bit
return(Data);
}
94
95. 95
/**************************************************************************************
* @fn delay_time
* @brief simple delay with a NOP loop
* @param time = 0 ~ 255, the delay time be be around few tens to hundred of us.
* @return None
************************************************************************************/
void delay_time(uint8 delay)
{
uint8 i;
for(i=0; i<delay; i++) { ; }
}
/*************************************************************************************
* @fn delayms
* @brief delay with ms
* @param time = 0 ~ 255, the maximum delay is 255 ms
* @return None
************************************************************************************/
void delayms(uint8 time)
{
uint8 n;
while(time>0)
{
n = 162;
while(n>0) n--;
time --;
}
}