cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L4xx I2C Interrupts

DPyke
Associate II

Please can you help me. I cannot use the HAL as I have to write an ultra low power/ minimalist application. I need to Tx/Rx a few bytes over I2C3 . I have set it up as below but I do not get any interrupts, either event or errors. Can you tell me what I am doing wrong, thank you

I am setting up the I2C interface :

RCC->APB1ENR1 |= RCC_APB1ENR1_I2C3EN;

I2C3->CR1 = (I2C_CR1_WUPEN|I2C_CR1_ERRIE|I2C_CR1_TCIE|I2C_CR1_TXI|I2C_CR1_STOPIE);

I2C3->CR2 = ( I2C_CR2_AUTOEND);

I2C3->TIMINGR = ((0x00000000 & ~(I2C_TIMINGR_PRESC_Msk|I2C_TIMINGR_SCLDEL_Msk|I2C_TIMINGR_SDADEL_Msk|I2C_TIMINGR_SCLH_Msk|I2C_TIMINGR_SCLL_Msk))\

|( 0x03 << I2C_TIMINGR_PRESC_Pos)\

|( 0x04 << I2C_TIMINGR_SCLDEL_Pos)\

|( 0x02 << I2C_TIMINGR_SDADEL_Pos)\

|( 0x0f << I2C_TIMINGR_SCLH_Pos)\

|( 0x13 << I2C_TIMINGR_SCLL_Pos));

(I do other things too, (I set the GPIO pins to alt Fn)

When I read back the contents of the reg I get)

CR1 = 0x00008023

CR2 = 0x000400e3

ISR = 0x022c2070

To transmit:

RCC->APB1ENR1 |= RCC_APB1ENR1_I2C3EN; // AHB1 Peripheral Clock Enable

I2C3->CR1 |= I2C_CR1_PE;  // I2C3 Enable 

I2C3->CR2 &= ~(I2C_CR2_NBYTES_Msk | I2CADDRESSBITS | I2C_CR2_RD_WRN); // Clear Addr

I2C3->CR2 |= Address; // address of target

I2C3->CR2 |= (NumberOfBytes<<I2C_CR2_NBYTES_Pos); // setup number of bytes

I2C3->TXDR = Data; // Transmit data

I2C3->CR1 |= (I2C_CR1_TXIE|I2C_CR1_TCIE|I2C_CR1_STOPIE|I2C_CR1_ERRIE); // AGAIN!

I2C3->CR2 |= I2C_CR2_START; // START Tx

It successfully transmits one byte @ 100Khz (16MHz operation)

The flags are set but it never goes to I2C3_EV_IRQHandler or I2C3_ER_IRQHandler

Is there global interrupt mask I need to set?

I would appreciated any help, thank you

7 REPLIES 7

NVIC_EnableIRQ(I2C3_EV_IRQn);

NVIC_EnableIRQ(I2C3_ER_IRQn);

JW

PS. You don't need line continuation (backslashes) in C code, only in preprocessor macros (#define).

Did you enable the interrupt in NVIC? Something like this:

NVIC_SetPriority(I2C3_ER_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 3, 0));

NVIC_EnableIRQ(I2C3_ER_IRQn);

edit: was late :)

Excellent, thank you for your help, I will give that a ago ASAP

The timers worked fine without setting a priority and when I looked at the I2C3 interrupts it said that there were priority default of 79, 80 ? I will set them manually and hope that brings this to life

Backslashes : I cut and pasted the code from a macro to make it easier to see :)

DPyke
Associate II

I will do this now and let you know what happens, thank you for your assistance :)

Late? this is not a race I am so glad to receive all help

Thanks for your time to write

DPyke
Associate II

I added :

NVIC_EnableIRQ( I2C3_EV_IRQn); // Enable Event interrupts

NVIC_EnableIRQ( I2C3_ER_IRQn); // Enable Error interrupts

and it works! Excellent thank you both.

I have datasheet RM0351 and it does not this information, or I could not find it. What documentation can I find this information from?

All the best

Dren

See the "Nested vectored interrupt controller (NVIC)" section in the mentioned RM0351.

It will refer you to PM0214 "programming manual" for more information.

This macro reduces errors.

#define _VAL2FLD(field, value)    ((value << field ## _Pos) & field ## _Msk)

An example of using a macro.

    I2C2->TIMINGR = _VAL2FLD( I2C_TIMINGR_PRESC, 9)|        /// Timings prescale
                    _VAL2FLD( I2C_TIMINGR_SCLL, 30)|        /// SCL low period (master mode)
                    _VAL2FLD( I2C_TIMINGR_SCLH, 12)|        /// SCL high period (master mode)
                    _VAL2FLD( I2C_TIMINGR_SDADEL, 3)|       /// Data hold time
                    _VAL2FLD( I2C_TIMINGR_SCLDEL, 12);      /// Data setup time

The documentation has a convenient timing table for several frequency options.