While testing I noticed, that my I2C interface (I2C1 - PB8 & PB9) isn't working at all on my Nucleo-L452RE. I also tried to change the SCL and SDA pins via the SetSCL() and SetSDA() functions before I call Wire.begin()
I even tried other I2C interfaces with your API tutorial.
https://github.com/stm32duino/wiki/wiki/API#i2C
Arduino example code:
#include <Wire.h>
void setup() {
Wire.begin();
}
void loop() {
Wire.beginTransmission(0x71);
Wire.write('v');
Wire.endTransmission();
delay(1000);
}
After that I tried code, which I generated with the STM32CubeMX and the I2C1 interface worked as it should.
STM32 code:
int main(void)
{
/* USER CODE BEGIN 1 */
unsigned char buffer[5] = {0};
buffer[0] = 0x02;
buffer[1] = 0x08;
buffer[2] = 0x80;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_I2C_Master_Transmit(&hi2c1, 0x40, buffer, 3, 100);
}
/* USER CODE END 3 */
}
To further strengthen my suspicion that the problem is related to the Nucleo-L452RE, I tried the same arduino code with the Nucleo-L073RZ and this worked as expected.
IDE: VisualGDB in Visual Studio.
STM32 core version: 1.8.0
Upload method: STLink-V2.1 (integrated in the Nucleo)
OS: Windows 10 1809
Further settings:

Can someone confirm the I2C problem with the Nucleo-L452RE C-04?
It seems strange.
You have a Nucleo-L452RE or Nucleo-L452RE-P ?
You have PULL UP resistor on each line ?
I have a Nucleo-L452RE.
I don't think that the Nucleo has external Pull Ups... The schematics of the Nucleo-64 also don't show any.
And the i2c communication is working well with the STM32CubeMX generated code even with no sensor attached (mostly they have pull ups).
Probably the cube MX init the pin with the internal PULL UP which can explain the difference.
I tried to read out a bme280 sensor (with integrated pull ups) and this is working.
Is there a way to activate the internal pull ups if the external sensor doesn't have any?
And can I use a second I2C interface? For example I2C3 on the pins PC0 (A5) and PC1 (A4)?
I tried to read out a bme280 sensor (with integrated pull ups) and this is working.
Is there a way to activate the internal pull ups if the external sensor doesn't have any?And can I use a second I2C interface? For example I2C3 on the pins PC0 (A5) and PC1 (A4)?
you can redefine weak i2c pins configuration in your sketch
const PinMap PinMap_I2C_SDA[] = {
{PB_9, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF4_I2C1)},
{PC_1, I2C4, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF2_I2C4)},
{NC, NP, 0}
};
const PinMap PinMap_I2C_SCL[] = {
{PB_8, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF4_I2C1)},
{PC_0, I2C4, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF2_I2C4)},
{NC, NP, 0}
};
here i left only PB9/PB8 and PC1/PC0 pins for i2c and changed GPIO_NOPULL to GPIO_PULLUP
probably it will help
Is there a way to activate the internal pull ups if the external sensor doesn't have any?
Yes, redefine the PinMap I2C array at sketch level and replace GPIO_NOPULL by GPIO_PULLUP
They are weaked and default config is here:
https://github.com/stm32duino/Arduino_Core_STM32/blob/7f68be4581bc424af6ac0b621b881c0d57a1524b/variants/NUCLEO_L452RE/PeripheralPins.c#L68-L98
And can I use a second I2C interface? For example I2C3 on the pins PC0 (A5) and PC1 (A4)?
Yes, but you will have to uncomment them in the PinMap array as by default those pins are set to use I2C4.
To use an other instance you have to declare it as a global:
TwoWire Wire2(PC1, PC0);
So for your case, you should add something like this in your sketch:
const PinMap PinMap_I2C_SDA[] = {
{PB_9, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF4_I2C1)},
{PC_1, I2C3, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF4_I2C3)},
{NC, NP, 0}
};
const PinMap PinMap_I2C_SCL[] = {
{PB_8, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF4_I2C1)},
{PC_0, I2C3, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF4_I2C3)},
{NC, NP, 0}
};
So I close it as all works ;)
I added this explanation to the API wiki site if someone is curious.
https://github.com/stm32duino/wiki/wiki/API#i2C
Most helpful comment
Yes, redefine the PinMap I2C array at sketch level and replace
GPIO_NOPULLbyGPIO_PULLUPThey are weaked and default config is here:
https://github.com/stm32duino/Arduino_Core_STM32/blob/7f68be4581bc424af6ac0b621b881c0d57a1524b/variants/NUCLEO_L452RE/PeripheralPins.c#L68-L98
Yes, but you will have to uncomment them in the PinMap array as by default those pins are set to use I2C4.
To use an other instance you have to declare it as a global:
TwoWire Wire2(PC1, PC0);So for your case, you should add something like this in your sketch: