Everyone is familiar with I2C, which has two lines, CLK and DATA. I believe everyone is more familiar with stm32's I2C. It uses the writing controller method, and the controller directly completes the I2C timing operation. Users do not need to care about the specific logic generated. However, in most cases, the I2C Master mode is used, that is, the master device mode, and it is rarely used as the slave mode. This article talks about how to use stm32 I2C as a slave mode. More strictly speaking, this article talks about the smbus mode.
From the official website stm32 manual, we found the difference between smbus and I2C, you can understand it by yourself:
When actually using it, you can set and use smbus as I2C. From the code, except that the I2C Clock is set to 20K, there is no obvious difference. The following is the setting of I2C smbus mode:
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
// RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOB , ENABLE);
/* Configure I2C1 pins: SCL and SDA */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //6:SCL 7:SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// RCC_APB1PeriphClockCmd (RCC_APB1Periph_I2C1, ENABLE);
// Initialize I2C1 clock
// Reset I2C1 device clock in order to avoid non-cleared error flags
//__I2C_RCC_RESET(CPAL_I2C_CLK [Device]);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1,ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1,DISABLE);
// Enable I2C1 device clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
I2C_DeInit(I2C1);
I2C_InitStructure.I2C_Mode = I2C_Mode_SMBusDevice;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x76;//slave addr
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 20000;//20K
I2C_Init(I2C1, &I2C_InitStructure);
I2C_ITConfig(I2C1, I2C_IT_EVT|I2C_IT_BUF, ENABLE);
I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);
I2C_Cmd(I2C1,ENABLE);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure and enable I2Cx event interrupt -------------------------------*/
NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
From the above code, we can see that I2C initializes I2C IO mapping, working mode I2C_Mode_SMBusDevice, slave address 0x76 (customizable), I2C Clock, I2C interrupt vector and other parameters. After the settings are completed, whenever I2C generates data, an IRQ interrupt will be generated and the interrupt processing function I2C1_EV_IRQn will be entered, as shown below:
void I2C1_EV_IRQHandler(void)
{
uint32_t I2CFlagStatus;
static uint8_t IIC_Data=0;
I2CFlagStatus = I2C_GetLastEvent(I2C1); // => (SR2<<16|SR1)
// print_info("I2CFlagStatus=0x%x rn",I2CFlagStatus);
IIC1_EV_INT_Flag=1;
IIC_Get_Data_Flag=1;
if ((I2CFlagStatus & I2C_SR1_ADDR) != 0)//bit1:addr matched
{
//print_info("4rn");
if(I2CFlagStatus & I2C_SR1_TXE) //bit7 Data register empty (transmitters)
{//read
Rx_Idx=0;
Tx_Idx = 0;
I2C_SendData(I2C1, I2C_Buffer_Tx[Tx_Idx]);
}
else
{
}
}
else if((I2CFlagStatus & I2C_SR1_RXNE) != 0)//bit6 RxNE -Data register not empty (receivers))
{
IIC_Data=I2C_ReceiveData(I2C1);
I2C_Buffer_Rx[Frame_Idx][Rx_Idx] = IIC_Data;
Rx_Idx++;
}
else if((I2CFlagStatus & I2C_SR1_STOPF) != 0)//bit4 STOPF -Stop detection (slave mode)
{
//I2C_Buffer_Rx[0] = num-1;
I2C1->CR1 |= 0x1000;//CR1_PEC_Set;
Rx_Idx_t=Rx_Idx;
Rx_Idx=0;
Frame_Idx++;
I2C1->SR1=0;
I2C1->SR2=0;
}
else
{
}
}
In the interrupt handling function, after an interrupt is generated, the flag bit IIC_Get_Data_Flag is set to 1, and the current I2C status is obtained according to the read I2CFlagStatus status bit, and the data is obtained. Then, in the main function, the data generated by I2C is processed according to the flag bit. After the processing is completed, the IIC_Get_Data_Flag flag bit is set to 0. This is a good way to process data. (PS: The interrupt handling function cannot handle too complex and time-consuming transactions, so as not to affect the real-time nature of the interrupt response, so the data processing process is placed in the main function)
Previous article:STM32 GPIO and the first STM32 program (marquee)
Next article:STM32CubeMX learning tutorial 10: Hardware I2C reading and writing AT24C02
Recommended ReadingLatest update time:2024-11-16 20:51
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
- Where can I buy a multi-channel RF front-end development board with integrated digital attenuator and phase shifter?
- Question: What is the maximum communication rate of AT32F421?
- Why are there so few microcontrollers with integrated 16-bit ADC?
- micropython update: 2020.10
- Reply to receive a gift! It’s Chinese Valentine’s Day, let’s talk about how you and your significant other met?
- Theoretical speed calculation of WiFi protocols
- Does ARM have an instruction to directly obtain the overflow bit?
- MSP430F6638 three system reset
- EEWORLD University Hall----Live Replay: Maxim nanoPower Technology: Extending Battery Life and Improving Sensor Performance
- What knowledge do you need to do LED lighting?