Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
10 years, 12 months ago.
I2C Master and Slave STM32F401.Nucleo
I have 2 boards STM32F401.Nucleo. If on board Slave set waitEnable = 1 => on board Master i2c.write() return failure Why the delay break I2C communication?
DigitalOut led(PA_5);
DigitalOut orange(D8);
DigitalOut green(D9);
DigitalIn button(PC_13);
Serial pc(USBTX, USBRX); // tx, rx
I2C i2c(PB_9,PB_8); // SDA, SCL
I2CSlave slave(PB_3,PB_10); // SDA, SCL
const int addr = 0x04;
char MasterTX[] = "Message from Master";
char MasterRX[64] = {0};
char SlaveTX[] = "Message from Slave";
char SlaveRX[64] = {0};
int waitEnable = 0;
#ifdef MASTER
while(1) {
nRet = i2c.write(addr,MasterTX,sizeof(MasterTX),true);
if (nRet == 0) { // Slave ack
orange = 1;
green = 0;
} else { // Slave nack
orange = 0;
green = 1;
}
led = 1;
wait(0.5);
led = 0;
wait(0.5);
}
#else
int nCounter = 0;
slave.address(addr);
while(1) {
if (waitEnable == 1) {
wait(0.01);
}
led = 1;
memset(SlaveTX,0,sizeof(SlaveRX));
step = slave.receive();
switch(step) {
case I2CSlave::ReadAddressed: // Master запрашивает ответ от Slave
slave.write(SlaveTX,sizeof(SlaveTX));
printf("TX: %s\r\n",SlaveTX);
orange = 1;
break;
case I2CSlave::WriteGeneral: // Бродкаст
slave.read(SlaveRX,sizeof(SlaveRX));
printf("Broadcast RX: %s\r\n",SlaveRX);
orange = 1;
break;
case I2CSlave::WriteAddressed: // Master спрашивает текущий Slave
slave.read(SlaveRX,sizeof(SlaveRX));
printf("Slave RX %d: %s\r\n",nCounter,SlaveRX);
orange = 1;
break;
case I2CSlave::NoData:
orange = 0;
break;
}
nCounter++;
}
#endif
Update: The problem was a bad pull-up SDA and SCL. Now I use an external power supply for the Nucleo boards and pull-up lines.
A new problem: Slave receives the message "Message from Master" correctly. Master receives incorrect.
Init MasterRX = "ProbaOdnako". Slave transmit "123\0". If there is no delay in Master between nRet = i2c.write(addr,MasterTX,sizeof(MasterTX)) and nRet = i2c.read(addr,MasterRX,4) nRet = i2c.read(addr,MasterRX,4) return "яяяяaOdnako".
With delay sometimes nRet = i2c.read(addr,MasterRX,4) return "я123aOdnako". nRet = i2c.read(addr,MasterRX,4) return "123".
Why sometimes appears first symbol 'я' (0xFF)? What values should be a delay between the functions write and read?
New code:
#include "Global.h"
#include "main.h"
DigitalOut led(PA_5);
DigitalOut orange(D7);
DigitalOut green(D9);
DigitalIn button(PC_13);
Serial pc(USBTX, USBRX); // tx, rx
Serial uart(PA_9, PA_10); // tx, rx
Timer timer;
#define ARRAY_SIZE 24
I2C i2c(PB_9,PB_8); // SDA, SCL
I2CSlave slave(PB_3,PB_10); // SDA, SCL
int i;
int step;
int nRet = 1;
int waitEnable = 0;
const int addr = 0xA0;
char nameDevice[16] = {0};
char MasterTX[] = "Message яяяя Master";
char SlaveTX[] = "Message from Slave";
char MasterRX[sizeof(SlaveTX)] = {0};
char SlaveRX[sizeof(MasterTX)] = {0};
int nCounter = 0;
#define MASTER
int main() {
led = 0;
green = 0;
orange = 0;
uart.baud(9600);
//pc.printf("SystemCoreClock = %d Hz\n", SystemCoreClock);
#ifdef MASTER
int search = 0;
strcpy(nameDevice,"Master");
uart.printf("Uart start %s\r\n",nameDevice);
i2c.frequency(100000); //Set the clock frequency
// Send a start message to RealTerm
pc.printf("\fmbed I2C debug tool ready\n\r");
// Scan for I2C devices that reply with ack
for (i=0; i<=254; i=i+2) {
if (i2c.read(i, &MasterRX[0], 1) == 0)
{
pc.printf("I2C device detected at address = 0x%02X\n\r", i);
search++;
}
}
if (search == 0) {
pc.printf("I2C Slaves NO DETECTED!\n\r");
} else {
pc.printf("I2C Slaves %d\n\r",search);
}
MasterRX[0] = 0;
while(1) {
nRet = i2c.write(addr,MasterTX,sizeof(MasterTX));
if (nRet == 0) { // Slave ответил
orange = 1;
//green = 0;
} else { // Slave не ответил
orange = 0;
//green = 1;
}
memset(MasterRX,0,sizeof(MasterRX));
strcpy(MasterRX,"ProbaOdnako");
nRet = i2c.read(addr,MasterRX,4/*sizeof(MasterRX)*/);
if (nRet == 0) { // Slave ответил
green = 1;
uart.printf("Master RX %d: %s\r\n",nCounter,MasterRX);
} else { // Slave не ответил
green = 0;
}
led = 1;
wait(1.5);
led = 0;
wait(1.5);
nCounter++;
}
#else
int begin = 0, end = 0;
strcpy(nameDevice,"Slave");
uart.printf("Uart start %s\r\n",nameDevice);
timer.start();
slave.frequency(100000); //Set the clock frequency
slave.address(addr);
pc.printf("Slave start\r\n");
while(1) {
begin = timer.read_us();
for (i=0;i<1000L;i++) { // Задержка 1000
led = 1;
waitEnable++;
}
end = timer.read_us();
memset(SlaveRX,0,sizeof(SlaveRX));
step = slave.receive();
switch(step) {
case I2CSlave::ReadAddressed: // Master запрашивает ответ от Slave
strcpy(SlaveTX,"123\0");
slave.write(SlaveTX,4);
printf("Slave TX: %s\r\n",SlaveTX);
uart.printf("Slave TX: %s\r\n",SlaveTX);
orange = 1;
break;
case I2CSlave::WriteGeneral: // Бродкаст
slave.read(SlaveRX,sizeof(SlaveRX));
printf("Broadcast RX: %s\r\n",SlaveRX);
orange = 1;
break;
case I2CSlave::WriteAddressed: // Master спрашивает текущий Slave
slave.read(SlaveRX,sizeof(SlaveRX));
//wait(0.01);
printf("Slave RX %d: %s\r\n",nCounter,SlaveRX);
uart.printf("Uart Slave %d: %s\r\n",nCounter,SlaveRX);
//uart.printf("No critical I2C delay %d us\r\n", end - begin);
orange = 1;
break;
case I2CSlave::NoData:
orange = 0;
break;
}
nCounter++;
}
#endif
}