2018-04-24 03:08 AM
I'm trying to make I2C Slave using examples from Cube.
The wizard can write the register, but when reading the HAL_I2C_ListenCpltCallback is called only once.
Can someone share their working code with me? I don't understand how this should work.
uint8_t i2cSlavDirection;
uint8_t i2cSlaveTransmitBuffer;uint8_t i2cSlaveReceiveBuffer[2];// Never calledvoid HAL_I2C_ErrorCallback(I2C_HandleTypeDef *i2cHandle) { _Error_Handler(__FILE__, __LINE__);}// Never called
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *i2cHandle) { }// Never called
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *i2cHandle) { }void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *i2cHandle) {
HAL_GPIO_TogglePin(GPIOB, LED_GREEN_Pin);switch (i2cSlavDirection) {
case I2C_DIRECTION_TRANSMIT: { // master write // ... reg write ... } break; case I2C_DIRECTION_RECEIVE: { // master read // ... get reg value and write to i2cSlaveTransmitBuffer ...if(HAL_I2C_Slave_Sequential_Transmit_IT(i2cHandle, (uint8_t*)&i2cSlaveTransmitBuffer, 1, I2C_FIRST_AND_LAST_FRAME) != HAL_OK){
_Error_Handler(__FILE__, __LINE__); } } break; }// Restarting
if(HAL_I2C_EnableListen_IT(i2cHandle) != HAL_OK){ _Error_Handler(__FILE__, __LINE__); }}void HAL_I2C_AddrCallback(I2C_HandleTypeDef *i2cHandle, uint8_t transferDirection, uint16_t addrMatchCode) {
i2cSlave.transferDirection = transferDirection;// 2 - master write, 1 - master read
uint8_t receiveSize = transferDirection == I2C_DIRECTION_TRANSMIT ? 2 : 1; if(HAL_I2C_Slave_Sequential_Receive_IT(i2cHandle, (uint8_t*)i2cSlaveReceiveBuffer, receiveSize, I2C_FIRST_FRAME) != HAL_OK){ _Error_Handler(__FILE__, __LINE__); }}void StartDefaultTask(void const * argument) {
if(HAL_I2C_EnableListen_IT(&hi2c1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }while (1);
}#hal #i2c-slave #hal_i2c2018-04-24 04:20 AM
Ok, in order for me to try to help please supply the following additional info
- chip or board you are using
- which Cube example are you using
- what are you using as master I2C
- IDE and link you are using
I will try to replicate your setup.
Frank.
2018-04-25 05:24 AM
,
,
I use trueSTUDIO and STM32F101C8U
I looked at an example in , F0_V1.8.0\Projects\STM32F072RB-Nucleo\Examples\I2C\I2C_TwoBoards_RestartAdvComIT
I don't understand anything, now my call stack is like this:
♯ RESTART_LISTEN
,
♯ MASTER_WIRE,
♯ RESTART_LISTEN,
♯ MASTER_WIRE,
♯ MASTER_READSlave code:
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t transferDirection, uint16_t addrMatchCode) {
,
, , ,if(transferDirection == I2C_DIRECTION_TRANSMIT) {,
,
, , , , , ,// ♯ MASTER_WIRE,
,
, , , , , ,if(HAL_I2C_Slave_Sequential_Receive_IT(&,hi2c1, (uint8_t *)&,(i2cSlaveReceiveBuffer[receiveIndex++]), 1, I2C_FIRST_FRAME) != HAL_OK) {,
, , , , , , , , ,Error_Handler(),,
, , , , , ,},
, , ,} else {,
, , , , , ,// ♯ MASTER_READ,
,
, , , , , ,receiveIndex = 0,,
,
, , , , , ,// ... get reg value and write to i2cSlaveTransmitBuffer ...,
,
, , , , , ,if(HAL_I2C_Slave_Sequential_Transmit_IT(&,hi2c1, (uint8_t*)&,i2cSlaveTransmitBuffer, 1, I2C_LAST_FRAME) != HAL_OK) {,
, , , , , , , , ,Error_Handler(),,
, , , , , ,},
, , ,},
},
void StartDefaultTask(void const *argument) {,
, , ,receiveIndex = 0,, , ,while (1) {
,
, , , , , ,// ♯ RESTART_LISTEN,
, , , , , ,if (HAL_I2C_EnableListen_IT(&,hi2c1) != HAL_OK) {,
, , , , , , , , ,Error_Handler(),,
, , , , , ,}, , , , , ,while(HAL_I2C_GetState(&,hi2c1) != HAL_I2C_STATE_READY),
, , , , , ,if(receiveIndex == 2) {
,
, , , , , , , , ,receiveIndex = 0,,
,
, , , , , , , , , // ... reg update ...,
, , , , , ,},
, , ,},
}Master code:
, , , uint8_t reg = 3,
,
, , ,uint8_t data = 50,,
, , ,uint8_t read,,
, , ,uint8_t slave = 0x20 <,<, 1,, , ,HAL_I2C_Mem_Write(&,hi2c3, slave, reg, 1, &,data, 1, 100),
,
, , ,HAL_Delay(50),, , ,HAL_I2C_Mem_Read(&,hi2c3, slave, reg, 1, &,read, 1, 100),
,
, , ,HAL_Delay(50),2018-04-27 04:37 PM
To let you know, I built the example project on 2 boards (not Nucleo - my own hardware) and it works fine.
Its not clear why your call stack looks the way it does. Just a shot in the dark - in your slave code did you enable address listen mode using HAL_I2C_EnableListen_IT() ? You dont show it in your code. EDIT: correction, it is there.
May be worth getting a logic analyzer hooked onto the bus. Below a trace of some of the master -> slave transmit data from the example.
2018-04-28 12:55 PM
Look also at
https://github.com/cnoviello/mastering-stm32/blob/master/nucleo-f103RB/src/ch14/main-ex2.c
, it is in line with what you are trying to do.2018-10-24 05:38 AM
In line 88, data is passed to the master.
But what if the master will write? How to find out in advance will be written or read the second byte?