PCA9554 I don't understand this code

I am trying to us the 9554 for input and output and the example is poor.

#include <M5Stack.h>

#include "PCA9554.h"

PCA9554 ioCon1(
  0x27);  // Create an object at this address. 

uint8_t res;
void setup() {
  M5.begin();
  M5.Power.begin();
  Wire.begin();
  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(YELLOW);
  M5.Lcd.setCursor(0, 90);
  M5.Lcd.print("UNIT_IO EXAMPLE\n");

  ioCon1.twiWrite(
    21, 22);  // Sets the I2C pin of the connection.  设置连接的I2C引脚
  delay(10);
  res = 1;
  ioCon1.twiRead(res);
  Serial.printf("res:%d\r\n", res);

  ioCon1.portMode(
    ALLOUTPUT);  // Set the port as all output.  设置所有引脚为输出模式
}

In the code we have res declared as a uint8_t. The code then sets res=1 and does a ioCon1.twiRead(res);

How does this work since in the class definition :

class PCA9554
{
	public :
		PCA9554(byte SlaveAddress);

		bool twiRead(byte &registerAddress);
		bool twiWrite(byte registerAddress, byte dataWrite);

		bool pinMode(byte pinNumber, bool state);
		bool portMode(byte value);
		
		bool digitalWrite(byte pinNumber, bool state);
		bool digitalWritePort(byte value);
				
		bool digitalRead(byte &pinNumber);
		bool digitalReadPort(byte &value);
		
	private :
		int _SlaveAddress;
};

iwiRead receives the address of the of a byte containing the register. The code then prints a value.

Thanks
Kurt

the twiRead() function is declared as taking a reference to a variable of type byte byte & and since it is a reference, the function can change the value held by the variable.

Typically, in C/C++, you have pass by value, or pass in a pointer to a variable that can be changed, but pass by reference is also valid C++. So this function receives the address of the register and then modifies it to hold the contents of that register after the read.

Thanks. I understand that C is pass by value but res is declared as a unit8_t and passed as twiRead(res) so help me understand why does the function not get the value 1. I expected it to be called with twiRead(&res). This is my confusion. Why does this even compile?

Kurt

because the compiler knows the definition of the function and sees it as pass by reference, so does the dereferencing for you.

As for the function, it does receive the value 1, which is the register number. After reading the contents of register 1, it puts that result back into res

Thanks. If you bear with me a moment. Why does this fail:

  byte Inputs;                                                                               // PCA9554 input register
  if (!RoofControls.digitalReadPort(&Inputs)) return false;  // return false if read failed
 

Thanks

Kurt

Define Fail. Fails to compile?

If you look at the definition of digitalReadPort

bool digitalReadPort(byte &value);

it takes one parameter of type byte that is a reference. Your code

is passing in the address of a variable of type byte (i.e. a pointer to a byte) which would match a function definition of

bool digitalReadPort(byte *value);

And since there is no matching signature, the compiler throws an error.

the & is a bit confusing due to the "address of" function vs. "pass by reference" meaining in parameter declarations.

Thanks. What I mean by failure is that it throws a compile error.

Since I taught myself C I don't have a complete background/understanding but I used to do a bunch of assembly language programming. Can you explain what you mean by "signature" in "there is no matching signature". I was thinking that by coding !RoofControls.digitalReadPort(&Inputs) that this would pass the value of address of the variable Inputs which is what the class definition of digitalReadPort declared.

Kurt

In C++, every function has a signature which is made up of the return value (void, int, etc.), the name of the function, the number of parameters and the types of each parameter. For example, if you look at the declaration of the .print() function, there will be multiple (these are not the real ones, but you should get the idea)

int print( void );
int print( char );
int print( uint8_t );
int print( int );
int print( long );
...

and then, in your code, the compiler looks at what you are calling and matches that with the proper function call. Check this code out

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