6 years, 11 months ago.

STM32F429ZI (master) to STM32F429ZI(slave) I2C protocol reg

I am trying check the I2c protocol using two STM board .I have not received any output when I was checking in the serial terminal using "pc.print "

Master Code:

  1. include "mbed.h"

I2C i2c(PB_9,PB_6); Serial pc(USBTX, USBRX);

int main() { const int addr = 0xA0; int a,b; char buff[10]; const char data[]="message master";

i2c.frequency(10000);

while(1) { /* i2c.start(); a=i2c.read(addr, buff,10,1); wait(1); pc.printf("Read %d", a); i2c.stop(); pc.printf("MASTER READ: %s \n\r", buff);*/ i2c.start(); b=i2c.write( addr, data, strlen(data)+1); wait(0.07); i2c.stop(); pc.printf("Write %d\n\r", b); for(int i = 0; i < 10; i++) buff[i] = 0;

} }

SLAVE CODE:

  1. include "mbed.h"

I2C i2c(PB_9,PB_6); Serial pc(USBTX, USBRX);

int main() {

const char test[]= "message slave"; char buf[10]; int i, b;

i2c.frequency(10000); slave.address(0xA0);

while(1) {

i = slave.receive(); wait(0.75);

switch (i) {

case I2CSlave::ReadAddressed:

slave.stop(); b=slave.write(test, strlen(test) + 1); wait(0.75);

pc.printf("Return Slave %d", b); only to check return value

break; case I2CSlave::WriteGeneral:

slave.stop(); slave.read(buf, 10); wait(0.75); pc.printf("SLAVE Read G: %s\n\r", buf); break; case I2CSlave::WriteAddressed:

slave.stop(); slave.read(buf, 10); wait(0.75); pc.printf("SLAVE Read A: %s\n\r", buf); break; } for(int i = 0; i < 10; i++) buf[i] = 0;

} }

1 Answer

6 years, 11 months ago.

Hi. A few pointers.

1) apply the <<code>> your code <</code>> markers when you post your source code so it is easier for others to review. Here is your code reformatted using these special markers.

Master code:

#include "mbed.h" 

I2C i2c(PB_9,PB_6); Serial pc(USBTX, USBRX);

int main()
{ 
const int addr = 0xA0; int a,b; char buff[10]; const char data[]="message master";

i2c.frequency(10000);

while(1) 
 { 
 /* i2c.start(); 
   a=i2c.read(addr, buff,10,1); 
   wait(1); 
   pc.printf("Read %d", a); 
   i2c.stop(); 
   pc.printf("MASTER READ: %s \n\r", buff);
*/ 

   i2c.start(); 
   b=i2c.write( addr, data, strlen(data)+1); 
   wait(0.07); 
   i2c.stop(); 
   pc.printf("Write %d\n\r", b); 
   for(int i = 0; i < 10; i++) buff[i] = 0;

 } 
}

Slave Code:

 #include "mbed.h" 

I2C i2c(PB_9,PB_6); Serial pc(USBTX, USBRX);

int main() 
{
const char test[]= "message slave"; 
char buf[10]; 
int i, b;

i2c.frequency(10000); slave.address(0xA0);

while(1) 
{
i = slave.receive(); wait(0.75);
switch (i) 
{
 case I2CSlave::ReadAddressed:
 slave.stop(); 
 b=slave.write(test, strlen(test) + 1); 
 wait(0.75);
 pc.printf("Return Slave %d", b); // only to check return value
 break; 

case I2CSlave::WriteGeneral:
 slave.stop(); 
 slave.read(buf, 10); 
 wait(0.75); 
 pc.printf("SLAVE Read G: %s\n\r", buf); 
 break; 

case I2CSlave::WriteAddressed:
 slave.stop(); 
 slave.read(buf, 10); 
 wait(0.75); 
 pc.printf("SLAVE Read A: %s\n\r", buf); 
 break; 

} 

for(int i = 0; i < 10; i++) buf[i] = 0;
 }
}

2) Read my post here on a similar review:

https://developer.mbed.org/questions/78077/I2CSlave-mbed-code-review/

3) Remove the use of:

i2c.start();   // remove from your code
i2c.stop();    // remove from your code
slave.stop();  // remove from your code

The START and STOP states are automatically inserted by the I2C routines and your manual use of these lines will break the code.

4) Be sure that you have a single pair of pull-up resistors as required by the I2C spec. The value of the resistors is not critical but recommended values are 2k2 to say 10k to 3v3. The same ST port pins for I2C use a 5 volt tolerant so it is also safe to apply the same pull-up resistors to +5 volts if required. The resistors are mandatory to pull up the port pins to a logic high as I2C pins are open collector when the s/w outputs a high.

5) Most important is the use of the I2CSlave routine. As per my review last week, the Slave I2C read MUST use the proper buffer size. For your example, your I2C master is sending to the I2C Slave a string length of 14 bytes + 1 EOF marker = 15 bytes.

Try the following revised code (not tested as my setup is at work):

I2C Master:

#include "mbed.h" 
 
I2C i2c(PB_9,PB_6); Serial pc(USBTX, USBRX);
 
int main()
{ 
const int addr = 0xA0; 
int a,b; 
char buff[10]; 
const char data[]="message master";
 
i2c.frequency(10000);
 
while(1) 
 { 
 /* i2c.start(); 
   a=i2c.read(addr, buff,10,1); 
   wait(1); 
   pc.printf("Read %d", a); 
   i2c.stop(); 
   pc.printf("MASTER READ: %s \n\r", buff);
*/ 

   b=i2c.write( addr, data, strlen(data)+1); 
   wait(0.07); 

   pc.printf("Write %d\n\r", b); 
   for(int i = 0; i < 10; i++) 
        buff[i] = 0;
 
 } 
}

I2C Slave:

#include "mbed.h" 

I2C i2c(PB_9,PB_6); Serial pc(USBTX, USBRX);

int main() 
{
const char test[]= "message slave"; // 13 bytes + 1 EOF = 14 bytes
char buf[10]; 
int i, b;

i2c.frequency(10000); slave.address(0xA0);

while(1) 
{

 i = slave.receive();  
 wait(0.75);

switch (i) 
{
 case I2CSlave::ReadAddressed:
 b=slave.write(test, strlen(test) + 1); 
 wait(0.75);
 pc.printf("Return Slave %d", b); // only to check return value
 break; 

case I2CSlave::WriteGeneral:
 slave.read(buf, 15);  // since the I2C master is sending to the slave 14 bytes of data + 1 EOF marker = 15 bytes 
 wait(0.75); 
 pc.printf("SLAVE Read G: %s\n\r", buf); 
 break; 

case I2CSlave::WriteAddressed:
 slave.read(buf, 15); // since the I2C master is sending to the slave 14 bytes of data + 1 EOF marker = 15 bytes 
 wait(0.75); 
 pc.printf("SLAVE Read A: %s\n\r", buf); 
 break; 

} 

for(int i = 0; i < 10; i++) buf[i] = 0;
 }
}

The I2C Slave routine will block if more bytes are being read than what the I2C Master is sending. Ok if reading less bytes from the I2C Master but suggest to use the exact send buffer size.

After testing, please post your results.

Accepted Answer