6 years, 12 months ago.

Anyone got the STM32F103RB working with a PCF8574 I2C expander?

According to the PCF8574 library example I came up with the following code:

  1. include <string>
  2. include "mbed.h"
  3. include "PCF8574.h"
  1. define PCF8574_ADDR 0 I2c PCF8574 hardware address is 000 DigitalOut led1(LED1); Serial pc(USBTX, USBRX);

static void myerror(std::string msg) { pc.printf("Error %s\r\n",msg.c_str()); exit(1); }

void pcf8574_it(uint8_t data, PCF8574 *o) { pc.printf("PCF8574 interrupt data = %02x\r\n",data); }

int main() { pc.baud(115200); PCF8574 pcf(I2C_SDA,I2C_SCL,PCF8574_ADDR,false); Declare PCF8574 i2c with sda = I2C_SDA and scl = I2C_SCL uint8_t data;

led1 = 0;

Set all IO port bits to 1 to enable inputs and test error data = 0xFF; pcf = data; if(pcf.getError() != 0) myerror(pcf.getErrorMessage());

Assign interrupt function to pin 17 pcf.interrupt(PC_9,&pcf8574_it);

if(pcf.getError() != 0) myerror(pcf.getErrorMessage());

Get IO port (switch is used to flip bit 1) while(1) { wait(2.0); data = pcf; if(pcf.getError() != 0) myerror(pcf.getErrorMessage()); led1 = !led1; } }

My hardware address is 000 and the chip prefix is 0100. R/W bit is 1/0. I have tried every address from 0 to 7 and all I get in the terminal is "Error I2C error (nack)" above 7 give me "Error Bad chip address"

It also appears to be sending only a single low pulse over the logic analyser, which may just be the board start noise or sometimes I get what looks like a 10bit pulse. It should be 7 + r/w

What am I doing wrong?

Apparently posting your code make it look like crap. Not sure what happened with the formatting..

posted by Dave Boechler 20 Apr 2017

2 Answers

6 years, 11 months ago.

Hello Dave,
The PCF8574 I2C IO Expander demo published in mbed's Cookbook works fine for me with a NUCLEO-F103RB board, although it does not support interrupts. It seems that the bug reported by Wim has been fixed because it works even after updating the mbed library to the latest revision. I have connected PCF8574's SDA pin to pin PB_9 on the NUCLEO board and the SCL pin to pin PB_8. Since in my case the PCF8574's address pins A2, A1 and A0 were not grounded (in contrary to the Cookbook demo) the I2C address passed to the PCF8574 constructor was set to 0x4E as in the code below:

#include "mbed.h"
#include "PCF8574.h"

DigitalOut  myled(LED1);
PCF8574     io(PB_9, PB_8, 0x4E);

int main(void) {
    while(1) {
        myled = 1;
        io.write(0x00);
        wait_ms(1000);
        myled = 0;
        io.write(0xFF);
        wait_ms(1000);
    }
}

Great! I will try your code when I get back to my lab. It was unclear in the code if they where looking address as 7, 8 bits or shifted 7 bits so a working address helps.

posted by Dave Boechler 28 Apr 2017
6 years, 12 months ago.

Please use the <<code>> and <</code>> before and after posted code to keep it readable. See ''editing tips'' link for more hints.

Did you check the I2C pull-up resistors on SDA and SCL (and Interrupt). Is the powersupply for the PCF8574 Ok.

Thanks for the tip.

I have a 4.7k on SDA and SCL and they do read logic high and low on the logic analyzer/DMM.

Is 4.7k too high for 3.3v?

Thanks

posted by Dave Boechler 21 Apr 2017

The 4K7 should be Ok, although I prefer 3K3.

The problem seems to be introduced in the updated I2C libs for the STM devices. I noticed a failure on the first write operation after a reset. There are also issues with read operations. I have raised a bug report on github.

The lib that you use for the PCF8574 detects the write error and then blocks all further communications.

A quick fix could be to replace mbed rev 140 in your program and select revision 132 instead. That version still seems to work OK. Select the mbed lib in your program filetree, then select revisions in the window on the right hand side and select revisions, switch to the desired revision and recompile

posted by Wim Huiskamp 22 Apr 2017