2017-12-14 01:21 PM
Hi,
I'm using a STM32F429l-DISC1 Board and trying to get I2C working.
Somehow my code fails, and I come back to the code from:
https://sites.google.com/site/johnkneenmicrocontrollers/18b-i2c/i2c_stm32f407
Now I want to send the adress 0x66, then the Data 0x24 and 0x04. This is working perfectly,
but then I want to send the Address 0x67 which still works, then 0x24 and 0x04 which does not work, because the I2C TX Resgister is missing the correct falue!
Strangely I get on the I2C Bus a 0xBE after the 0x67 address!
See logic analyser: ?
Logic analyser Data
Time [s], Analyzer Name, Decoded Protocol Result
2.639135875000000,I2C,Setup Write to [0x66] + ACK
2.639227250000000,I2C,0x24 + ACK
2.639317562500000,I2C,0x04 + ACK
2.639424625000000,I2C,Setup Read to [0x67] + ACK
2.639514875000000,I2C,0xBE + NAK
?
My Full code is here
&sharpinclude 'stm32f4xx.h'
&sharpdefine WORKING GPIOD->ODR ^= 1<<15
&sharpdefine ACTION GPIOD->ODR |= 1<<11
&sharpdefine ACTION_E GPIOD->ODR &= ~(1<<11)
&sharpdefine ADDRESS GPIOD->ODR |= 1<<12
&sharpdefine ADDRESS_E GPIOD->ODR &= ~(1<<12)
&sharpdefine WRITE GPIOD->ODR |= 1<<13
&sharpdefine WRITE_E GPIOD->ODR &= ~(1<<13)
&sharpdefine READ GPIOD->ODR |= 1<<14
&sharpdefine READ_E GPIOD->ODR &= ~(1<<14)
void I2C_Start() {
ACTION;//To highlight start on MSO
I2C1->CR1 |= 1<<8; //I2C Start
while (!(I2C1->SR1 & 0x0001));//wait for start bit
}//subsequent access of data register will clear start bit
void I2C_Stop (void) {
I2C1->CR1 |= 0x0200;
while (I2C1->SR2 & 0x0002); //wait for BUSY set
ACTION_E; //Highlight stop on MSO
}//I2C Transfer now complete
void I2C_Write (unsigned char c) {
WRITE;//Indicate write on MSO
I2C1->DR = c;
while (!(I2C1->SR1 & (1<<7))); // Wait TxE bit set - <A HREF='&sharplinkSR'>see status register</A>
WRITE_E;
}//Could also wait until BTF (Byte Transfer Complete)
unsigned char I2C_Read (int ack) {
READ; //Indicate read on MSO
if (ack) I2C1->CR1 |= 0x0400; //multiple bytes - set acknowledge bit in<A HREF='&sharplinkcontrol'> I2C_CR1</A>
else I2C1->CR1 &= ~0x0400; //single or last byte clear ack bit
// while (!(I2C1->SR1 & 0x00000040)); // Wait until RxNE bit set - <A HREF='&sharplinkSR'>see status register</A>
READ_E;
return (I2C1->DR);
}
void I2C_Address (unsigned char adr) {
char res;
ADDRESS; //Signal for MSO
I2C1->DR = adr | 0; //Write to I2C Address register
while (!(I2C1->SR1 & 0x0002)); //wait until address sent
res = (I2C1->SR2); //dummy read to clear
ADDRESS_E;
}
void Delay( ) {
int i;
for (i=0; i<400000; i++);
}
int main ( ) {
RCC->AHB1ENR |= 1<<3; //Clocks for GPIOD
GPIOD->MODER |= 0x55400000; //Bits 11..15 are output
GPIOD->MODER |= 1<<8; //PB4 reset to CS43L22
GPIOD->ODR |= 1<<4; //set high
//configure the AF
RCC->AHB1ENR |= 1<<1; //Clock for GPIOB
RCC->APB1ENR |= 1 <<21; //clock to I2C1
GPIOB->AFR[0] |= (4<< 24); //enable SCK to PB6
GPIOB->AFR[1] |= (4<< 4); //enable SDA to PB9
GPIOB->MODER &= ~(3 << 12); //clear bits 12 & 13 (PB6)
GPIOB->MODER |= 2 << 12; //MODER6[1:0] = 10 bin
GPIOB->MODER &= ~(3 << 18); //clear bits 18 & 19 (PB9)
GPIOB->MODER |= 2 << 18; //MODER9[1:0] = 10 bin
GPIOB->OTYPER |= 1 <<6; //PB6 open drain
GPIOB->OTYPER |= 1<<9; //PB9 open drain
GPIOB->PUPDR &= ~(3 << 12);//clear bits 12 & 13 (PB6)
GPIOB->PUPDR &= ~(3 << 18);//clear bits 18 & 19 (PB9)
//Configure the I2C
I2C1->CR2 = 0x0010; //16MHz HSI
I2C1->CCR = 0x0050; //100kHz Bit rate
I2C1->TRISE = 0x0011; //1000 ns / 62.5 ns = 16 + 1
I2C1->CR1 = 0x0001; //enable peripheral
char res;
while (1){
I2C_Start();
I2C_Address(0x66); //Write address of slave
I2C_Write (0x24);
I2C_Write (0x04);
I2C_Start();
I2C_Address(0x67);
I2C_Write (0x24);
I2C_Write (0x04);
I2C_Stop();
Delay();
WORKING; //visible indication that I2C didn't stall
}
}
Does anyone know how to fix my problem? any advice?
Thank you
##i2c ##stm32f42017-12-14 02:56 PM
Look, the low order bit of the I2C address defines the direction of the transaction (high order 7-bit slave address, low order R/W bit). Writing a ONE indicates you're READING, so you can't jam data back at the Slave.