
In the second section of the fourteenth part of I2C BSP, we shall develop functions that will communicate with slave devices to write/read to/from MPU9250.
In this guide, we shall cover the following:
- Updating the header file.
- Updating the source file.
- Main code.
- Results.
1. Updating the header file:
In i2c_bps.h header file, include the following three functions.
The first function:
I2C_StatusTypedef BSP_I2C_Write(I2C_TypeDef *i2c, uint8_t address, uint8_t *data,uint16_t length, uint32_t timeout);
The function takes five parameters as following:
- I2C_Typedef to indicate which i2c to be used.
- The address of the slave device.
- Array that holds the data to be written to the slave device.
- Length of the data to be written.
- Timeout for time management.
Also, the function will return the I2C status as following:
- Success
- Failed.
- Timeout
The second function:
I2C_StatusTypedef BSP_I2C_Read_Memory(I2C_TypeDef *i2c, uint8_t address,uint8_t MemAddr, uint8_t *data,uint16_t length, uint32_t timeout);
This function will send the memory address to be read . It takes six parameters:
- I2C_Typedef to indicate which i2c to be used.
- The address of the slave device.
- The memory address within the slave.
- Array which holds the data to be read.
- Length of the data to be read.
- Timeout for time management.
The function will return the status of I2C as mentioned earlier.
The third and final function as following:
I2C_StatusTypedef BSP_I2C_Read(I2C_TypeDef *i2c, uint8_t address, uint8_t *data,uint16_t lenght, uint32_t timeout);
This function will read the slave directly without sending the memory to read first.
Hence, the update header file as following:
#ifndef I2C_BSP_H_
#define I2C_BSP_H_
#include "stm32f4xx.h"
#include "stdint.h"
#include "bsp_debug.h"
#include "bsp.h"
#define __I2C1_CLOCK_ENABLE() RCC->APB1ENR|=RCC_APB1ENR_I2C1EN
#define __I2C2_CLOCK_ENABLE() RCC->APB1ENR|=RCC_APB1ENR_I2C2EN
#define __I2C3_CLOCK_ENABLE() RCC->APB1ENR|=RCC_APB1ENR_I2C3EN
typedef enum
{
standardSpeed=0,
fastMode=1
}I2C_MasterModeTypedef;
typedef enum
{
Duty_2=0,
Duty_16_9=1
}I2C_DutyModeTypedef;
typedef enum
{
i2c_success=0,
i2c_failed=1,
i2c_timeOut=2
}I2C_StatusTypedef;
typedef struct
{
uint8_t PeripheralFrequency;
uint8_t MasterMode;
uint8_t DutyMode;
uint16_t RiseTime;
uint16_t Clock;
}I2C_ConfigTypedef;
void BSP_I2C_Init(I2C_TypeDef *i2c, I2C_ConfigTypedef *config);
void BSP_I2C_Bus_Scan(I2C_TypeDef *i2c);
I2C_StatusTypedef BSP_I2C_Write(I2C_TypeDef *i2c, uint8_t address, uint8_t *data ,uint16_t length, uint32_t timeout);
I2C_StatusTypedef BSP_I2C_Read_Memory(I2C_TypeDef *i2c, uint8_t address,uint8_t MemAddr, uint8_t *data,uint16_t length, uint32_t timeout);
I2C_StatusTypedef BSP_I2C_Read(I2C_TypeDef *i2c, uint8_t address, uint8_t *data,uint16_t lenght, uint32_t timeout);
#endif /* I2C_BSP_H_ */
2. Updating the source file:
Before heading into updating the source file, please refer to these two guide:
The write function as following:
I2C_StatusTypedef BSP_I2C_Write(I2C_TypeDef *i2c, uint8_t address, uint8_t *data,uint16_t length, uint32_t timeout)
{
uint32_t start_timer=BSP_Get_Ticks();
while (i2c->SR2 & I2C_SR2_BUSY) //wait until bus not busy
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->CR1 |= I2C_CR1_START; //generate start
while (!(i2c->SR1 & I2C_SR1_SB)) //wait until start is generated
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->DR = address<< 1; // Send slave address
while (!(i2c->SR1 & I2C_SR1_ADDR)) //wait until address flag is set
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
(void) i2c->SR2; //Clear SR2
while (!(i2c->SR1 & I2C_SR1_TXE)) //Wait until Data register empty
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
for (uint16_t i=0;i<length;i++)
{
i2c->DR=data[i]; //filling buffer with command or data
while (!(i2c->SR1 & I2C_SR1_BTF))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
}
i2c->CR1 |= I2C_CR1_STOP;
return i2c_success;
}For the read from memory address:
I2C_StatusTypedef BSP_I2C_Read_Memory(I2C_TypeDef *i2c, uint8_t address,uint8_t MemAddr, uint8_t *data,uint16_t length, uint32_t timeout)
{
uint32_t start_timer=BSP_Get_Ticks();
while (i2c->SR2 & I2C_SR2_BUSY)
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->CR1|=I2C_CR1_START;
while(!(i2c->SR1 & I2C_SR1_SB))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->DR=address<<1;
while(!(i2c->SR1 & I2C_SR1_ADDR))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
(void)i2c->SR2;
while(!(i2c->SR1&I2C_SR1_TXE))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->DR = MemAddr;
while(!(i2c->SR1&I2C_SR1_TXE))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->CR1|=I2C_CR1_START;
while(!(i2c->SR1 & I2C_SR1_SB))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->DR=address<<1|1;
while(!(i2c->SR1 & I2C_SR1_ADDR))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
(void)i2c->SR2;
i2c->CR1|=I2C_CR1_ACK;
while(length>0U)
{
if(length==1U)
{
i2c->CR1&=~I2C_CR1_ACK;
i2c->CR1|=I2C_CR1_STOP;
while(!(i2c->SR1&I2C_SR1_RXNE))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
*data++=i2c->DR;
break;
}
else
{
while(!(i2c->SR1&I2C_SR1_RXNE))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
(*data++)=i2c->DR;
length--;
}
}
return i2c_success;
}For reading the i2c slave only without memory:
I2C_StatusTypedef BSP_I2C_Read(I2C_TypeDef *i2c, uint8_t address, uint8_t *data, uint16_t length, uint32_t timeout)
{
uint32_t start_timer=BSP_Get_Ticks();
while (i2c->SR2 & I2C_SR2_BUSY)
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->CR1|=I2C_CR1_START;
while(!(i2c->SR1 & I2C_SR1_SB))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->DR=address<<1|1;
while(!(i2c->SR1 & I2C_SR1_ADDR))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
(void)i2c->SR2;
i2c->CR1|=I2C_CR1_ACK;
while(length>0U)
{
if(length==1U)
{
i2c->CR1&=~I2C_CR1_ACK;
i2c->CR1|=I2C_CR1_STOP;
while(!(i2c->SR1&I2C_SR1_RXNE))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
*data++=i2c->DR;
break;
}
else
{
while(!(i2c->SR1&I2C_SR1_RXNE))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
(*data++)=i2c->DR;
length--;
}
}
return i2c_success;
}
Hence, the updated source file as following:
#include "i2c_bsp.h"
void BSP_I2C_Init(I2C_TypeDef *i2c, I2C_ConfigTypedef *config)
{
i2c->CR1=I2C_CR1_SWRST;
i2c->CR1&=~I2C_CR1_SWRST;
i2c->CR2|= config->PeripheralFrequency;
i2c->TRISE=config->RiseTime;
i2c->CCR|=(config->MasterMode<<I2C_CCR_FS_Pos);
i2c->CCR|=(config->DutyMode<<I2C_CCR_DUTY_Pos);
if((config->Clock)==0)
{
float period =1.0/(float)(config->PeripheralFrequency);
if((config->MasterMode)==standardSpeed)
{
uint16_t tmp = 5/period;
i2c->CCR|=(tmp<<I2C_CCR_CCR_Pos);
}
else
{
if(config->DutyMode==Duty_2)
{
uint16_t tmp=5/period;
i2c->CCR|=(tmp<<I2C_CCR_CCR_Pos);
}
else
{
uint16_t tmp=13/period;
i2c->CCR|=(tmp<<I2C_CCR_CCR_Pos);
}
}
}
else
{
i2c->CCR|=(config->Clock<<I2C_CCR_CCR_Pos);
}
i2c->CR1|=I2C_CR1_PE;
}
void BSP_I2C_Bus_Scan(I2C_TypeDef *i2c)
{
char data[100];
uint8_t a=0;
for (uint8_t i=0;i<128;i++)
{
i2c->CR1 |= I2C_CR1_START;
while(!(i2c->SR1 & I2C_SR1_SB));
i2c->DR=(i<<1|0);
while(!(i2c->SR1)|!(I2C1->SR2)){};
i2c->CR1 |= I2C_CR1_STOP;
BSP_Delay(1);
a=(i2c->SR1&I2C_SR1_ADDR);
if (a==2)
{
sprintf(data,"Found I2C device at address 0x%X (hexadecimal), or %d (decimal)\n\r",i,i);
log_info(data);
}
}
}
I2C_StatusTypedef BSP_I2C_Write(I2C_TypeDef *i2c, uint8_t address, uint8_t *data,uint16_t length, uint32_t timeout)
{
uint32_t start_timer=BSP_Get_Ticks();
while (i2c->SR2 & I2C_SR2_BUSY) //wait until bus not busy
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->CR1 |= I2C_CR1_START; //generate start
while (!(i2c->SR1 & I2C_SR1_SB)) //wait until start is generated
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->DR = address<< 1; // Send slave address
while (!(i2c->SR1 & I2C_SR1_ADDR)) //wait until address flag is set
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
(void) i2c->SR2; //Clear SR2
while (!(i2c->SR1 & I2C_SR1_TXE)) //Wait until Data register empty
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
for (uint16_t i=0;i<length;i++)
{
i2c->DR=data[i]; //filling buffer with command or data
while (!(i2c->SR1 & I2C_SR1_BTF))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
}
i2c->CR1 |= I2C_CR1_STOP;
return i2c_success;
}
I2C_StatusTypedef BSP_I2C_Read_Memory(I2C_TypeDef *i2c, uint8_t address,uint8_t MemAddr, uint8_t *data,uint16_t length, uint32_t timeout)
{
uint32_t start_timer=BSP_Get_Ticks();
while (i2c->SR2 & I2C_SR2_BUSY)
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->CR1|=I2C_CR1_START;
while(!(i2c->SR1 & I2C_SR1_SB))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->DR=address<<1;
while(!(i2c->SR1 & I2C_SR1_ADDR))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
(void)i2c->SR2;
while(!(i2c->SR1&I2C_SR1_TXE))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->DR = MemAddr;
while(!(i2c->SR1&I2C_SR1_TXE))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->CR1|=I2C_CR1_START;
while(!(i2c->SR1 & I2C_SR1_SB))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->DR=address<<1|1;
while(!(i2c->SR1 & I2C_SR1_ADDR))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
(void)i2c->SR2;
i2c->CR1|=I2C_CR1_ACK;
while(length>0U)
{
if(length==1U)
{
i2c->CR1&=~I2C_CR1_ACK;
i2c->CR1|=I2C_CR1_STOP;
while(!(i2c->SR1&I2C_SR1_RXNE))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
*data++=i2c->DR;
break;
}
else
{
while(!(i2c->SR1&I2C_SR1_RXNE))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
(*data++)=i2c->DR;
length--;
}
}
return i2c_success;
}
I2C_StatusTypedef BSP_I2C_Read(I2C_TypeDef *i2c, uint8_t address, uint8_t *data, uint16_t length, uint32_t timeout)
{
uint32_t start_timer=BSP_Get_Ticks();
while (i2c->SR2 & I2C_SR2_BUSY)
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->CR1|=I2C_CR1_START;
while(!(i2c->SR1 & I2C_SR1_SB))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
i2c->DR=address<<1|1;
while(!(i2c->SR1 & I2C_SR1_ADDR))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
(void)i2c->SR2;
i2c->CR1|=I2C_CR1_ACK;
while(length>0U)
{
if(length==1U)
{
i2c->CR1&=~I2C_CR1_ACK;
i2c->CR1|=I2C_CR1_STOP;
while(!(i2c->SR1&I2C_SR1_RXNE))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
*data++=i2c->DR;
break;
}
else
{
while(!(i2c->SR1&I2C_SR1_RXNE))
{
if (BSP_Get_Ticks()- start_timer>timeout)
{
return i2c_timeOut;
}
}
(*data++)=i2c->DR;
length--;
}
}
return i2c_success;
}
3. Main code.
In main.c file:
Include the following:
#include "bsp.h" #include "uart_bsp.h" #include "exti_bsp.h" #include "bsp_debug.h" #include "spi_bsp.h" #include "dma_bsp.h" #include "i2c_bsp.h" #include "stdlib.h"
Declare i2c configuration data structure:
I2C_ConfigTypedef i2c1Config;
Declare an array of 6 bytes to hold the acceleration data:
uint8_t MPU9250_ACC_Data[6];
In main function:
#if FPU_EN SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); #endif clock_config(); BSP_Ticks_Init(100000000); GPIO_Configure_Typedef I2C_PB8, I2C_PB9; GPIOB_CLOCK_ENABLE(); I2C_PB8.PinNumber=8; I2C_PB8.OutputType=Open_Drain; I2C_PB8.Mode=Alternate_function; I2C_PB8.PullUp_PullDown=PullUp; I2C_PB8.AlternateType=AF4; I2C_PB9.PinNumber=9; I2C_PB9.OutputType=Open_Drain; I2C_PB9.Mode=Alternate_function; I2C_PB8.PullUp_PullDown=PullUp; I2C_PB9.AlternateType=AF4; GPIO_Initialization(GPIOB,&I2C_PB8); GPIO_Initialization(GPIOB,&I2C_PB9); __I2C1_CLOCK_ENABLE(); i2c1Config.MasterMode=standardSpeed; i2c1Config.PeripheralFrequency=50; i2c1Config.RiseTime=9; BSP_I2C_Init(I2C1, &i2c1Config);
In while(1) loop:
while(1)
{
BSP_I2C_Read_Memory(I2C1, 0x68, 0x3B, MPU9250_ACC_Data, 6, 200);
}Hence, the main code as following:
#include "bsp.h"
#include "uart_bsp.h"
#include "exti_bsp.h"
#include "bsp_debug.h"
#include "spi_bsp.h"
#include "dma_bsp.h"
#include "i2c_bsp.h"
#include "stdlib.h"
void clock_config(void);
I2C_ConfigTypedef i2c1Config;
uint8_t MPU9250_ACC_Data[6];
int main()
{
#if FPU_EN
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));
#endif
clock_config();
BSP_Ticks_Init(100000000);
GPIO_Configure_Typedef I2C_PB8, I2C_PB9;
GPIOB_CLOCK_ENABLE();
I2C_PB8.PinNumber=8;
I2C_PB8.OutputType=Open_Drain;
I2C_PB8.Mode=Alternate_function;
I2C_PB8.PullUp_PullDown=PullUp;
I2C_PB8.AlternateType=AF4;
I2C_PB9.PinNumber=9;
I2C_PB9.OutputType=Open_Drain;
I2C_PB9.Mode=Alternate_function;
I2C_PB8.PullUp_PullDown=PullUp;
I2C_PB9.AlternateType=AF4;
GPIO_Initialization(GPIOB,&I2C_PB8);
GPIO_Initialization(GPIOB,&I2C_PB9);
__I2C1_CLOCK_ENABLE();
i2c1Config.MasterMode=standardSpeed;
i2c1Config.PeripheralFrequency=50;
i2c1Config.RiseTime=9;
BSP_I2C_Init(I2C1, &i2c1Config);
while(1)
{
BSP_I2C_Read_Memory(I2C1, 0x68, 0x3B, MPU9250_ACC_Data, 6, 200);
}
}
void clock_config(void)
{
Clock_Config_Typedef clockConfig;
clockConfig.PLL_M= 4;
clockConfig.PLL_N= 200;
clockConfig.PLL_P= 4;
clockConfig.AHB1Prescaler=AHB1_Prescaler1;
clockConfig.APB1Prescaler=APB1_Prescaler2;
clockConfig.APB2Prescaler=APB2_Prescaler1;
clockConfig.clockSourc=External_Oscillator;
clockConfig.flash_latency= Three_wait_state;
Clock_Configuration(&clockConfig);
}
4. Results:
Upload the code to your STM32 and connect MPU9250 and you should get the following:

Happy coding 🙂
4 Comments
Dear Sir,
Good Morning,
in UART2 Serial Prinitng, we Use, function
int __io_putchar(int ch) { uart2_write(ch); return ch; }
where as in SWO, we use the Same function as..
int __io_putchar(int ch) { ITM_SendChar(ch); return ch; }
if we need both SWO output for debugging, and Serial Display using Printf(),
simultaneously in the same program how to address, them. Please Respond,
thanks with regards,
HSR-Rao.
Hi,
just put ITM_SendChar(ch); after the uart and you can get both.
Thank you sir,
Dear Sir,
Good morning, Suggestion Worked successfully,
thanks, with regards,
HSR-Rao.
Add Comment