AnsweredAssumed Answered

STM8S003F3 I2c master-slave problem

Question asked by A2 on Oct 29, 2014
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;
         
    }
 
}




Outcomes