cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F030 Nucleo: Bit-Banging I²C to DS1338 RTC returning 0xFFFF

niranukroshah
Associate

Hi Guys, for an internship I am making a dual channel datalogger. So for that datalogger, I am using DS1338 RTC. Now instead of doing I2C normally, I am doing Bit-banging.

 

I am using Nucleo-F030R8 board for my prototyping and I am using PA0(SDA) and PA1(SDA). 

 

After using DSO I was able to verify start condition, stop condition and slave address transfer. Also I tried to test ack by manually pulling the sda down and the output was as expected. 

 

Now the issue is I am not able to write or read the RTC and I am getting FFFF while reading it. And there are no hardware issues as I have tested the RTC. This makes me think there is problem with my I2C read function.

 

Following is the snippet of code I am using for this purpose -

#define I2C1_SDA_HIGH()    (GPIOA->BSRR = (1U << SDA1_PIN))
#define I2C1_SDA_LOW()     (GPIOA->BSRR = (1U << (SDA1_PIN + 16)))

#define I2C1_SCL_HIGH()    (GPIOA->BSRR = (1U << SCL1_PIN))
#define I2C1_SCL_LOW()     (GPIOA->BSRR = (1U << (SCL1_PIN + 16)))

#define I2C1_SDA_READ()    ((GPIOA->IDR >> SDA1_PIN) & 0x1)


#define I2C1_SDA_INPUT()   (GPIOA->MODER &= ~(3U << (SDA1_PIN * 2))) // Input mode = 00
#define I2C1_SDA_OUTPUT()  (GPIOA->MODER = (GPIOA->MODER & ~(3U << (SDA1_PIN * 2))) | (1U << (SDA1_PIN * 2)))

UINT8 i2c1_getdata(void)
{
    UINT8 dat = 0;

    I2C1_SDA_HIGH();       
    I2C1_SDA_INPUT();      

    for(UINT8 i = 0; i < 8; i++)
    {
        dat <<= 1;

        I2C1_SCL_HIGH();
        delay_us(I2C1_DELAY);

        if(I2C1_SDA_READ()) dat |= 0x01;

        I2C1_SCL_LOW();
        delay_us(I2C1_DELAY);
    }

    I2C1_SDA_OUTPUT();     
    return dat;
}

void i2c1_opdata(UINT8 dat)
{
    for(UINT8 i = 0; i < 8; i++)
    {
        if(dat & 0x80) I2C1_SDA_HIGH();
        else I2C1_SDA_LOW();

        I2C1_SCL_HIGH();  
        delay_us(I2C1_DELAY);
        I2C1_SCL_LOW();   
        delay_us(I2C1_DELAY);

        dat <<= 1;
    }

    
    i2c1_waitack();
}
void i2c1_waitack(void)
{
    I2C1_SDA_HIGH();      
    I2C1_SDA_INPUT();    

    i2c1_wait_tout = I2C1_WAIT_TOUT;

    I2C1_SCL_LOW();
    delay_us(I2C1_DELAY);

    I2C1_SCL_HIGH();       
    delay_us(I2C1_DELAY);

    while (I2C1_SDA_READ()) 
    {
        if (i2c1_wait_tout-- == 0) break; // Timeout
        delay_us(5);
    }

    I2C1_SCL_LOW();        
    delay_us(I2C1_DELAY);

    I2C1_SDA_OUTPUT();     
}

Help will be really appreciated!

 

Footnotes-

 

1)delay_us() is a software delay, hence not very precise, but I have fine tuned the I2C1_delay to get 100khz SCL

 

2)The time out for ack after calculating came out to be almost 5 us, considering 48Mhz sysclock.

 

10 REPLIES 10

Maybe best is say menthor , dont waste money and time, write some code for bitbang existing hw interface on same MCU .