.H file preprocessing
typedef unsigned char INT8U; //0~255
typedef signed char INT8S; //-128~127
typedef unsigned int INT16U; //0~65535
typedef signed int INT16S; //-32768~32767
typedef unsigned long INT32U; //0~0xFFFFFFFF
typedef signed long INT32S; //0x8000 0000~7FFFFFFF
typedef float FP32; //Single precision floating point
typedef double FP64; //Double precision floating point
#define XTAL 1 //Crystal frequency, unit MHz
#define m_delayus(x) __delay_cycles((unsigned long)(x*XTAL))
#define m_delayms(x) __delay_cycles((unsigned long)(x*XTAL*1000UL))
#define m_delays(x) __delay_cycles((unsigned long)(x*XTAL*1000000UL))
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80
//Assume SCL is port PD6, SDA is port PD7, WP is port PD5
#define m_EnE2pWrite PORTD&=~BIT5 //Allow EEPROM to read and write
#define m_DiE2pWrite PORTD|=BIT5 //EEPROM read only
#define m_I2CWritePort DDRD|=BIT7 //When I2C writes, the SDA port direction is output
#define m_I2CReadPort DDRD&=~BIT7 //When I2C reads, the SDA port direction is input
#define m_SetSCL PORTD|=BIT6 //PD6=1, SCL set
#define m_ClrSCL PORTD&=~BIT6 //PD6=0, SCL cleared to 0
#define m_SetSDA PORTD|=BIT7 //PD7=1,SDA set
#define m_ClrSDA PORTD&=~BIT7 //PD7=0, SDA is cleared to 0
#define m_SDAIn (PIND&BIT7) //SDA read in
#define m_I2C_Delay m_delayus(5) //I2C delay, different devices may have different
#define m_I2C_StopDelay m_delayms(10) //Bus idle time before next Start is generated
void I2C_Start(); //Generate the start state of the I2C bus
void I2C_Write(INT8U dat); //Write 1 byte of data to the I2C bus
INT8U I2C_Read(); //Read 1 byte of data from the slave
INT8U I2C_GetAck(); //Read the slave response bit
void I2C_PutAck(INT8U ack); //The host generates an acknowledge bit or a non-acknowledge bit
void I2C_Stop(); //Generate the stop state of the I2C bus
INT8U I2C_Puts(INT8U SlaveAddr,INT16U SubAddr,INT8U SubMod,INT8U *dat,INT16U Size); //I2C bus integrated sending function, sends multiple bytes of data to the slave
INT8U I2C_Gets(INT8U SlaveAddr,INT16U SubAddr,INT8U SubMod,INT8U *dat,INT16U Size); //I2C bus integrated receiving function, receiving multiple bytes of data from the slave
INT8U I2C_DigitalPot(INT8U SlaveAddr,INT8U dat); //I2C bus digital potentiometer sending program
.C Files
void I2C_Start()
{
m_I2CWritePort; //Port direction is output
m_SetSDA;
m_I2C_Delay;
m_SetSCL;
m_I2C_Delay;
m_ClrSDA;
m_I2C_Delay;
m_ClrSCL;
m_I2C_Delay;
}
void I2C_Write(INT8U dat)
{
m_I2CWritePort; //Port direction is output
for(INT8U t=0;t<8;t++)
{
if ((dat&0x80)!=0)
{
m_SetSDA; //SDA=1
}
else
{
m_ClrSDA; //SDA=0
}
m_I2C_Delay;
dat<<=1;
m_SetSCL; //SCK=1
m_I2C_Delay;
m_ClrSCL; //SCK=0
m_I2C_Delay;
}
}
INT8U I2C_Read()
{
INT8U dat;
m_I2CReadPort; //Port direction is input
for(INT8U t=0;t<8;t++)
{
m_SetSCL; //SCK=1
dat<<=1;
if(m_SDAIn)
{
dat|=0x01;
}
m_ClrSCL; //SCK=0
m_I2C_Delay;
}
return dat;
}
INT8U I2C_GetAck()
{
INT8U ack=0;
m_I2CReadPort; //Port direction is input
//Bus ready, accept response
m_SetSDA;
m_I2C_Delay;
m_SetSCL;
m_I2C_Delay;
if(m_SDAIn!=0)
ack = 1;
m_ClrSCL;
m_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:
The host should generate an acknowledge bit after receiving each byte of data.
After receiving the last byte of data, the host should generate a non-acknowledge bit.
*************************************************** ****************************/
void I2C_PutAck(INT8U ack)
{
m_I2CWritePort; //Port direction is output
if(ack==0)
{
m_ClrSDA;
}
else
{
m_SetSDA;
}
m_I2C_Delay;
m_SetSCL;
m_I2C_Delay;
m_ClrSCL;
m_I2C_Delay;
m_SetSDA;
}
/****************************************************** *******************************
Function: I2C_Stop()
Function: Generate the stop state of the I2C bus
illustrate:
When a rising edge appears on SDA while SCL is at a high level, the I2C bus is stopped.
Regardless of the level of SDA and SCL, this function can always correctly generate the stop state
After this function is executed, the I2C bus is in idle state
*************************************************** ****************************/
void I2C_Stop()
{
m_I2CWritePort; //Port direction is output
m_ClrSDA;
m_I2C_Delay;
m_SetSCL;
m_I2C_Delay;
m_SetSDA;
m_I2C_StopDelay;
}
/****************************************************** *******************************
Function: I2C_Puts()
Function: I2C bus integrated sending function, sending multiple bytes of data to the slave
parameter:
SlaveAddr: slave address (7-bit pure address, excluding read/write bit, 0xxx xxxx)
SubAddr: slave subaddress
SubMod: Subaddress mode, 0 - no subaddress, 1 - single-byte subaddress, 2 - double-byte subaddress
*dat: data to be sent
Size: The number of bytes of data
return:
0: Send successfully
1: An exception occurred during the sending process
illustrate:
This function works well with all common I2C devices, whether or not they have subaddresses.
When the slave has no subaddress, the parameter SubAddr is arbitrary, and SubMod should be 0
*************************************************** ****************************/
INT8U I2C_Puts(INT8U SlaveAddr,INT16U SubAddr,INT8U SubMod,INT8U *dat,INT16U Size)
{
m_EnE2pWrite; //Allow EEPROM to read and write
INT8U a[3];
if (Size==0) return 1; // Check the length, an exception occurred during the receiving process
a[0]=(SlaveAddr<<1); //Prepare slave address
if (SubMod>2) SubMod = 2; //Check sub-address mode
//Determine the sub-address
switch (SubMod)
{
case 0:
break;
case 1:
a[1]=(INT8U)(SubAddr);
break;
case 2:
a[1]=(INT8U)(SubAddr >> 8);
a[2]=(INT8U)(SubAddr);
break;
default:
break;
}
//The master sends the slave address (a[0]), followed by the sub-address (if any) (a[1], a[2])
I2C_Start();
for (INT8U t=0;t<=SubMod;t++)
{
I2C_Write(a[t]);
if (I2C_GetAck())
{
I2C_Stop();
m_DiE2pWrite; //EEPROM read only
return 1;
}
}
//Host sends data
while(Size--)
{
I2C_Write(*dat++);
if (I2C_GetAck())
{
I2C_Stop();
m_DiE2pWrite; //EEPROM read only
return 1;
}
}
//Sending completed, stop I2C bus, and return the result
I2C_Stop();
m_DiE2pWrite; //EEPROM read only
return 0; //Send successfully
}
/****************************************************** *******************************
Function: I2C_Gets()
Function: I2C bus integrated receiving function, receiving multiple bytes of data from the slave
parameter:
SlaveAddr: slave address (7-bit pure address, excluding read/write bit, 0xxx xxxx)
SubAddr: slave subaddress
SubMod: Subaddress mode, 0 - no subaddress, 1 - single-byte subaddress, 2 - double-byte subaddress
*dat: save the received data
Size: The number of bytes of data
return:
0: Received successfully
1: An exception occurred during the receiving process
illustrate:
This function works well with all common I2C devices, whether or not they have subaddresses.
When the slave has no subaddress, the parameter SubAddr is arbitrary, and SubMod should be 0
*************************************************** ****************************/
INT8U I2C_Gets(INT8U SlaveAddr,INT16U SubAddr,INT8U SubMod,INT8U *dat,INT16U Size)
{
m_EnE2pWrite; //Allow EEPROM to read and write
INT8U a[3];
if(Size==0) return 1; //Check the length, an exception occurred during the receiving process
a[0]=(SlaveAddr<<1); //Prepare slave address
if(SubMod>2) SubMod=2; //Check sub-address mode
//If it is a slave with a sub-address, the host must first send the slave address and sub-address
if(SubMod!=0)
{
//Determine the sub-address
if(SubMod==1)
{
a[1]=(INT8U)(SubAddr);
}
else
{
a[1]=(INT8U)(SubAddr>>8);
a[2]=(INT8U)(SubAddr);
}
//Send the slave address write, then send the sub address
I2C_Start();
for(INT8U t=0;t<=SubMod;t++)
{
I2C_Write(a[t]);
if(I2C_GetAck())
{
I2C_Stop();
m_DiE2pWrite; //EEPROM read only
return 1;
}
}
}
//The I2C_Start() here is a repeated start state for the slave with a sub-address
//For a slave without a sub-address, it is a normal starting state
I2C_Start();
//Send slave address to read
I2C_Write(a[0]+1);
if(I2C_GetAck())
{
I2C_Stop();
m_DiE2pWrite; //EEPROM read only
return 1;
}
//Host receives data
while(1)
{
*dat++ = I2C_Read();
if(--Size==0)
{
I2C_PutAck(1);
break;
}
I2C_PutAck(0);
}
//Receiving completed, stop I2C bus, and return the result
I2C_Stop();
m_DiE2pWrite; //EEPROM read only
return 0;
}
/****************************************************** *******************************
Function: I2C_DigitalPot()
Function: I2C bus digital potentiometer sending program
parameter:
SlaveAddr: slave address (7-bit pure address, excluding read/write bit, 0xxx xxxx)
dat: data to be sent
return:
0: Send successfully
1: An exception occurred during the sending process
illustrate:
This function can be well adapted to common digital potentiometers, such as AD5245, AD5241
*************************************************** ****************************/
INT8U I2C_DigitalPot(INT8U SlaveAddr,INT8U dat)
{
I2C_Start();
//The host sends the slave address
I2C_Write(SlaveAddr<<1);
if(I2C_GetAck())
{
I2C_Stop();
return 1;
}
//Host sends control word
I2C_Write(0x00);
if(I2C_GetAck())
{
I2C_Stop();
return 1;
}
//Host sends data
I2C_Write(dat);
if(I2C_GetAck())
{
I2C_Stop();
return 1;
}
//Receiving completed, stop I2C bus, and return the result
I2C_Stop();
return 0;
}
Example:
1. Write EEPROM, slave address 1010 000?, subaddress 0x00 (single byte), send data a (2 bytes)
I2C_Puts (0x50,0, 1, &a, 2);
2. Read EEPROM, slave address 1010 000?, subaddress 0x00 (single byte), receive data b (2 bytes)
I2C_Gets (0x50,0, 1, &b, 2);
3. Write digital potentiometer, address 0101 100?, write data 0xFF
I2C_DigitalPot ( 0x2C, 0xFF);
I2C read and write EEPROM flow chart
Previous article:IAR library file generation and usage
Next article:6. AVR timer/counter 1 --TC1 --input capture mode (capture external event mode)
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- How can LM3447 achieve constant power control?
- 【Nucleo G071 Review】 Final Conclusion
- Differences between CPU and CLA and Error Handling Techniques
- Automobile crankshaft dynamic balance problem-N600
- zstack protocol stack serial port problem
- MY-8188EUS Linux-3.14.52 Test
- MSP430 MCU Development Record (12)
- EEWORLD University Hall----Choosing the latest boost converter and Class D amplifier from Texas Instruments to significantly increase the battery life of the trolley speakers
- Award-winning live broadcast | TI Embedded Live Broadcast Month is waiting for you [Low-power Wi-Fi MCU, Sitara AM57X platform, machine learning]
- SPI settings for msp430f149