I2C bus protocol program
When I was working on the program, I found Zhou Ligong's program on the Internet. I thought it was pretty good and reprinted it by the way; during use, I must pay attention to timing and time issues.
"i2c.h file"
//I2C bus comprehensive sending function, sending multiple bytes of data to the slave
I2C read and write EEPROM flow chart
bit I2C_Puts(
unsigned char SlaveAddr,
unsigned int SubAddr,
unsigned char SubMod,
char*dat,
unsigned int Size
);
//I2C bus comprehensive receiving function, receives multiple bytes of data from the slave
bit I2C_Gets
(
unsigned char SlaveAddr,
unsigned int SubAddr,
unsigned char SubMod,
char*dat,
unsigned int Size
);
#endif
"i2c.c file"
#include “I2C.h”
//Define delay variables for macro I2C_Delay()
unsigned char I2C_Delay_t;
#define I2C_Delay(){I2C_Delay_t = (I2C_DELAY_VALUE);while (--I2C_Delay_t != 0);}
void I2C_Start()
{
I2C_SDA = 1;I2C_Delay();
I2C_SCL = 1;I2C_Delay();
I2C_SDA = 0;I2C_Delay();
I2C_SCL = 0;I2C_Delay();
}
void I2C_Write(char dat)
{
unsigned char t = 8;
do
{
I2C_SDA = (bit) (dat & 0x80);
dat "《= 1;
I2C_SCL = 1; I2C_Delay();
I2C_SCL = 0; I2C_Delay();
} while ( --t != 0 );
}
char I2C_Read()
{
char dat;
unsigned char t = 8;
I2C_SDA = 1;//Before reading data, SDA should be pulled high
do
{
I2C_SCL = 1;
I2C_Delay();
dat "《= 1;
if (I2C_SDA) dat |= 0x01;
I2C_SCL = 0;
I2C_Delay();
} while ( --t != 0 );
return dat;
}
bit I2C_GetAck()
{
bit ack;
//Bus preparation, accept response
I2C_SDA = 1;I2C_Delay();
I2C_SCL = 1;I2C_Delay();
ack = I2C_SDA;
I2C_SCL = 0;
I2C_Delay();
return ack;
}
/****************************************************** *****************************
Function: I2C_PutAck()
Function: The host generates an acknowledge bit or a non-acknowledge bit
parameter:
ack=0: The host generates an acknowledge bit
ack=1: The host generates a non-acknowledge bit
illustrate:
After receiving each byte of data, the host should generate a response bit
After receiving the last byte of data, the host should generate a non-acknowledge bit
*************************************************** ****************************/
void I2C_PutAck(bit ack)
{
I2C_SDA = ack;I2C_Delay();
I2C_SCL = 1;I2C_Delay();
I2C_SCL = 0;I2C_Delay();
}
/************
Function: I2C_Stop()
Function: Generate the stop state of the I2C bus
illustrate:
Stop the I2C bus when SDA has a rising edge while SCL is high
No matter what level state SDA and SCL are in, this function can always correctly generate the stop state.
After this function is executed, the I2C bus is in an idle state
*************/
void I2C_Stop()
{
unsigned int t = I2C_STOP_WAIT_VALUE;
I2C_SDA = 0;I2C_Delay();
I2C_SCL = 1;I2C_Delay();
I2C_SDA = 1I2C_Delay();
while (--t != 0); //Add a certain delay before generating Start next time
}
/****
Function: I2C_Puts()
Function: I2C bus comprehensive sending function, sending multiple bytes of data to the slave
parameter:
SlaveAddr: Slave address (7-bit pure address, excluding read and write bits)
SubAddr: Subaddress of the slave machine
SubMod: sub-address mode, 0-no sub-address, 1-single-byte sub-address, 2-double-byte sub-address
*dat: data to be sent
Size: number of bytes of data
return:
0: Sent successfully
1: An exception occurred during the sending process
illustrate:
This function works well with all common I2C devices, regardless of whether they have subaddresses or not.
When the slave has no sub-address, the parameter SubAddr is arbitrary, and SubMod should be 0
*****/
bit I2C_Puts
(unsigned char SlaveAddr, unsigned int SubAddr, unsigned char SubMod,
char *dat, unsigned int Size)
{
//Define temporary variables
unsigned char i;
char a[3];
if (Size == 0) return 0;//Check the length
a[0] = (SlaveAddr《《1);//Prepare the slave address
if (SubMod 》 2) SubMod = 2; //Check subaddress mode
//Determine subaddress
switch(SubMod)
{
case 0:
break;
case 1:
a[1] = (char)(SubAddr);
break;
case 2:
a[1] = (char)(SubAddr 》》 8);
a[2] = (char)(SubAddr);
break;
default:
break;
}
//Send the slave address (a[0]), then send the sub-address (if there is a sub-address) (a[1], a[2])
I2C_Start();
for ( i=0; i《=SubMod; i++ )
{
I2C_Write(a[i]);
if(I2C_GetAck())
{
I2C_Stop();
return 1;
}
}
//send data
do
{
I2C_Write(*dat++);
if (I2C_GetAck()) break;
} while ( --Size != 0 );
//After sending, stop the I2C bus and return the result
I2C_Stop();
if(Size==0)
{
return 0;//sent successfully
}
else
{
return 1;//An exception occurred during the sending process
}
}
/******
Function: I2C_Gets()
Function: I2C bus comprehensive receiving function, receiving multiple bytes of data from the slave
parameter:
SlaveAddr: Slave address (7-bit pure address, excluding read and write bits)
SubAddr: Subaddress of the slave machine
SubMod: sub-address mode, 0-no sub-address, 1-single-byte sub-address, 2-double-byte sub-address
*dat: save the received data
Size: number of bytes of data
return:
0: Reception successful
1: An exception occurred during the reception process
illustrate:
This function works well with all common I2C devices, regardless of whether they have subaddresses or not.
When the slave has no sub-address, the parameter SubAddr is arbitrary, and SubMod should be 0
*****/
bit I2C_Gets
(unsigned char SlaveAddr, unsigned int SubAddr, unsigned char SubMod,
char *dat, unsigned int Size)
{
//Define temporary variables
unsigned char i;
char a[3];
if (Size == 0) return 0; //Check the length and receive successfully
a[0] = (SlaveAddr《《1);//Prepare the slave address
if (SubMod 》 2) SubMod = 2; //Check subaddress mode
//If it is a slave with a sub-address, the slave address and sub-address must be sent first
if (SubMod != 0 )
{
//Determine subaddress
if(SubMod==1)
{
a[1] = (char)(SubAddr);
}
else
{
a[1] = (char)(SubAddr 》》 8);
a[2] = (char)(SubAddr);
}
//Send the slave address to write, and then send the sub-address
I2C_Start();
for ( i=0; i《=SubMod; i++ )
{
I2C_Write(a[i]);
if(I2C_GetAck())
{
I2C_Stop();
return 1;
}
}
}
//The I2C_Start() here is a repeated start state for slaves with sub-addresses
//For slaves without subaddresses, it is the normal starting state.
I2C_Start();
//Send slave address to read
I2C_Write(a[0]+1);
if(I2C_GetAck())
{
I2C_Stop();
return 1;
}
//Receive data
for (;;)
{
*dat++ = I2C_Read();
if ( --Size == 0 )
{
I2C_PutAck(1);
break;
}
I2C_PutAck(0);
}
//After receiving, stop the I2C bus and return the result
I2C_Stop();
return 0;
}
Previous article:The structure and working principle of the timing counter of 80C51 microcontroller
Next article:Data acquisition LM12H458 and 80C51 interface circuit - circuit diagrams read every day (153)
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- LPS28DFW driver and related information
- Battery Test Equipment --- Signal Chain
- mini risc mcu source code
- Analysis of the problem that the program cannot run after F28004x online debugging reset
- Share a PD fast charging power deception chip CH224 is very practical
- Alloy sampling resistor series
- TI's Class AB car amplifier chip recommendations
- I am majoring in measurement and control, and am planning to work in the embedded system industry. Could you please tell me if this is the right major for me?
- MSP432E401Y MCU intelligent car speed measurement function
- Motor drive video