A few days ago, I was learning STM32's 485 communication. I basically understood the principle and successfully operated it. I will learn more in the future to communicate with the frequency converter to control the 380V motor!
Now I plan to thoroughly understand the I2C bus communication of STM32 - first of all, the reading and writing of AT24C02 - I have the IO expansion chip of PCF8574, which is also I2C protocol, and hope to achieve multiple controls!
STM32's I2C has its own hardware driver, and can also be simulated using GPIO-----First summarize the problems under the hardware driver.
----------------------------------Hardware-----Take AT24C02 and PCF8574 as an example---------------
------The first part is a simple macro definition-------
#define I2C_Speed 300000 //Transmission rate--When there are many original components mounted, the rate needs to be reduced. I have encountered such problems during debugging.
#define I2C1_OWN_ADDRESS7 0x0A //Host custom address--Each device on the bus needs an address---including the host STM32
#define I2C_PageSize 8 // AT24C02 has 8 bytes per page
#define EEP_Firstpage 0x00 //Write start address
#define EEPROM_ADDRESS 0xA0 //AT24C02 slave address--assign value later
#define PCF8574_ADDRESS 0x70 //PCF8574 slave address--assign value later
uint8_t I2c_Buf_Write[256]; //Write cache
uint8_t I2c_Buf_Read[256]; //Read cache
------ The second part is IO---Clock---I2C hardware configuration-------
static void I2C_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
//----Clock-----
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
// -----GPIO settings-----PB6-I2C1_SCL-----PB7-I2C1_SDA----
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // Open drain output
GPIO_Init(GPIOB, &GPIO_InitStructure);
//-- I2C configuration--------------------------
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//Select I2C mode
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//High and low level duty cycle is 2:1
I2C_InitStructure.I2C_OwnAddress1 =I2C1_OWN_ADDRESS7;//Local address
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;//Response allowed
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//Addressing mode is 7 bits---(there is also a 10-bit option)
I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;//Transmission rate 30000--When mounting many components, it is required to reduce the rate. I have encountered such problems during debugging
I2C_Cmd(I2C1, ENABLE); // Enable I2C1
I2C_Init(I2C1, &I2C_InitStructure); //I2C1 initialization
}
------The third part is----I2C writes a byte to AT24C02----I will not study the while loop in detail, but mainly judge whether each step is completed
void I2C_EE_ByteWrite(u8* pBuffer, u8 WriteAddr)
{
u8 i=0;
I2C_GenerateSTART(I2C1, ENABLE); //----(1.)----Generate communication start signalwhile
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
i++;
if(i>100)//Prevent device damage from causing an infinite loop
break;
}
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS,I2C_Direction_Transmitter); //---(2.)---Send address to find a match-- I2C_Direction_Transmitter--Indicates that the data transmission direction is STM32 sending-- I2C_Direction_Receiver--Indicates that the data transmission direction is STM32 receiving
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
i++;
if(i>100)//Prevent device damage from causing an infinite loop
break;
}
I2C_SendData(I2C1, WriteAddr); //---(3.)---Write the start addresswhile
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
i++;
if(i>100)//Prevent device damage from causing an infinite loop
break;
}
I2C_SendData(I2C1, *pBuffer); //---(4.)---Write datawhile
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
i++;
if(i>100)//Prevent device damage from causing an infinite loop
break;
}
I2C_GenerateSTOP(I2C1, ENABLE); //---(5.)---Generate an end signal
}
-----Part 4---I2C writes multiple bytes to AT24C02, but not more than 8 bytes in one page of AT24C02----I will not study the while loop in detail, but mainly judge whether each step is completed
void I2C_EE_PageWrite(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite)
{
u8 i=0;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY))//---(1.)---Detect bus status
{
i++;
if(i>100)
break;
}
I2C_GenerateSTART(I2C1, ENABLE);//---(2.)---Start signalwhile
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
i++;
if(i>100)
break;
}
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter); //---(3.)---Send address addressing matchwhile
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
i++;
if(i>100)
break;
}
I2C_SendData(I2C1, WriteAddr); //---(4.)---Write start addresswhile
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
i++;
if(i>100)
break;
}
while(NumByteToWrite--) //Write in sequence according to the number of writes
{
I2C_SendData(I2C1, *pBuffer); //---(5.)---Write data
pBuffer++;
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
i++;
if(i>100)
break;
}
}
I2C_GenerateSTOP(I2C1, ENABLE);//---(6.)---Generate end signal
}
-----Part 5---I2C reads multiple bytes from AT24C02----We will not study the while loop in detail, but mainly judge whether each step is completedvoid
I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)
{
u8 i=0;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY))//---(1.)---Busy signal
{
i++;
if(i>100)
break;
}
I2C_GenerateSTART(I2C1, ENABLE);//---(2.)---Start signalwhile
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
i++;
if(i>100)
break;
}
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//---(3.)---Address matchingwhile
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
i++;
if(i>100)
break;
}
I2C_Cmd(I2C1, ENABLE);
I2C_SendData(I2C1, ReadAddr); //---(4.)---Read the starting address of the datawhile
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
i++;
if(i>100)
break;
}
I2C_GenerateSTART(I2C1, ENABLE);//---(5.)---Specialty of reading data---Resend the start signalwhile
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
i++;
if(i>100)
break;
}
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver);//---(6.)---Address matchingwhile
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
{
i++;
if(i>100)
break;
}
while(NumByteToRead)
{
if(NumByteToRead == 1)
{
I2C_AcknowledgeConfig(I2C1, DISABLE);//Turn off responseI2C_GenerateSTOP
(I2C1, ENABLE);//Stop signal
}
if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED))
{
*pBuffer = I2C_ReceiveData(I2C1); //---(7.)---Read data in
sequencepBuffer++;
NumByteToRead--;
}
}
I2C_AcknowledgeConfig(I2C1, ENABLE);
}
-----Part 6---I2C writes a byte of data to PCF8574----I will not study the while loop in detail, but mainly judge whether each step is completed
void I2C_PCF8574_ByteWrite(u8 PCF_ADD, u8 WriteData)
{
u8 i=0;
I2C_GenerateSTART(I2C1, ENABLE); //----(1.)----Generate communication start signalwhile
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
{
i++;
if(i>100)
break;
}
i=0;
I2C_Send7bitAddress(I2C1, PCF_ADD, I2C_Direction_Transmitter); //----(2.)----Send address to find a matchwhile
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
i++;
if(i>100)
break;
}
i=0;
I2C_SendData(I2C1, WriteData); //----(3.)----Write data
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
i++;
if(i>100)
break;
}
I2C_GenerateSTOP(I2C1, ENABLE); //----(4.)----Generate stop signal
}
-----Part 7----
int main(void)
{
u8 i,led=0x01;
USART1_Config();
GPIO_Config();
I2C_All_Init();
while (1)
{
led++;
if(led>98)
led=0x01;
I2C_PCF8574_ByteWrite(0x70,led);
Delay(0xffffe);
printf("\r\nRead data\r\n");
I2C_EE_BufferRead(I2c_Buf_Read, 0, 100); //Keep the EEPROM read data in order in I2c_Buf_Read
printf("0x%02X \r\n", I2c_Buf_Read[led]);
printf("0x%02X \r\n ", I2c_Buf_Read[led+1]);
printf("\r\nI2C(AT24C02) read and write test successful\r\n");
Delay(0xffffe);
}
}
---------------------To summarize from the above---------------------
For writing to the I2C bus, pay attention to the following steps
-------(1.)----Detect busy signal----
-------(2.)----Send start signal
-------(3.)----Send address matching signal
-------(4.)----Send or receive data----Sometimes you need to look at the chip manual----For example, AT24C02 interprets the first data sent at this time as the starting address for reading and writing-----but PCF8574 does not, it directly interprets it as data for reading!
-------(5.)----Send bus end signal
For reading the I2C bus, pay attention to the following steps - here we take AT24C02 as an example - simple differences for other chips
-------(1.)----Detect busy signal----
-------(2.)----Send start signal
-------(3.)----Send address matching signal
-------(4.)----Send the starting address of the read
-------(5.)----Resend the start signal
-------(6.)----Resend address matching signal
-------(7.)----Read data in sequence
-------(8.)----Send bus end signal
----------------------------------GPIO software simulation-----Take AT24C02 and PCF8574 as an example------------
----1.----I2C bus GPIO configuration----
static void i2c_CfgGpio(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE);
GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //Open drain output
GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);
i2c_Stop(); //Send a stop signal to reset all devices on the bus
}
----2.----I2C bus start signal----
void i2c_Start(void) //When SCL is high, a falling edge appears on SDA, indicating the start signal of the I2C bus
{
I2C_SDA_1();
I2C_SCL_1();
i2c_Delay();
I2C_SDA_0();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
----3.----I2C bus stop signal----
void i2c_Stop(void) //When SCL is high, a rising edge appears on SDA, indicating the I2C bus stop signal
{
I2C_SDA_0();
I2C_SCL_1();
i2c_Delay();
I2C_SDA_1();
}
----4.----Send 8Bit data to I2C bus----
void i2c_SendByte(uint8_t _ucByte)
{
uint8_t i;
for (i = 0; i < 8; i++) //Send the high bit first
{
if (_ucByte & 0x80)
I2C_SDA_1();
else
I2C_SDA_0();
i2c_Delay();
I2C_SCL_1() ;
i2c_Delay();
I2C_SCL_0();
if (i == 7)
I2C_SDA_1();
_ucByte <<= 1;
i2c_Delay();
}
}
----5.----Read 8Bit data from I2C bus----
uint8_t i2c_ReadByte(void)
{
uint8_t i;
uint8_t value;
value = 0;
for (i = 0; i < 8; i++) //Read the high bit first
{
value <<= 1;
I2C_SCL_1();
i2c_Delay();
if (I2C_SDA_READ())
value++;
I2C_SCL_0();
i2c_Delay();
}
return value;
}
----6.----Generate an ACK signal to I2C----
void i2c_Ack(void)
{
I2C_SDA_0();
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
I2C_SDA_1();
}
----7.----Generate a NACK signal to I2C----
void i2c_NAck(void)
{
I2C_SDA_1();
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
----8.----Detect I2C bus devices, send device addresses, read device responses to determine if a device at this address exists----
uint8_t i2c_CheckDevice(uint8_t _Address)
{
uint8_t ucAck;
i2c_CfgGpio();//Configure GPIO
i2c_Start();//Start signal
i2c_SendByte(_Address | I2C_WR);//Send device address and read/write control--the last bit indicates read/write selection
ucAck = i2c_WaitAck();//Detect response
i2c_Stop();//Send stop signal
return ucAck;
}
----9.---- Here we will not use AT24C02 as an example, because the code is a little more, here we use PCF8574 as an example------
uint8_t I2C_PCF8574_ByteWrite(, uint16_tPCF_ADD,uint8_t *_pWriteBuf)
{
uint16_t i,m;
i2c_Stop();
for (m = 0; m < 100; m++) //Multiple detections---Exit when time exceeds
{
i2c_Start();
i2c_SendByte(PCF_ADD); //Here is the write address instructionif
(i2c_WaitAck() == 0)
break;
}
if (m == 100)
goto cmd_fail;//I2C device fails, no response, jump
i2c_SendByte((uint8_t)_pWriteBuf);
if (i2c_WaitAck() != 0)
goto cmd_fail;//I2C device fails, no response, jump to
i2c_Stop(); //Command execution is successful, send I2C bus stop signalreturn
1;
cmd_fail: //After the command execution fails, remember to send a stop signal to avoid affecting other devices on the I2C busi2c_Stop
(); //Send I2C bus stop signalreturn
0;
}
----10.----Simple call of main function----Control PCF8574 to switch LED light---
int main(void)
{
u8 led=0x00;
USART1_Config();
while(1)
{
led++;
if(led>255)
led=0x00;
I2C_PCF8574_ByteWrite(led,0x70); //Light up different LED lights according to different values of led
}
}
---------------------Summarized as follows----------
The steps are the same, the main thing is to pay attention to stopping the bus signal ---- and detecting the ACK response at all times ---
---------------------------Some pictures---------------------
--------------------------0---------------------------- ----------
--------------------------1----------------------- -----------------------
---------------------------------------------2---- -------------------
--------------------------------3-------------------------------- -------------
Previous article:STM32 MDK project creation diagram steps self-study summary
Next article:STM32 485 communication self-study summary
- Popular Resources
- Popular amplifiers
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
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- ARM supports advanced video graphics capabilities for MCUs
- Why are current and magnetic sensors crucial to TWS (true wireless earphones) design?
- MBD environment construction of TMS320F28335
- MSP430 digital tube display problem
- Ask: How to test the WIFI function of the product from both software and hardware aspects
- About ARM's interrupt service routine
- Study stickers
- 24 "Millions" Raspberry Pi Car - Bullseye Benchmark Test of Raspberry Pi 64-bit System
- Sensors and measurement and control circuits
- Advanced usage of embedded C language