cancel
Showing results for 
Search instead for 
Did you mean: 

I2C CMSIS STM32F303RE

JMart.13
Senior

Hello again.

I'm having this problem with I2C with the STM32F303RE.

I have this array of data I want to send via I2C to a sensor.

std::uint8_t conf_bytes[2] = {0xF4, 0x03}; 
periph::I2C::write_data(I2C1, BME_ADDR, 2U, conf_bytes);  

BME_ADDR is the address of the sensor I want to write to.

and this is my function write_data:

void write_data(I2C_TypeDef * i2c, std::uint8_t slave_addr, std::uint8_t data_size, std::uint8_t * data){
	volatile std::uint8_t nbytes = data_size; 
	volatile std::uint8_t i = 0; 
	i2c->CR1 &= ~I2C_CR1_PE; 
	i2c->CR1 |= I2C_CR1_PE; 
	while((i2c->ISR & IS_BUSSY)){}
	i2c->CR2 &= ~I2C_CR2_RD_WRN;
	i2c->CR2 |= (slave_addr << 1U); 
			
	i2c->CR2 |= (nbytes << NBYTES);
	i2c->CR2 |= I2C_CR2_START; 
				
        while(nbytes--){
		while(!(i2c->ISR & I2C_ISR_TXIS)){}				
		i2c->TXDR = data[i]; 
		i++;					
	}
	i2c->CR2 |= I2C_CR2_STOP;	
}

Trying this I get the following result with the logic analyzer:

0693W00000D1A7VQAV.pngThat strange glitch happens all the time, and I don't know what else I can do.

I made another function to read a register of the sensor:

uint8_t * read_data(I2C_TypeDef * i2c, std::uint8_t slave_addr, std::uint8_t size, std::uint8_t * data); 

it is defined as follows:

	uint8_t * read_reg(I2C_TypeDef * i2c, std::uint8_t slave_addr, std::uint8_t data_tx_size, std::uint8_t * data_tx, std::uint8_t data_rx_size){				
	i2c->CR1 &= ~I2C_CR1_PE; 
	i2c->CR1 |= I2C_CR1_PE; 
	std::uint8_t tx_s = data_tx_size; 
	std::uint8_t rx_s = data_rx_size; 
	std::uint8_t received = 0; 
	std::uint8_t * data_return = new std::uint8_t[rx_s]; 
	while((i2c->ISR & IS_BUSSY)){}
	i2c->CR2 &= ~I2C_CR2_RD_WRN;
	i2c->CR2 |= (slave_addr << 1U); 
				
	volatile std::uint8_t i = 0; 
	i2c->CR2 |= (tx_s << NBYTES);
	i2c->CR2 |= I2C_CR2_START; 
	while(tx_s--){
		while(!(i2c->ISR & I2C_ISR_TXIS)){}				
		i2c->TXDR = data_tx[i]; 
		i++;					
	}
			
	i2c->CR2 &= ~(tx_s << NBYTES);
	i2c->CR2 |= (rx_s << NBYTES);
	i2c->CR2 |= I2C_CR2_RD_WRN;
	i2c->CR2 |= I2C_CR2_START;
	while(rx_s--){
		while(!(i2c->ISR & I2C_ISR_RXNE)){}
		data_return[received] = i2c->RXDR; 
	}
	i2c->CR2 |= I2C_CR2_STOP; 	
	return data_return; 
}

and for example, I want to read the register 0XD0 that contains the sensor ID:

utils::delay::ms(200); 
std::uint8_t data_i2c[1] = {0xD0}; 
periph::I2C::read_reg(I2C1, BME_ADDR, 1U, data_i2c, 1U); 
utils::delay::ms(200); 

And the result is the following:

0693W00000D1A7pQAF.png 

It works perfectly, but, even if I make a write and then a read, all the data gets distorted all over again, so, I don't know what could it be, or maybe is my logic analyzer (is one of those cheap Chinese of saelae, but for now, it has been working perfectly)

Thanks for any answer

6 REPLIES 6

> It works perfectly, but, even if I make a write and then a read, all the data gets distorted all over again,

So does it work perfectly or not? And what do you mean by "data gets distorted"?

JW

TDK
Guru

What chip are you interfacing with?

What's wrong with the data in the plot you're showing?

If you feel a post has answered your question, please click "Accept as Solution".

I'm trying to read data from a BME-280 sensor, in the first plot I want to write to the 0xF4 register the value 0x03, but it doesn´t show the 0x03, instead, there is like that glitch showing.

The second one is a good reading of a register from the sensor. so I think I'm having problems with the write statement, i don't know if there is a step more

well, the write function is not working that good, it shows that little glitch when I'm sending data to a register (I'm using a BME-280 sensor) I'm trying to send 0xF4(register direction) and 0x03(the data I want to write)

In the second plot, I'm reading a register that contains the ID of the device, and the function reads that register with no problem. So I think I'm having a problem with the write function.

What I mean with the data is distorted is that, when I send a write function and then read a register, neither of them sends the data correctly, and then the SCL line stays low, but that only happen when I send a write and then a read, neither of them send the correct values I want to send.

example, I want to sent this information like this:

std::uint8_t data_i2c[1] = {0xD0}; 
std::uint8_t conf_bytes[2] = {0xF4, 0x03}; 
 
periph::I2C::write_data(I2C1, BME_ADDR, 2U, conf_bytes);  
utils::delay::ms(200); 
periph::I2C::read_reg(I2C1, BME_ADDR, 1U, data_i2c, 1U);

so, this is when it makes the write function:

0693W00000D1BNUQA3.pngand this is when happens the read instruction:

0693W00000D1BNeQAN.png

The I2C module is picky and notoriously hard to make right. You appear to use symbols different from what are in the CMSIS-mandated device header, e.g. IS_BUSSY

and NBYTES. Double-check they are correct; read back the I2C registers content and check that they contain what you intended.

JW

Hi @Community member​ sorry for the late answer, I will try to check that, thanks for the answer!