Why does'nt this work? (I2C on Bluepill) STM32F103

What you see here is an attempt to debug much bigger program:
I recently moved it to STM32, and ran into this trouble:

In short: the program never sees any packet adressed to it (address 0xB or 11)
I DO see and decode packets incoming on the I2C bus, with a scope connected to SCL1/PB6/22 and SDA1/PB7/23 .
I do NOT get to see them in the serial monitor.

#include <Wire.h>

long lastms;
void receiveEvent(int howMany) {
int x = Wire.read();

Serial.print("U:0x");
Serial.println(x, HEX);
}

void requestEvent() {
    Serial.println("req");
}

void setup() {
  Serial.begin(115200); 

  pinMode(22,INPUT); 
  pinMode(23,INPUT);
  
  Wire.setSCL(22);
  Wire.setSDA(23);
  
  Wire.begin(11);     // join i2c bus as slave
  Wire.onRequest(requestEvent);  // register event
  Wire.onReceive(receiveEvent);  // register event

  lastms = millis();
}

void loop() {
  if (millis() > lastms+1000) {
    Serial.print("=");
    lastms = millis();
  }
}

First thought: if receiveEvent and requestEvent are called from an interrupt, does Serial I/O work in an interrupt on the STM32F103?

just to make sure, I did:

#include <Wire.h>


long lastms;
int x = 0;

void receiveEvent(int howMany) {
  x = Wire.read();
}

void requestEvent() {
  Serial.println("req");
}

void setup() {
  Serial.begin(115200);

  pinMode(22, INPUT);
  pinMode(23, INPUT);

  Wire.setSCL(22);
  Wire.setSDA(23);

  Wire.begin(11);                // join i2c bus as slave
  Wire.onRequest(requestEvent);  // register event
  Wire.onReceive(receiveEvent);  // register event

  lastms = millis();
}

void loop() {
  if (millis() > lastms + 1000) {
    Serial.print("=");
    lastms = millis();
  }
  if (x != 0) {
    Serial.print("U:0x");
    Serial.println(x, HEX);
    x = 0;
  }
}

It did not help , I still only get "="
Also: please have in mind that the scope is connected to said pins, so the pullups/connection is ok.

If requestEvent and receiveEvent are called from an interrupt context, x should be declared volatile otherwise the compiler might optimize away checking it in loop. And the code is still printing from requestEvent.

I tried this, it did not help,

#include <Wire.h>
long lastms;
volatile int x = 0;
volatile int y = 0;

void receiveEvent(int howMany) {
  x = Wire.read();
}

void requestEvent() {
  y = 1;
}

void setup() {
  Serial.begin(115200);

  pinMode(22, INPUT);
  pinMode(23, INPUT);

  Wire.setSCL(22);
  Wire.setSDA(23);

  Wire.begin(11);                // join i2c bus as slave
  Wire.onRequest(requestEvent);  // register event
  Wire.onReceive(receiveEvent);  // register event

  lastms = millis();
}

void loop() {
  if (millis() > lastms + 1000) {
    Serial.print("=");
    lastms = millis();
  }
  if (x != 0) {
    Serial.print("U:0x");
    Serial.println(x, HEX);
    x = 0;
  }
  if (y != 0) {
    Serial.println("V");
    y = 0;
  }
}

This worked fine for me on my admittedly ancient STM32 core that I haven't updated since forever. I rigged up a Pico to send a message over I2C once every 2 seconds and the Blue Pill displays them.

#include <Wire_slave.h>

volatile char buf[80];
volatile unsigned count = 0;
volatile bool received = false;

void setup() {
   Serial.begin(115200);
   delay(5000);
   Serial.println("Started");

   Wire.begin(11);
   Wire.onReceive(receiveEvent);
}

void loop() {
   if( received ) {
      for( unsigned i=0; i<count; ++i ) {
         Serial.print(buf[i]);
      }
      received = false;
      count = 0;
   }
   delay(50);
}

void receiveEvent(int howMany) {
   for( int i=0; i<howMany; ++i ) {
      char c = Wire.read();
      if( count < sizeof buf ) {
         buf[count++] = c;
      }
   }
   received = true;
}

this one is new to me.

Remember, it's an ancient core that I'm using. It may no longer be that way.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.