Introduction to I2C
I2C is a two-wire bidirectional serial bus that provides a simple and efficient method for exchanging data between devices. The I2C standard is a true multi-host bus with conflict detection and arbitration mechanisms. It prevents data conflicts when two or more hosts request control of the bus at the same time.
The I2C bus controller can meet various specifications of the I2C bus and support all transmission modes for communicating with the I2C bus.
The I2C bus uses "SCL" (serial clock bus) and "SDA" (serial data bus) to transmit information between connected devices. Data is transmitted synchronously byte by byte on the SDA data line through the SCL clock line control between the master and the slave. Each byte is 8 bits long. One SCL clock pulse transmits one data bit. Data is transmitted starting from the highest bit MSB. Each transmitted byte is followed by an acknowledge bit. Each bit is sampled when SCL is high; therefore, the SDA line can only change when SCL is low, and SDA remains stable when SCL is high. When SCL is high, the jump on the SDA line is regarded as a command interrupt (START or STOP), and the I2C logic can handle the transmission of bytes autonomously. It can keep track of the serial transmission, and there is also a status register (I2C_SR) that reflects the status of the I2C bus controller and the I2C bus.
I2C Key Features
The I2C controller supports the following features:
⚫ Support four working modes: host send/receive, slave send/receive
⚫ Support three working speeds: standard (100Kbps)/fast (400Kbps)/high speed (1Mbps)
⚫ Support 7-bit addressing function
⚫ Support noise filtering function
⚫ Support broadcast address
⚫ Support interrupt status query function
I2C Protocol Description
Usually the standard I2C transmission protocol consists of four parts:
Start signal or repeated start signal
Slave address transmission and R/W bit transmission
data transmission
Stop signal
/********************************************************************************
* @file bsp_i2c.c
* @author jianqiang.xue
* @version V1.0.0
* @date 2021-04-11
* @brief NULL
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include #include #include "RTE_Components.h" #include CMSIS_device_header #include "cx32l003_hal.h" #include "bsp_gpio.h" #include "bsp_i2c.h" /* Private Includes ----------------------------------------------------------*/ #include "business_gpio.h" #include "business_function.h" /* Private Variables ---------------------------------------------------------*/ #if BS_I2C0_EN // Define IIC0 information handle static I2C_HandleTypeDef i2c0_handle_t = { .Instance = I2C, .Init.master = I2C_MASTER_MODE_ENABLE, // Master mode enable .Init.slave = I2C_SLAVE_MODE_DISABLE, // Slave mode disabled .Mode = HAL_I2C_MODE_MASTER, // Master mode .Init.broadack = I2C_BROAD_ACK_DISABLE, // Broadcast address response disabled .Init.speedclock = BS_I2C0_SPEED_RATE, // I2C transfer rate .State = HAL_I2C_STATE_RESET }; #endif /** * @brief [Initialization] IIC initialization * @note NULL * @param i2c_bus: IIC group number * @retval None */ void bsp_i2c_init(bsp_i2c_bus_t i2c_bus) { #if BS_I2C0_EN if (i2c_bus == I2C_BUS0) { __HAL_RCC_I2C_CLK_ENABLE(); BS_I2C0_SDA_GPIO_CLK_ENABLE(); bsp_gpio_init_i2c(BS_I2C0_SCL_GPIO_PORT, BS_I2C0_SCL_PIN, GPIO_AF4_I2C_SCL); bsp_gpio_init_i2c(BS_I2C0_SDA_GPIO_PORT, BS_I2C0_SDA_PIN, GPIO_AF4_I2C_SDA); HAL_I2C_Init(&i2c0_handle_t); } #endif } /** * @brief [Deinitialization] IIC turns off the clock and resets the pin * @note NULL * @param i2c_bus: IIC group number * @retval None */ void bsp_i2c_deinit(bsp_i2c_bus_t i2c_bus) { #if BS_I2C0_EN if (i2c_bus == I2C_BUS0) { __HAL_RCC_I2C_CLK_DISABLE(); bsp_gpio_deinit(BS_I2C0_SCL_GPIO_PORT, BS_I2C0_SCL_PIN); bsp_gpio_deinit(BS_I2C0_SDA_GPIO_PORT, BS_I2C0_SDA_PIN); HAL_I2C_DeInit(&i2c0_handle_t); } #endif } /** * @brief i2c read a byte * @note NULL * @param i2c_bus: IIC group number * @param dev_addr: device address * @param reg_addr: register address * @param r_data: pointer to the data header to be sent * @retval 0--success 1--failure */ uint8_t bsp_i2c_read_byte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t reg_addr, uint8_t *r_data) { if (i2c_bus == I2C_BUS0) { #if BS_I2C0_EN return HAL_I2C_Master_Receive(&i2c0_handle_t, dev_addr, ®_addr, 1, r_data, 1); #else return HAL_ERROR; #endif } return HAL_ERROR; } /** * @brief i2c read multiple bytes * @note NULL * @param i2c_bus: IIC group number * @param dev_addr: device address * @param w_data: txbuff header pointer data format: (reg_addr, w_data, w_data1, ...) * @param w_size: txbuff length * @param r_data: rxbuff head pointer * @param r_size: size of rxbuff * @retval 0--success 1--failure */ uint8_t bsp_i2c_read_nbyte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t *w_data, uint16_t w_size, uint8_t *r_data, uint16_t r_size) { if (i2c_bus == I2C_BUS0) { #if BS_I2C0_EN return HAL_I2C_Master_Receive(&i2c0_handle_t, dev_addr, w_data, w_size, r_data, r_size); #else return HAL_ERROR; #endif } return HAL_ERROR; } /** * @brief i2c write a byte * @note NULL * @param i2c_bus: IIC group number * @param dev_addr: device address * @param reg_addr: register address * @param w_data: byte value to be written * @retval 0--success 1--failure */ uint8_t bsp_i2c_write_byte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t reg_addr, uint8_t w_data) { uint8_t right = HAL_OK; if (i2c_bus == I2C_BUS0) { #if BS_I2C0_EN uint8_t data[2] = {reg_addr, w_data}; ret = HAL_I2C_Master_Transmit(&i2c0_handle_t, dev_addr, data, 2); #else right = HAL_ERROR; #endif } else { right = HAL_ERROR; } return right; } /** * @brief i2c write multiple bytes * @note NULL * @param i2c_bus: IIC group number * @param dev_addr: device address * @param w_data: txbuff header pointer data format: (reg_addr, w_data, w_data1, ...) * @param w_size: txbuff length * @retval 0--success 1--failure */ uint8_t bsp_i2c_write_nbyte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t *w_data, uint16_t w_size) { uint8_t right = HAL_OK; if (i2c_bus == I2C_BUS0) { #if BS_I2C0_EN ret = HAL_I2C_Master_Transmit(&i2c0_handle_t, dev_addr, w_data, w_size); #else right = HAL_ERROR; #endif } else { right = HAL_ERROR; } return right; } // ---------------------Bulk function----------------------------- /** * @brief i2c write multiple bytes without stop signal (with start signal and device address) * @note NULL * @param i2c_bus: IIC group number * @param dev_addr: device address * @param w_data: txbuff header pointer data format: (reg_addr, w_data, w_data1, ...) * @param w_size: txbuff length * @retval 0--success 1--failure */ uint8_t bsp_i2c_write_nbyte_nostop(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t *w_data, uint16_t w_size) { uint8_t right = HAL_OK; if (i2c_bus == I2C_BUS0) { #if BS_I2C0_EN ret = HAL_I2C_Master_Transmit_NOStop(&i2c0_handle_t, dev_addr, w_data, w_size); #else right = HAL_ERROR; #endif } else { right = HAL_ERROR; } return right; } /** * @brief i2c write multiple bytes without stop signal (without start signal and device address) * @note Must be used with [bsp_i2c_write_nbyte_nostop()] * @param i2c_bus: IIC group number * @param w_data: txbuff header pointer data format: (w_data, w_data1, ...) * @param w_size: txbuff length * @retval 0--success 1--failure */ uint8_t bsp_i2c_send_nbyte(bsp_i2c_bus_t i2c_bus, uint8_t *w_data, uint16_t w_size) { uint8_t right = HAL_OK; if (i2c_bus == I2C_BUS0) { #if BS_I2C0_EN uint16_t i = 0; uint32_t i2c_flag = 0XFF; HAL_I2C_Wait_Flag(&i2c0_handle_t, &i2c_flag); while (i < w_size) { i2c_flag = 0XFF; HAL_I2C_Send_Byte(&i2c0_handle_t, w_data[i]); HAL_I2C_Wait_Flag(&i2c0_handle_t, &i2c_flag); if (i2c_flag != I2C_FLAG_MASTER_TX_DATA_ACK) // 0x00000028U { i2c0_handle_t.State = HAL_I2C_STATE_ERROR; i2c0_handle_t.ErrorCode = i2c0_handle_t.PreviousState; return HAL_ERROR; } i++; } #else right = HAL_ERROR; #endif } else { right = HAL_ERROR; } return right; } /** * @brief Send a stop signal * @note NULL * @param i2c_bus: IIC group number * @param state: false--clear the interrupt flag true--do not clear the interrupt flag * @retval 0--success 1--failure */ uint8_t bsp_i2c_stop(bsp_i2c_bus_t i2c_bus, bool state) { uint8_t right = HAL_OK; if (i2c_bus == I2C_BUS0) { #if BS_I2C0_EN HAL_I2C_Stop_Config(&i2c0_handle_t, (FunctionalState)true); #else right = HAL_ERROR; #endif } else { right = HAL_ERROR; } return right; } /******************************************************************************** * @file bsp_i2c.h * @author jianqiang.xue * @version V1.0.0 * @date 2021-04-11 * @brief NULL ********************************************************************************/ #ifndef __BSP_I2C_H #define __BSP_I2C_H /* Includes ------------------------------------------------------------------*/ #include #include /* Public enum ---------------------------------------------------------------*/ typedef enum { I2C_BUS0 = 0, I2C_BUS1 = 1, I2C_BUS2 = 2, } bsp_i2c_bus_t; /* Public Function Prototypes ------------------------------------------------*/ void bsp_i2c_init(bsp_i2c_bus_t i2c_bus); void bsp_i2c_deinit(bsp_i2c_bus_t i2c_bus); // Finished product complete set of logic start-response-data-stop uint8_t bsp_i2c_read_byte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t reg_addr, uint8_t *r_data); uint8_t bsp_i2c_read_nbyte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t *w_data, uint16_t w_size, uint8_t *r_data, uint16_t r_size);
Previous article:[MCU framework][BSP layer][cx32l003][bsp_tim] TIM timer configuration and use
Next article:[MCU framework][bsp layer][cx32l003][bsp_crc] Hardware CRC configuration and use
- 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
- Studying the road to electric motor drive
- Help with op amp output sine wave signal analysis
- How to use Klipper99se?
- Q: What determines the amplifier power supply voltage range? What are the mainstream power supply ranges?
- GigaDevice GD Series System Solution Evaluation
- Learn about IO-Link and its five advantages
- 【RT-Thread Reading Notes】Reflections on RT-Thread Chapters 9-12
- 【NXP Rapid IoT Review】+ Familiar with the hardware
- 【Qinheng RISC-V core CH582】BLE lighting
- EEWORLD University ---- Altium Designer 4-layer smart car complete PCB design video tutorial