cancel
Showing results for 
Search instead for 
Did you mean: 

STMF0 I2C Slave IT states

BNeum
Associate II

I have a STM32F030C6 on a custom board and I want to use it as an I2C slave device.

With the example given with the cube hal (FW 1.9) I got it working. Kind of.

I can write data from the master to the slave. But I have problems reading data from the device.

I also used this example I found online, because it is mostly what I want

https://github.com/cnoviello/mastering-stm32/blob/master/nucleo-f030R8/src/ch14/main-ex2.c

What I got now is this:

void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection,
		uint16_t AddrMatchCode) {
 
	if (hi2c->Instance == I2C1 && AddrMatchCode == hi2c->Init.OwnAddress1) {
		transferRequested = 1;
		transferDirection = TransferDirection;
	}
}
void processI2C() {
	HAL_I2C_EnableListen_IT(&hi2c1);
	if (transferRequested) {
		transferRequested = 0;
 
		HAL_I2C_Slave_Sequential_Receive_IT(&hi2c1, i2c_buf, 1,
		I2C_FIRST_FRAME);
 
		if (transferDirection == TRANSFER_DIR_READ) {
 
			while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
				;
 
			// Register is in buffer for all to read
			reg = i2c_buf[0];
			switch (i2c_buf[0]) {
			case GLOBAL_GO: // we read a byte
				HAL_I2C_Slave_Sequential_Receive_IT(&hi2c1, i2c_buf, 1,
				I2C_LAST_FRAME);
				game_running = i2c_buf[1];
				break;
			case GAME_POINTS:
				// do something?
				break;
			}
			while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
				;
		}
 
		if (transferDirection == TRANSFER_DIR_WRITE) {
 
			while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_LISTEN)
				;
 
			switch (i2c_buf[0]) {
			case GAME_POINTS:
				// prepare buffer for Point transmission
				i2c_buf[0] = game.points.u8[0];
				i2c_buf[1] = game.points.u8[1];
				i2c_buf[2] = game.points.u8[2];
				i2c_buf[3] = game.points.u8[3];
				break;
			default:
				i2c_buf[0] = 0;
				i2c_buf[1] = 0;
				i2c_buf[2] = 0;
				i2c_buf[3] = 0;
			}
			HAL_I2C_Slave_Sequential_Transmit_IT(&hi2c1, i2c_buf, 4,
			I2C_LAST_FRAME);
			while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
				;
 
		}
	}
}

Using a master device to write to register GLOBAL_GO works perfectly. But reading Register GAME_POINTS causes the thing to be stuck in Line 11 of the code above with State HAL_I2C_STATE_LISTEN

This causes clock stretching to keep SCL low and everything comes to a halt. Is there a resource where it is shown how read and write is done? Or do I simply miss a little information?

I attached a trace of a working write0690X0000089c3mQAA.png

and a not working read

0690X0000089c3rQAA.png

1 REPLY 1
BNeum
Associate II

I used byte wise transfers and they work. To bad HAL does not clearly statzes how to do sequential transfers correctly.