2025-10-08 11:14 AM
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.
2025-10-08 11:20 AM
Are pins in open-drain mode?
Can you show a logic analyzer capture of what's happening? Do you get an ACK?
You show functions, but not the larger context that calls them.
2025-10-08 11:44 AM
Yes, I have configured the pins as open drain, so that isn't the problem.
Following are the outputs i observed on the dso-
This is the start condition
And this is the slave address.
And about ACK, i manually pulled the sda down but I didn't get time to check for RTC. But it is working as the HAL code was functional.
And for the larger context, following is the flow(I am unable to provide full code as my mentor has placed some restrictions)-
Please do point out if I am making any mistake here.