cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F3 (stm32f303vct6) + i2c + CMSIS

kudlata
Associate II
Posted on August 18, 2014 at 17:08

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
5 REPLIES 5
stm322399
Senior
Posted on August 18, 2014 at 17:34

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.

setartarney
Associate II
Posted on August 18, 2014 at 18:07

Check the i2c buffer, maybe it is full.

kudlata
Associate II
Posted on August 18, 2014 at 19:43

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. :(
stm322399
Senior
Posted on August 18, 2014 at 20:37

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;

kudlata
Associate II
Posted on August 24, 2014 at 19:33

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;