AnsweredAssumed Answered

I2C Slave

Question asked by stevens.mark on May 17, 2015
Latest reply on May 23, 2015 by stevens.mark
I've been trying to work out how to make the STM8S act as an I2C slave and to be honest I'm failing.  I think I've set everything up according to the reference manual but for some reason I'm not getting the expected interrupts being fired.

I have a Netduino setup as an I2C master.  The logic analyser and the scope both show a write and an address of 0x02 and a NAK being generated on the I2C bus.

I was expecting the STM8S to generate an ACK and an interrupt to request data or to send data.  At the very least I was expecting an interrupt to be generated.

I know the interrupt handler is being wired up as I get an error interrupt when I recompile the Netduino code and it redeploys.  At this time it messes up the I2C bus.

The STM8S application code is:

#include <iostm8s103f3.h>
#include <intrinsics.h>
//
//  I2C interrupts all share the same handler.
//
#pragma vector = I2C_RXNE_vector
__interrupt void I2C_IRQHandler()
{
    if (I2C_SR1_RXNE)
    {
        unsigned char data;
        data = I2C_DR;
    }
    if (I2C_SR1_TXE)
    {
        I2C_DR = 0xaa;                  //  Some dummy data to send.
    }
}
//
//  Setup the system clock.
//
void InitialiseSystemClock()
{
    CLK_ICKR = 0;                       //  Reset the Internal Clock Register.
    CLK_ICKR_HSIEN = 1;                 //  Enable the HSI.
    CLK_ECKR = 0;                       //  Disable the external clock.
    while (CLK_ICKR_HSIRDY == 0);       //  Wait for the HSI to be ready for use.
    CLK_CKDIVR = 0;                     //  Ensure the clocks are running at full speed.
    CLK_PCKENR1 = 0xff;                 //  Enable all peripheral clocks.
    CLK_PCKENR2 = 0xff;                 //  Ditto.
    CLK_CCOR = 0;                       //  Turn off CCO.
    CLK_HSITRIMR = 0;                   //  Turn off any HSIU trimming.
    CLK_SWIMCCR = 0;                    //  Set SWIM to run at clock / 2.
    CLK_SWR = 0xe1;                     //  Use HSI as the clock source.
    CLK_SWCR = 0;                       //  Reset the clock switch control register.
    CLK_SWCR_SWEN = 1;                  //  Enable switching.
    while (CLK_SWCR_SWBSY != 0);        //  Pause while the clock switch is busy.
}
//
//  Setup I2C.
//
void InitialiseI2C()
{
    I2C_CR1_PE = 0;                     //  Diable I2C before configuration starts.
    //
    //  Setup the clock information.
    //
    I2C_FREQR = 16;                     //  Set the internal clock frequency (MHz).
    I2C_CCRH_F_S = 0;                   //  I2C running is standard mode.
    I2C_CCRL = 0xa0;                    //  SCL clock speed is 50 KHz.
    I2C_CCRH_CCR = 0x00;
    //
    //  Set the address of this device.
    //
    I2C_OARL_ADD = 0x02;                //  Seven bit address.
    I2C_CR1_ENGC = 1;                   //  Enable the general call address.
    I2C_OARH_ADDMODE = 0;               //  7 bit address mode.
    I2C_OARH_ADDCONF = 1;               //  Docs say this must always be 1.
    //
    //  Setup the bus characteristics.
    //
    I2C_CR2_ACK = 1;
    I2C_TRISER = 17;
    //
    //  Turn on the interrupts.
    //
    I2C_ITR_ITBUFEN = 1;                //  Buffer interrupt enabled.
    I2C_ITR_ITEVTEN = 1;                //  Event interrupt enabled.
    I2C_ITR_ITERREN = 1;
    //
    //  Configuration complete so turn the peripheral on.
    //
    I2C_CR1_PE = 1;
}
int main()
{
    __disable_interrupt();
    InitialiseSystemClock();
    InitialiseI2C();
    __enable_interrupt();
    while (1)
    {
        __wait_for_interrupt();
    }
}

Can anyone see where I'm going wrong?

Regards,
Markl

Outcomes