cancel
Showing results for 
Search instead for 
Did you mean: 

STM8S003F3 I2c master-slave problem

aamirali641989
Associate II
Posted on October 29, 2014 at 13:28

I have two STM8 boards. One is master & other is slave.

What master does is: send 4 bytes to slave & then read 4 bytes from slave. Problem: Sometimes the cycle work & many times code is stuck. I don't know what exactly is the problem. Master code:

/* definition of fast or default standard mode (bus speed up to 400 or 100 kHz) */
#define FAST_I2C_MODE
#ifdef FAST_I2C_MODE
#define I2C_SPEED 300000
#else
#define I2C_SPEED 100000
#endif
/* definition of 10-bit or default 7-bit slave address */
/* #define TEN_BITS_ADDRESS */
#define OWN_ADDRESS 0xa0 
#define SLAVE_ADD_1 0x30 
/* This define is used in master receiver */
/* Uncomment the line below if you want to use the safe procedure */
#define SAFE_PROCEDURE
#define BUFFERSIZE 4
volatile uint8_t TxBuffer[BUFFERSIZE];
volatile uint8_t RxBuffer[BUFFERSIZE];
volatile uint8_t NumOfBytes;
volatile uint8_t NumByteToRead;
volatile uint8_t slave_add;
volatile uint8_t Rx_Idx;
volatile uint8_t Tx_Idx;
int main(void)
{
uint8_t test_i2c[4] = {0xaaU , 0x55U , 0xf0U , 0x0fU};
/* init sys clock to internal 16Mhz HSI & peripheral clock divider = 1 */
set_system_clock();
I2C_DeInit();
/* I2C Initialize */
I2C_Init(I2C_SPEED, OWN_ADDRESS, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 16);
enableInterrupts(); 
i2c_send_receive_4_bytes(SLAVE_ADD_1 , test_i2c);
}
void i2c_send_receive_4_bytes(uint8_t temp_slave_add , uint8_t tx_data[]) 
{
uint8_t cnt;
/* set vars */
Tx_Idx = 0U;
Rx_Idx = 0U;
NumOfBytes = BUFFERSIZE;
NumByteToRead = BUFFERSIZE;
/* fill vars */
slave_add = temp_slave_add;
for(cnt = 0U ; cnt < BUFFERSIZE ; cnt++)
{
TxBuffer[cnt] = tx_data[cnt];
}
/* Enable Buffer and Event Interrupt*/
I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_EVT | I2C_IT_BUF) , ENABLE); 
/* Send START condition */
I2C_GenerateSTART(ENABLE); 
while(NumOfBytes);
while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY));
/* Add a delay to be sure that communication is finished */
Delay(0xffffU); 
/***** reception phase ***/
/* Wait while the bus is busy */
while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); 
/* Send START condition */
I2C_GenerateSTART(ENABLE); 
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)); 
/* Send slave Address for write */
I2C_Send7bitAddress(slave_add, I2C_DIRECTION_RX);
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); 
/* While there is data to be read */
while(NumByteToRead)
{
#ifdef SAFE_PROCEDURE
if(3U != NumByteToRead) /* Receive bytes from first byte until byte N-3 */
{
while((RESET == I2C_GetFlagStatus(I2C_FLAG_TRANSFERFINISHED))); /* Poll on BTF */
/* Read a byte from the Slave */
RxBuffer[Rx_Idx] = I2C_ReceiveData();
/* Point to the next location where the byte read will be saved */
Rx_Idx++;
/* Decrement the read bytes counter */
NumByteToRead--;
}
if(3U == NumByteToRead) /* it remains to read three data: data N-2, data N-1, Data N */
{
/* Data N-2 in DR and data N -1 in shift register */
while((RESET == I2C_GetFlagStatus(I2C_FLAG_TRANSFERFINISHED))); /* Poll on BTF */
/* Clear ACK */
I2C_AcknowledgeConfig(I2C_ACK_NONE);
/* Disable general interrupts */
disableInterrupts();
/* Read Data N-2 */
RxBuffer[Rx_Idx] = I2C_ReceiveData();
/* Point to the next location where the byte read will be saved */
Rx_Idx++;
/* Program the STOP */
I2C_GenerateSTOP(ENABLE);
/* Read DataN-1 */
RxBuffer[Rx_Idx] = I2C_ReceiveData();
/* Enable General interrupts */
enableInterrupts();
/* Point to the next location where the byte read will be saved */
Rx_Idx++;
while((RESET == I2C_GetFlagStatus(I2C_FLAG_RXNOTEMPTY))); /* Poll on RxNE */
/* Read DataN */
RxBuffer[Rx_Idx] = I2C_ReceiveData();
/* Reset the number of bytes to be read by master */
NumByteToRead = 0U;
}
#else
if(1U == NumByteToRead)
{
/* Disable Acknowledgement */
I2C_AcknowledgeConfig(I2C_ACK_NONE);
/* Send STOP Condition */
I2C_GenerateSTOP(ENABLE);
/* Poll on RxNE Flag */
while((RESET == I2C_GetFlagStatus(I2C_FLAG_RXNOTEMPTY)));
/* Read a byte from the Slave */
RxBuffer[Rx_Idx] = I2C_ReceiveData();
/* Point to the next location where the byte read will be saved */
Rx_Idx++;
/* Decrement the read bytes counter */
NumByteToRead--;
}
/* Test on EV7 and clear it */
if(I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED) )
{
/* Read a byte from the EEPROM */
RxBuffer[Rx_Idx] = I2C_ReceiveData();
/* Point to the next location where the byte read will be saved */
Rx_Idx++;
/* Decrement the read bytes counter */
NumByteToRead--;
}
#endif /* SAFE_PROCEDURE */
} 
/* Add a delay to be sure that communication is finished */
Delay(0xffffU); 
}
INTERRUPT_HANDLER(I2C_IRQHandler, 19)
{
switch(I2C_GetLastEvent())
{
/* EV5 */
case I2C_EVENT_MASTER_MODE_SELECT :
/* Send slave Address for write */
I2C_Send7bitAddress(slave_add, I2C_DIRECTION_TX); 
break; 
/* EV6 */
case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
if(0U != NumOfBytes)
{
/* Send the first Data */
I2C_SendData(TxBuffer[Tx_Idx++]);
/* Decrement number of bytes */
NumOfBytes--;
}
if(0U == NumOfBytes)
{
I2C_ITConfig(I2C_IT_BUF, DISABLE);
}
break; 
/* EV8 */
case I2C_EVENT_MASTER_BYTE_TRANSMITTING:
/* Transmit Data */
I2C_SendData(TxBuffer[Tx_Idx++]);
/* Decrement number of bytes */
NumOfBytes--;
if(0U == NumOfBytes)
{
I2C_ITConfig(I2C_IT_BUF, DISABLE);
}
break;
/* EV8_2 */
case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
/* Send STOP condition */
I2C_GenerateSTOP(ENABLE);
I2C_ITConfig(I2C_IT_EVT, DISABLE);
break;
default:
break; 
}
}

Slave code:

#define FAST_I2C_MODE
#ifdef FAST_I2C_MODE
#define I2C_SPEED 300000
#else
#define I2C_SPEED 100000
#endif
/* definition of 10-bit or default 7-bit slave address */
/* #define TEN_BITS_ADDRESS */
#define OWN_ADDRESS 0xa0 
#define SLAVE_ADD_1 0x30
#define SLAVE_ADD_2 0x31
#define SLAVE_ADD_3 0x32
#define SLAVE_ADD_4 0x33 
/* This define is used in master receiver */
/* Uncomment the line below if you want to use the safe procedure */
#define SAFE_PROCEDURE
#define BUFFERSIZE 4
volatile uint8_t TxBuffer[BUFFERSIZE];
volatile uint8_t RxBuffer[BUFFERSIZE];
volatile uint8_t Rx_Idx;
volatile uint8_t Tx_Idx;
volatile uint16_t Event;
volatile uint8_t comm_complete;
int main(void)
{
uint8_t test_i2c[4] = {0xaaU , 0x55U , 0xf0U , 0x0fU};
uint8_t test_rx[4];
/* init sys clock to internal 16Mhz HSI & peripheral clock divider = 1 */
set_system_clock();
I2C_DeInit();
/* I2C Initialize */
I2C_Init(I2C_SPEED, SLAVE_ADD_1, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, MHZ_SYS_FREQ);
/* Enable Error Interrupt*/
I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF), ENABLE); 
enableInterrupts();
i2c_send_receive_4_bytes(test_i2c , test_rx);
}
void i2c_send_receive_4_bytes(uint8_t tx_data[] , uint8_t rx_data[]) 
{
uint8_t cnt;
/* fill vars */
for(cnt = 0U ; cnt < 
BUFFERSIZE
; cnt++)
{
TxBuffer[cnt] = tx_data[cnt];
}
comm_complete
= 
0U
;
/* wait while comm complete */
while(0U == comm_complete);
/* disable interrupt */
disableInterrupts();
comm_complete
= 
0U
;
/* fill the rx arr */ 
for(
cnt
= 
0U
; cnt < BUFFERSIZE ; cnt++)
{
rx_data[cnt] = RxBuffer[cnt];
} 
/* Enable general interrupts */
enableInterrupts(); 
} /* function ends here */ 
INTERRUPT_HANDLER(I2C_IRQHandler, 19)
{
/* Read SR2 register to get I2C error */
if(0U != (I2C->SR2))
{
/* Clears SR2 register */
I2C->SR2 = 0U;
}
Event = I2C_GetLastEvent();
switch(Event)
{
/******* Slave transmitter ******/
/* check on EV1 */
case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:
Tx_Idx = 0U;
break;
/* check on EV3 */
case I2C_EVENT_SLAVE_BYTE_TRANSMITTING:
/* Transmit data */
I2C_SendData(TxBuffer[Tx_Idx++]);
if(BUFFERSIZE == Tx_Idx)
{
comm_complete = 1U;
} 
break;

/******* Slave receiver **********/
/* check on EV1*/
case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
Rx_Idx = 0U;
break;
/* Check on EV2*/
case I2C_EVENT_SLAVE_BYTE_RECEIVED:
RxBuffer[Rx_Idx++] = I2C_ReceiveData();
break;
/* Check on EV4 */
case (I2C_EVENT_SLAVE_STOP_DETECTED):
/* write to CR2 to clear STOPF flag */
I2C->CR2 |= I2C_CR2_ACK;
break;
default:
break; 
}
}

0 REPLIES 0