2019-09-26 01:34 AM
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
2019-09-26 01:52 AM
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).
2019-09-26 01:56 AM
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 :)
2019-09-26 03:16 AM
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 :)
2019-09-26 03:17 AM
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
2019-09-26 04:46 AM
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
2019-09-26 05:23 AM
See the "Nested vectored interrupt controller (NVIC)" section in the mentioned RM0351.
It will refer you to PM0214 "programming manual" for more information.
2019-09-26 02:33 PM
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.