2018-04-24 3: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 4: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 5: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 4: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 5: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?
We’re moving the ST Community to a new platform to give you a better and more reliable community experience.