Introduction
The I2C (inter-integrated circuit) bus interface handles communications between the
microcontroller and the serial I2C bus. It provides multimaster capability, and controls all I2C
bus-specific sequencing, protocol, arbitration and timing.
DMA can be used to reduce CPU overload
I2C main features
• I2C bus specification rev03 compatibility:
– Slave and master modes
– Multimaster capability
– Standard-mode (up to 100 kHz)
– Fast-mode (up to 400 kHz)
– Fast-mode Plus (up to 1 MHz) (Controller Specific)
– 7-bit and 10-bit addressing mode
– Multiple 7-bit slave addresses (2 addresses, 1 with configurable mask)
– All 7-bit addresses acknowledge mode
– General call
– Programmable setup and hold times
– Easy to use event management
– Optional clock stretching
– Software reset
• 1-byte buffer with DMA capability
• Programmable analog and digital noise filters
In addition to receiving and transmitting data, this interface converts it from serial to parallel
format and vice versa. The interrupts are enabled or disabled by software. The interface is
connected to the I2C bus by a data pin (SDA) and by a clock pin (SCL). It can be connected
with a standard (up to 100 kHz), Fast-mode (up to 400 kHz) or Fast-mode Plus (up to
1 MHz) I2C bus.
Pin name | Signal type | Description |
I2C_SDA | Bidirectional | I2C data |
I2C_SCL | Bidirectional | I2C clock |
How to use this driver
The I2C HAL driver can be used as follows:
1. Declare a I2C_HandleTypeDef handle structure, for example: I2C_HandleTypeDef hi2c;
2. Initialize the I2C low level resources by implementing the @ref HAL_I2C_MspInit() API:
a. Enable the I2Cx interface clock
b. I2C pins configuration
◦ Enable the clock for the I2C GPIOs
◦ Configure I2C pins as alternate function open-drain
c. NVIC configuration if you need to use interrupt process
◦ Configure the I2Cx interrupt priority
◦ Enable the NVIC I2C IRQ Channel
d. DMA Configuration if you need to use DMA process
◦ Declare a DMA_HandleTypeDef handle structure for the transmit or receive channel
◦ Enable the DMAx interface clock using
◦ Configure the DMA handle parameters
◦ Configure the DMA Tx or Rx channel
◦ Associate the initialized DMA handle to the hi2c DMA Tx or Rx handle
◦ Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx or
Rx channel
3. Configure the Communication Clock Timing, Own Address1, Master Addressing mode, Dual Addressing
mode, Own Address2, Own Address2 Mask, General call and Nostretch mode in the hi2c Init structure.
4. Initialize the I2C registers by calling the @ref HAL_I2C_Init(), configures also the low level Hardware (GPIO,
CLOCK, NVIC…etc) by calling the customized @ref HAL_I2C_MspInit(&hi2c) API.
5. To check if target device is ready for communication, use the function @ref HAL_I2C_IsDeviceReady()
6. For I2C IO and IO MEM operations, three operation modes are available within this driver :
DMA mode IO operation
• Transmit in master mode an amount of data in non-blocking mode (DMA) using @ref
HAL_I2C_Master_Transmit_DMA()
• At transmission end of transfer, @ref HAL_I2C_MasterTxCpltCallback() is executed and user can add his
own code by customization of function pointer @ref HAL_I2C_MasterTxCpltCallback()
• Receive in master mode an amount of data in non-blocking mode (DMA) using @ref
HAL_I2C_Master_Receive_DMA()
• At reception end of transfer, @ref HAL_I2C_MasterRxCpltCallback() is executed and user can add his own
code by customization of function pointer @ref HAL_I2C_MasterRxCpltCallback()
DMA mode IO MEM operation
• Write an amount of data in non-blocking mode with DMA to a specific memory address using @ref
HAL_I2C_Mem_Write_DMA()
• At Memory end of write transfer, @ref HAL_I2C_MemTxCpltCallback() is executed and user can add his
own code by customization of function pointer @ref HAL_I2C_MemTxCpltCallback()
• Read an amount of data in non-blocking mode with DMA from a specific memory address using @ref
HAL_I2C_Mem_Read_DMA()
• At Memory end of read transfer, @ref HAL_I2C_MemRxCpltCallback() is executed and user can add his
own code by customization of function pointer @ref HAL_I2C_MemRxCpltCallback()
• In case of transfer Error, @ref HAL_I2C_ErrorCallback() function is executed and user can add his own
code by customization of function pointer @ref HAL_I2C_ErrorCallback()
For this blog we are going to use I2C in DMA mode(master), we are going to used all above functions for demonstration, PA9 & PA10 Pin used for debugging purpose as UART Tx & UART Rx respectively. this blog is specially for I2C configuration in DMA mode, below 10 steps represents STM32 project creation from scratch, only difference will be board selection or controller selection part, user can select according to there requirements but below steps will remain same for all the projects.
for I2C implementation in poling mode refer
Creating a new STM32 executable project
- The easiest way to create a new STM32 C/C++ project is to use the STM32 project wizard. It is selected through the menu [File]>[New STM32 Project].
- The MCU/MPU selector and Board Selector tabs can be selected at the top of the window. Use the first tab to create project for a specific device and the second if a project for a specific board is needed. today we will select specific device.
3. Select SMT32F429ZI in MCU Selector tab
4. According to the settings in Figure 3, the project is meant to be stored in the default location with the following
options set:
• C project
• Executable binary type
• STM32CubeIDE targeted project type
Press [Next] to open the Firmware Library Package Setup page.
5. In this page, it is possible to select the STM32Cube firmware package to use when creating the project. In this case, the default settings are used. Press [Finish] to create the project. (Fig 4)
6. wait for project creation process
7. Initial view of STM32CUBE ide after project generation
8. Go to System core > SYS > Enable Serial wire debug
9. If require enable external clock
10. System clock setting at 180MHz
11. Enable Peripheral Configuration
Go to System mode > Connectivity > I2C > Enable I2C > keep all other settings as its
12. Enable the DMA settings for Tx & Rx depending upon your application requirement
I2C Tx DMA Settings
I2C Rx DMA Settings
12. Pin configuration
13. Press below icon for code generation
15. Sample Code:
/* Below is general pupose code for I2C communication user pass address accodinf to I2C device, simiparly he/she can pass config paramters USER_DEFINED_DATA_COUNT value can be vary from device to device */ HAL_StatusTypeDef I2C_Master_Functions_Handler(uint8_t address, uint8_t *config) { HAL_StatusTypeDef ret; uint8_t rxData[USER_DEFINED_DATA_COUNT]; ret = HAL_I2C_Master_Transmit_DMA(&hi2c1, (uint16_t)(address<<0x01u), config, sizeof(config)); if(ret != HAL_OK) { return ret; } HAL_Delay(10); //10ms delay ret = HAL_I2C_Master_Receive_DMA(&hi2c1, (uint16_t)((address<<0x01u)|0x01u), rxData, USER_DEFINED_DATA_COUNT); if(ret != HAL_OK) { return ret; } // Assemble reading data from rxData bytes //Todo Write user defined code return HAL_OK; }
#define MEMADD_Tx 0x00 //Dummy value #define MEMADD_Rx 0x00 //Dummy value #define MEM_CONFIG_COUNT 0x01 //Dummy value #define MEM_Rx_COUNT 0x01 //Dummy value /* Below is general pupose code for I2C communication user pass address accodinf to I2C device, simiparly he/she can pass config paramters USER_DEFINED_DATA_COUNT value can be vary from device to device */ HAL_StatusTypeDef I2C_Mem_Functions_Handler(uint8_t address, uint8_t *config) { HAL_StatusTypeDef ret; uint8_t rxData[USER_DEFINED_DATA_COUNT]; ret = HAL_I2C_Mem_Write_DMA(&hi2c1, (uint16_t)(address), (uint16_t)MEMADD, MEM_CONFIG_COUNT, config, sizeof(config)); if(ret != HAL_OK) { return ret; } HAL_Delay(10); //10ms delay ret = HAL_I2C_Mem_Read_DMA(&hi2c1, (uint16_t)(address) |0x01u, (uint16_t)MEMADD_Rx, MEM_Rx_COUNT, rxData, USER_DEFINED_DATA_COUNT); if(ret != HAL_OK) { return ret; } // Assemble reading data from rxData bytes //Todo Write user defined code return HAL_OK; }
Software Tools:
- STM32CubeIDE
- STM32CubeMx
- Teraterm
Hardware Setup:
- STM32F429IDISCOVERY board
- Mini USB Cable
- Jumper wire
Conclusion:
Successfully demonstrated I2C DMA mode functionality implementation. If you enjoyed this article, share your feedback.
References:
- STM32 HAL Library