2020-12-23 10:11 AM
Hi all i dont know what happen to the i2c line just after the address acknowledgement the SCL line goes LOW while SDA high and after that if i am sending data through data register I2C1_DR there is no response.Point to note that that if i initialize the I2C1 two times than again similar output(shown in output.png below) got two time but still no data transfers that means it stuck in data only while for address there is no problem .I check the the frequency of generated wave and it is 100khz which is accepted by our slave PCF8574 .Here I am using IAR EWARM for programming because i want to understand the proper register initialization & for slave PCF8574 GPIO extender..thanks please help
#include <ST/iostm32f100xB.h>
void I2c_sendata(char);
void i2c_init();
void delay(void);
int main()
{
i2c_init();
while(1)
{
I2c_sendata('k');
delay();
}
return 0;
}
void i2c_init()
{
/***********************************************************************************/
//PB6(SCL) and PB7(SDA)
I2C1_CR1_bit.SWRST=1;//I2C Peripheral under reset state(Before resetting this bit, make sure the I2C lines are released and the bus is free.)
RCC_APB2ENR_bit.IOPBEN=1;//Enable clock of port b
RCC_APB1ENR_bit.I2C1EN=1;//Enable I2C1
// RCC_APB2ENR_bit.AFIOEN=1;//Alternate function IO enable
GPIOB_CRL_bit.MODE6=0x1;//Output mode, max speed 10 MHz
GPIOB_CRL_bit.MODE7=0x1;//Output mode, max speed 10 MHz
/*For bidirectional Alternate Functions, the port bit must be configured in Alternate Function Output mode (Push-Pull or Open-Drain).
In this case the input driver is configured in input floating mode*/
GPIOB_CRL_bit.CNF6=0x3;//Alternate function output as open drain while input as floating
GPIOB_CRL_bit.CNF7=0x3;//Alternate function output as open drain while input as floating
I2C1_CR1_bit.ACK=1;//Enable Acknowledgement(Acknowledge returned after a byte is received (matched address or data)
I2C1_CR2_bit.ITBUFEN=1;//this will enable flag for Tx buffer empty,Rx buffer not empty
I2C1_CR2_bit.ITEVTEN=1;//this will enable flag for SB(start bit sent when Master),stop bit received when slave(STOPF)
I2C1_CCR_bit.F_S=0;//Standard mode 0 /Fast mode 1
/*************************************************************************************/
//delay();
I2C1_CR1_bit.PE=0;//disable pheripheral ,otherwise it is not allowed to make any changes in other register
I2C1_CR2=0x0008;//APB set to 8MHZ (other way 0b001000)
/* In Sm mode, to generate a 100 kHz SCL frequency: If FREQR = 08, TPCLK1 = 125 ns so CCR must be programmed with 0x28(0x28 <=> 40d x 125 ns = 5000 ns.)*/
I2C1_CCR=0x0028;
/*In Sm mode, the maximum allowed SCL rise time is 1000 ns.If, in the I2C_CR2 register, the value of FREQ[5:0] bits is equal to 0x08 and
TPCLK1= 125 ns therefore the TRISE[5:0] bits must be programmed with 09h */
I2C1_TRISE=0x0009;//TRISE[5:0] must be configured only when the I2C is disabled (PE = 0).Thaths why i write it before enabling PE of I2C1_CR1
//I2C1_DR=(0x20<<1)|(0x00000000);//send address and than write(Master Transmitter)
I2C1_CR1_bit.PE=1;//enable pheripheral
I2C1_CR1_bit.START=1;//Start/Repeated Start
while(!(I2C1_SR1_bit.SB));//wait for
I2C1_DR=0x4E;
//while(!(I2C1_SR1_bit.AF)); //End of address transmission(the bit is set after the ACK of the byte)
}
void I2c_sendata(char data)
{
I2C1_DR=data;
while(!(I2C1_SR1_bit.TxE));
//I2C1_CR1_bit.STOP=1;//End Termination
}
void delay(void){
int i = 1000000; /* About 1/4 second delay */
while (i-- > 0)
asm("nop");
}
2020-12-23 10:50 AM
Something is holding down the clock, possible the slave or master.
https://www.i2c-bus.org/i2c-primer/clock-generation-stretching-arbitration/
The little hiccup at your cursor isn't a valid I2C signal. Could be related to that. Can't have SCL go low while SDA is high. You could avoid initializing the pins as AF until the peripheral is active to avoid this.
2020-12-23 01:52 PM
Exceedingly few people are going to be interested in unpacking and debugging others register level code.
Test if it works with standard libraries (SPL, HAL, etc) and if it does, then unwind the code from there and check the sequences/nuances against your own implementation.
2020-12-23 07:27 PM
Sir actually i followed the same approach as you told that first created the project in STM32 cube IDE and than from there tried to follow the sequences....But the problem with this approach is (correct me if i am wrong) there is no concept of register is there instead everything is address Like if i trace I2C1 than it lead me to:
"#define I2C1_BASE (APB1PERIPH_BASE + 0x00005400UL)" which is very difficult to trace one by one.I know register on the background pointing to some address but it is very difficult to trace through address instead register.............please correct me if i am wrong..thanks and waiting for you answer
2020-12-23 07:34 PM
But why Master/Slave holding down the clock sir...i have two different SLAVES i have tested with both but both of them showing similar behavior..any suggestion sir
2020-12-23 07:55 PM
Typically one looks at the peripherals with the help of the IDE debugger. The SFRs tab in STM32CubeIDE, for instance.
2020-12-23 07:57 PM
Like I said in the post, it could be because the I2C signal you're providing is invalid. I'd fix that before anything else.