2014-08-18 08:08 AM
I'm trying to connect this port to i2c standard PCF8574 I/O expander.
And I can't get it to work. My GPIO init code:
RCC->APB1ENR |= ( RCC_APB1ENR_I2C1EN | RCC_APB1ENR_I2C2EN );
RCC->AHBENR |= ( RCC_AHBENR_GPIOAEN );
if ( hi2c == I2C2 ) {
GPIOA->MODER |= ( GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1 );
GPIOA->OTYPER |= ( GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10 );
GPIOA->OSPEEDR &= ~( GPIO_OSPEEDER_OSPEEDR9 | GPIO_OSPEEDER_OSPEEDR10 );
GPIOA->AFR[1] |= ( (GPIO_AFRH_AFRH1 & 0x0100) | (GPIO_AFRH_AFRH2 & 0x0100) );
}
if ( hi2c == I2C1 ) {
GPIOA->MODER |= ( GPIO_MODER_MODER14_1 | GPIO_MODER_MODER15_1 );
GPIOA->OTYPER |= ( GPIO_OTYPER_OT_14 | GPIO_OTYPER_OT_15 );
GPIOA->OSPEEDR &= ~( GPIO_OSPEEDER_OSPEEDR14 | GPIO_OSPEEDER_OSPEEDR15 );
GPIOA->AFR[1] |= ( (GPIO_AFRH_AFRH6 & 0x0100) | (GPIO_AFRH_AFRH7 & 0x0100) );
}
My I2C Init code:
// clear PE
hi2c->CR1 &= ~I2C_CR1_PE;
hi2c->CR1 = 0x00;
// ANFOFF =1 _ Analog noise filter disabled;
// DNF =0 _ Digital filter disabled;
hi2c->CR1 = 0x1000;
// SCLL =45
// SCLH =29
// SDADEL =0;
// SCLDEL =1;
// PRESC =0;
hi2c->TIMINGR = 0x101D2D;
// NOSTRETCH =1 _ Clock stretching disabled
hi2c->CR1 |= I2C_CR1_NOSTRETCH;
// set PE
hi2c->CR1 |= I2C_CR1_PE;
My MasterRead code:
// addressing mode _ 0: The master operates in 7-bit addressing mode
hi2c->CR2 &= ~I2C_CR2_ADD10;
// slave address to be sent _
hi2c->CR2 |= (address <<
1
);
// Transfer direction _ 1: Master requests a read transfer.
hi2c->CR2 |= I2C_CR2_RD_WRN;
// the number of bytes to be transferred _ NBYTES 23-16b
hi2c->CR2 |= dataSize <<
16
;
while( (hi2c->ISR & I2C_ISR_BUSY) == I2C_ISR_BUSY );
hi2c->CR2 |= I2C_CR2_START;
// 1: Automatic end mode: a STOP condition is automatically sent when NBYTES data are transferred.
// 0: software end mode: TC flag is set when NBYTES data are transferred, stretching SCL low.
hi2c->CR2 |= I2C_CR2_AUTOEND;
while ( dataSize ) {
// I2Cx_ISR.RXNE =1?
while( (hi2c->ISR & I2C_ISR_RXNE) != I2C_ISR_RXNE );
//YES
*data = hi2c->RXDR;
data++;
dataSize--;
}
//hi2c->CR2 |= I2C_CR2_STOP;
while( (hi2c->ISR & I2C_ISR_STOPF) != I2C_ISR_STOPF );
And it all stops on
while( (hi2c->ISR & I2C_ISR_RXNE) != I2C_ISR_RXNE );
line.
On osciloscope I don't see any START... etc.
I can't figure out what am I doing wrong...
#i2c #stm32f3 #stm32f303vct6
2014-08-18 08:34 AM
Are SCL/SDA correctly pulled high (use MCU internal pull-up when the board does not provide pull-up resistor) ? What are levels of SCL/SDA observed on the oscilloscope.
2014-08-18 09:07 AM
Check the i2c buffer, maybe it is full.
2014-08-18 10:43 AM
gonzalez.laurent
Are SCL/SDA correctly pulled high (use MCU internal pull-up when the board does not provide pull-up resistor) ? What are levels of SCL/SDA observed on the oscilloscope. I 've pulled SDA/SCL through 10kOhm to 5V. Internal pull-ups aren't connected.GPIOA->PUPDR &= ~( GPIO_PUPDR_PUPDR9 | GPIO_PUPDR_PUPDR10 );
&
GPIOA->PUPDR &= ~( GPIO_PUPDR_PUPDR14 | GPIO_PUPDR_PUPDR15 );
And that's strange.
Nothing shows, even after reset of the board.
Probably I don't configure something.
vadoud.ali
Check the i2c buffer, maybe it is full.
No, it's not. :(
2014-08-18 11:37 AM
The init of AFR registers looks suspicious, and is probably wrong.
Take care to erase the bits you don't need and set the ones you need like: REG = (REG & ~MASK) | VALUE;2014-08-24 10:33 AM
Thank you.
I've found my mistake.
1.
GPIOA->AFR[0] = 0x00;
2.
GPIOA->AFR[1] |= ( (0x04 <<4) | ( 0x04 <<8 ) );
Earlier, I meant hex but wrote in bits.
Interesting right now is that I don't know why, but when I'm trying read i2c in master and I'm setting AUTOEND mode, a STOP bit is not being sent.
1.
// 1: Automatic end mode: a STOP condition is automatically sent when NBYTES data are transferred.
2.
// 0: software end mode: TC flag is set when NBYTES data are transferred, stretching SCL low.
3.
hi2c->CR2 |= I2C_CR2_AUTOEND;
I have to sent it manually:
1.
hi2c->CR2 |= I2C_CR2_STOP;