Hello everyone,
I’m currently working on an I2C communication project using Mbed, and I’m facing an issue where one version of my code works perfectly, while another version does not, even though the addressing and setup seem identical.
Here’s the code that works:
Master test on F722ZE:
#include "mbed.h"
#include <cstdio>
#define I2C1_SDA PB_9
#define I2C1_SCL PB_8
#define ADDR 0xA0
DigitalIn SCL(I2C1_SCL);
DigitalIn SDA(I2C1_SDA);
I2C i2c1(I2C1_SDA, I2C1_SCL);
void device_scanner();
void ack_test(char* data);
int main() {
printf("................:[ I2C Device Tester ]:................\n\r");
char data[] = {0xAA}; // Example single byte data
char reads[3] = {0x00};
while (true) {
int write = i2c1.write(ADDR, data, sizeof(data));
int read = i2c1.read(ADDR, reads, sizeof(reads));
if (write == 0) {
printf("\tMessage sent successfully and acknowledged\n\r");
} else {
printf("\tMessage not sent (No ACK from slave)\n\r");
} if (read == 0) {
printf("\tMessage read: %s\n\r", reads);
} else {
printf("\tMessage not read\n\r");
}
}
}
Slave test on G031K8:
#include "mbed.h"
#include <cstdio>
I2CSlave slave(PA_12, PA_11);
#define SLAVE_ADDR 0xA0 // Use 7-bit address
#define WAIT_TIME_MS 500
DigitalOut LED(LED1);
int main() {
slave.address(SLAVE_ADDR);
while (1) {
int i2c_event = slave.receive();
switch (i2c_event) {
case I2CSlave::ReadAddressed:
slave.write("ACK", 3); // Just respond with "ACK"
break;
case I2CSlave::WriteAddressed:
char received[1]; // Expecting single byte
slave.read(received, 1);
printf("Received: 0x%02X\n", received[0]);
break;
}
LED = !LED;
}
}
This code successfully sends and receives data over I2C without any issues. However, when I use a different version of the code (shown below), it doesn’t work, even though the addressing and pin setup are the same. The problematic code fails during communication, as it doesn’t seem to receive any acknowledgments from the slave device.
My question is: Since the addressing seems correct, and the hardware works with this version of the code, what could be causing the other version to fail? Could it be related to how I’m initializing the pins or some other setup detail? I’d appreciate any suggestions or insights on what might be going wrong.
Thanks in advance for your help!
Master Implementation on F722ZE:
#include "PinNames.h"
#include "mbed.h"
#include <chrono>
#include <cstdint>
#include <cstdio>
#include "stepper.h"
#include "roboclaw.h"
#include "sdfat.h"
#include <ratio>
#include <sstream>
#include <string.h>
#include "messages.h"
#include "current.h"
#include "MB85RSxx_SPI.h"
char buf[BUFFER_SIZE] = "ABCDE";
I2C master(PB_9, PB_8); // SDA, SCL
bool readui(int max_retries, int delay_ms);
void init();
int main() {
init();
queue.call_every(50ms, []{ readui(5, 50); });
while (true) {
// Other code.
}
}
void init(){
//printf( "Working\n");
HVCTRL = 1;
readtimer.start();
pc.set_baud(9600);
pc.set_format(8, BufferedSerial::None, 1);
nsleep1 = 1;
nsleep2 = 1;
if (!readui(5,50)) {
printf("Use the A and D to move stepper motor 1\n Use Z and C to move stepper motor 2\n When Completed Restart System with UI plugged in");
}
while(!readui(5,50));
}
bool readui(int max_retries, int delay_ms) {
char buf[BUFFER_SIZE];
int result;
for (int attempt = 0; attempt < max_retries; attempt++) {
result = master.read(SLAVE_ADDR, buf, BUFFER_SIZE);
if (result == 0) { // Success
speedi = buf[0] & 7;
isstop = (buf[0] & 8) == 8;
return true;
} else {
printf("I2C read error: %d, attempt %d\n", result, attempt + 1);
ThisThread::sleep_for(delay_ms); // Wait before retrying
}
}
// If we reach here, all attempts failed
printf("Failed to read from slave after %d attempts.\n", max_retries);
return false;
}
Slave implementation on G031K8
#include "ticker_api.h"
#include "mbed.h"
#include "I2CSlave.h"
#include "I2C.h"
#include <cstdint>
#include <cstdio>
#include "Timer.h"
#define WAIT_TIME_MS 50
#define SCL PA_11
#define SDA PA_12
#include <string.h>
#define SLAVE_ADDR 0xA0
#define BUFFER_SIZE 6
char buf[BUFFER_SIZE] = "ABCDE";
//SLAVE byte buttons send 8 bit [4 bits empty, isstop, 3 bits speedi (8 decimal)]
uint8_t speedi = 2; //speedi && 7 0b00000111 4 is stop, 5 is up 3 is down ...
int speedizero = 2;
bool isstop = 1; // 8 0b00001000
char buff = (speedi & 7) | (isstop << 3);
I2CSlave slave(SDA, SCL);
DigitalOut i2cActivityLed(D3);
DigitalOut topBarCat(PA_0); //Initialise the cathode upper end of the LED Bar
DigitalOut midBarCat(PA_1); //Initialise the cathode middle of the LED Bar
DigitalOut botBarCat(PB_2); //Initialise the cathode bottom end of the LED Bar
DigitalOut REDBaruno(PA_7); //Initialise the Red of the LEDbar
DigitalOut REDBardos(PA_4); //Initialise the Red of the LEDbar
DigitalOut GreenBaruno(PA_6); //Initialise the Green of the LEDbar
DigitalOut GreenBardos(PA_5); //Initialise the Green of the LEDbar
DigitalOut led1(LED1);
DigitalOut LEDRED(PB_6); // Initialise red status circle LED
DigitalOut LEDGreen(PB_7); // Initialise green status circle LED
InterruptIn btndown(PA_10);
InterruptIn btnstop(PB_1);
InterruptIn btnup(PA_15);
DigitalIn SCL_pin(SCL);
DigitalIn SDA_pin(SDA);
// debounce
Timer upTimer, downTimer, StopTimer;
Timeout debounce_timeout;
volatile bool down_button_pressed_flag = false;
volatile bool stop_button_pressed_flag = false;
volatile bool up_button_pressed_flag = false;
int btnupPrev=0, btndownPrev=0, btnstopPrev=0;
int cbtnup,cbtndown,cbtnstop;
bool tbtnup=0,tbtndown=0,tbtnstop=0;
uint8_t LED[] = {0,1,0,1,1,0,0}; // {top, middle, bottom, red1, red2, green1, green2}
void upEventFunction();
void downEventFunction();
void down_button_ISR();
void up_button_ISR();
void stop_button_ISR();
void stopEventFunction();
void LEDCTRL(uint8_t* LED);
int main()
{
debug("-----------:User Controller Start:-----------\n");
slave.address(SLAVE_ADDR);
btndown.mode(PullUp);
btnstop.mode(PullUp);
btnup.mode(PullUp);
SDA_pin.mode(PullUp);
SCL_pin.mode(PullUp);
led1 = 1;
// MBed Interrupt function
btndown.fall(&down_button_ISR);
btnstop.fall(&stop_button_ISR);
btnup.fall(&up_button_ISR);
while (true){
LEDCTRL(LED);
buf[0] = (speedi & 7) | (isstop << 3);
int i = slave.receive();
printf("I2C event: %d\n", i); // Print the event type
switch (i) {
case I2CSlave::ReadAddressed:
// Write back the buffer from the master
slave.write(buf, BUFFER_SIZE);
printf("Written to master (addressed): speedi: %d isstop: %d\n", buf[0]&7,(buf[0]&8)==8);
break;
case I2CSlave::WriteGeneral:
slave.read(buf, BUFFER_SIZE);
printf("Read from master (general): %s\n", buf);
break;
case I2CSlave::WriteAddressed:
slave.read(buf, BUFFER_SIZE);
printf("Read from master (addressed): %s\n", buf);
break;
}
printf("Sending to master: 0x%02X\n", buf[0]);
led1 = !led1;
}
}