Hi David,
Yes I tried to write to the register and read it back but it didnt give the same value. (I am Thai co-worker)
I can share with you my code so far and you can correct me, please.
This is the ino file: pcal
#include <Arduino.h>
#include <SPI.h>
#include <stdint.h>
#include "pcal9714.h"
void setup() {
Serial.begin(9600);
uint8_t debounce_pins_port0 = 0xFF; // to enable debounce on all pins of port 0
uint8_t debounce_pins_port1 = 0xFF; // to enable debounce on all pins of port 1
uint16_t debounce_counter_value = 10; // debounce time of 10 microseconds
pcal9714_configure_debounce(debounce_pins_port0, debounce_pins_port1, debounce_counter_value);
// Set all pins you want to monitor as inputs with internal pull-up
for (uint8_t pin = 0; pin < 8; pin++) {
pcal9714_set_mode(pin, INPUT_PULLUP);
}
// Write a test value to a register
uint8_t testValue = 0xAA; // Example test value (170 in decimal)
pcal9714_write(PCAL_CONF_PORT0, testValue);
// Read the value back
uint8_t readBackValue = pcal9714_read(PCAL_CONF_PORT0);
// Print the read back value to the serial monitor
Serial.print("Wrote: 0x");
Serial.print(testValue, HEX);
Serial.print(", Read back: 0x");
Serial.println(readBackValue, HEX);
// Set GPIOEXP_LIMIT_SWITCH_HOME_Y_V10 as an output
pcal9714_set_mode(GPIOEXP_LIMIT_SWITCH_HOME_Y_V10, OUTPUT); // Set the pin as output
// Set the pin high
pcal9714_set_pin(GPIOEXP_LIMIT_SWITCH_HOME_Y_V10, HIGH); // Drive the pin high
// Add a short delay to observe the pin voltage with a multimeter
delay(1000); // Wait for 1 second
// Set the pin low
pcal9714_set_pin(GPIOEXP_LIMIT_SWITCH_HOME_Y_V10, LOW); // Drive the pin low
// Add another short delay to observe the pin voltage with a multimeter
delay(1000); // Wait for 1 second
Serial.println("Direct pin test setup complete.");
}
void loop() {
// Read the state of a pin (for example, P0_2) and print it to the serial monitor
int limitSwitchValue = pcal9714_read_pin(GPIOEXP_LIMIT_SWITCH_HOME_Y_V10);
// Print the state to the serial monitor
Serial.print("Limit Switch State: ");
Serial.println(limitSwitchValue);
// Add a delay to prevent flooding the serial monitor
delay(500);
static bool pinState = LOW;
pcal9714_set_pin(GPIOEXP_LIMIT_SWITCH_HOME_Y_V10, pinState);
pinState = !pinState; // Toggle the state
delay(1000); // 1 second delay
}
This is the cpp file pcal9714
#include <Arduino.h>
#include "pcal9714.h"
#include <SPI.h>
/**
********************************************************************************
* @file pcal9714.cpp
* @author ahmed
* @date 2024-04-22
* @brief Implementation of the pcal9714 driver.
********************************************************************************
*/
/// @brief Configure the pcal9714 device.
void pcal9714_init(void)
{
pinMode(PCAL9714_SPI_CS_PIN, OUTPUT);
digitalWrite(PCAL9714_SPI_CS_PIN, HIGH); // Deselect the device
SPI.begin(); // Initialize SPI communication
}
/// @brief Set the value of a pin on the pcal9714 device.
/// channel Channel number.
/// value 1 for high, 0 for low.
void pcal9714_set_pin(uint8_t channel, uint8_t value)
{
uint8_t port = channel / 8; // Determine port (0 or 1)
uint8_t pin = channel % 8; // Determine pin within the port
uint8_t portValue = pcal9714_read_port(port); // Read current port value
if (value) {
portValue |= (1 << pin); // Set the pin to HIGH
} else {
portValue &= ~(1 << pin); // Set the pin to LOW
}
pcal9714_write(PCAL_OUT_PORT0 + port, portValue); // Write to the output port
}
/// @brief Read the value of a pin on the pcal9714 device.
/// channel Channel number.
/// @return The value of the pin.
uint8_t pcal9714_read_pin(uint8_t channel)
{
uint8_t port = channel / 8;
uint8_t pin = channel % 8;
uint8_t portValue = pcal9714_read_port(port);
return (portValue >> pin) & 0x01;
}
/// @brief Set the mode of a pin on the pcal9714 device.
/// channel Channel number.
/// value 1 for high impedence input, 0 for output.
void pcal9714_set_mode(uint8_t channel, uint8_t mode) {
uint8_t port = channel / 8;
uint8_t pin = channel % 8;
// Setting the overall port configuration for push-pull if we're setting the pin as an output
if (mode == OUTPUT) {
uint8_t out_conf = pcal9714_read(PCAL_OUT_CONF_REG);
out_conf |= 0x03; // Set the ports to push-pull mode
pcal9714_write(PCAL_OUT_CONF_REG, out_conf);
// Set the individual pin configuration for pull-up if required
uint8_t out_conf_reg = (port == 0) ? PCAL_OUT_CONF_REG0 : PCAL_OUT_CONF_REG1;
uint8_t out_conf_value = pcal9714_read(out_conf_reg);
out_conf_value |= (1 << pin); // Enable pull-up for the pin
pcal9714_write(out_conf_reg, out_conf_value);
}
// Then set the pin direction (input/output)
uint8_t config_reg = (port == 0) ? PCAL_CONF_PORT0 : PCAL_CONF_PORT1;
uint8_t current_config = pcal9714_read(config_reg);
if (mode == OUTPUT) {
current_config &= ~(1 << pin); // Clear the bit to set it as output
} else {
current_config |= (1 << pin); // Set the bit to set it as input
}
pcal9714_write(config_reg, current_config);
}
void pcal9714_configure_debounce(uint8_t debounce_pins_port0, uint8_t debounce_pins_port1, uint8_t debounce_counter_value) {
// Initialize SPI communication
pcal9714_init();
// Set up the switch debounce enable registers for port 0 and port 1
pcal9714_write(PCAL_DEBOUNCE_EN_REG0, debounce_pins_port0);
pcal9714_write(PCAL_DEBOUNCE_EN_REG1, debounce_pins_port1);
// Write the debounce counter value to the debounce count register
pcal9714_write(PCAL_DEBOUNCE_COUNT, debounce_counter_value);
}
/// @brief Write a value to a register on the pcal9714 device.
/// addr Address of the register.
/// value Value to write.
void pcal9714_write(uint8_t addr, uint8_t value)
{
digitalWrite(PCAL9714_SPI_CS_PIN, LOW); // Select the device
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
SPI.transfer(addr); // Send the address
SPI.transfer(value); // Send the value
SPI.endTransaction();
digitalWrite(PCAL9714_SPI_CS_PIN, HIGH); // Deselect the device
}
/// @brief Read a value from a port on the pcal9714 device.
/// port port addr
/// @return value of the port
uint8_t pcal9714_read_port(uint8_t port)
{
uint8_t regAddr = (port == 0) ? PCAL_INP_PORT0 : PCAL_INP_PORT1;
return pcal9714_read(regAddr);
}
/// @brief Read a value from a register on the pcal9714 device.
/// addr Address of the register.
/// @return Value read from the register.
uint8_t pcal9714_read(uint8_t addr)
{
uint8_t read_value = 0;
digitalWrite(PCAL9714_SPI_CS_PIN, LOW); // Select the device
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
SPI.transfer(addr | 0x80); // Send the address ORed with the read command
read_value = SPI.transfer(0xFF); // Send dummy data to read the value
SPI.endTransaction();
digitalWrite(PCAL9714_SPI_CS_PIN, HIGH); // Deselect the device
return read_value;
}
This is the header file: pcal9714.h
#ifndef _PCAL9714_H_
#define _PCAL9714_H_
#include <stdint.h>
#include <stdbool.h>
/**
********************************************************************************
* @file pcal9714.h
* @author ahmed
* @date 2024-04-22
* @brief Header file for the pcal9714 driver.
********************************************************************************
*/
typedef enum gpio_expander_channels_v10_t {
GPIOEXP_NONE0_V10,
GPIOEXP_NONE1_V10,
GPIOEXP_LIMIT_SWITCH_HOME_Y_V10,
GPIOEXP_SEL_WG_CD_V10,
GPIOEXP_SEL_FIBER_V10,
GPIOEXP_SEL_WG_AB_V10,
GPIOEXP_NONE2_V10,
GPIOEXP_NONE3_V10,
GPIOEXP_LIMIT_SWITCH_HOME_X_V10,
GPIOEXP_LIMIT_SWITCH_END_X_V10,
GPIOEXP_LIMIT_SWITCH_END_Y_V10,
GPIOEXP_CCB_DETECT_V10,
GPIOEXP_CC_DETECT_V10,
GPIOEXP_MOTOR_ENABLE_V10,
NUMBER_OF_GPIOEXP_PINS_V10
}gpio_expander_channels_v10_t;
#define PCAL_INP_PORT0 0x00
#define PCAL_INP_PORT1 0x01
#define PCAL_OUT_PORT0 0x02
#define PCAL_OUT_PORT1 0x03
#define PCAL_POL_INV_PORT0 0x04
#define PCAL_POL_INV_PORT1 0x05
#define PCAL_CONF_PORT0 0x06
#define PCAL_CONF_PORT1 0x07
#define PCAL_OUT_STR_PORT0A 0x40
#define PCAL_OUT_STR_PORT0B 0x41
#define PCAL_OUT_STR_PORT1A 0x42
#define PCAL_OUT_STR_PORT1B 0x43
#define PCAL_INP_LATCH_REG0 0x44
#define PCAL_INP_LATCH_REG1 0x45
#define PCAL_PULL_EN_PORT0 0x46
#define PCAL_PULL_EN_PORT1 0x47
#define PCAL_PULL_SEL_PORT0 0x48
#define PCAL_PULL_SEL_PORT1 0x49
#define PCAL_INT_MASK_PORT0 0x4A
#define PCAL_INT_MASK_PORT1 0x4B
#define PCAL_INT_STAT_PORT0 0x4C
#define PCAL_INT_STAT_PORT1 0x4D
#define PCAL_OUT_CONF_REG 0x4F
#define PCAL_INT_EDGE_REG0A 0x50
#define PCAL_INT_EDGE_REG0B 0x51
#define PCAL_INT_EDGE_REG1A 0x52
#define PCAL_INT_EDGE_REG1B 0x53
#define PCAL_INT_CLR_REG0 0x54
#define PCAL_INT_CLR_REG1 0x55
#define PCAL_INP_PORT_READ_WO_INT_CLR0 0x56
#define PCAL_INP_PORT_READ_WO_INT_CLR1 0x57
#define PCAL_OUT_CONF_REG0 0x58
#define PCAL_OUT_CONF_REG1 0x59
#define PCAL_DEBOUNCE_EN_REG0 0x5A
#define PCAL_DEBOUNCE_EN_REG1 0x5B
#define PCAL_DEBOUNCE_COUNT 0x5C
// Define the SPI CS pin
#define PCAL9714_SPI_CS_PIN 9 // CS pin for the PCAL9714 is connected to Arduino pin 9
void pcal9714_init(void);
void pcal9714_set_pin(uint8_t channel, uint8_t value);
uint8_t pcal9714_read_pin(uint8_t channel);
void pcal9714_set_mode(uint8_t channel, uint8_t value);
void pcal9714_write(uint8_t addr, uint8_t value);
uint8_t pcal9714_read_port(uint8_t port);
uint8_t pcal9714_read(uint8_t addr);
void pcal9714_configure_debounce(uint8_t debounce_pins_port0, uint8_t debounce_pins_port1, uint8_t debounce_counter_value);
#endif /* _PCAL9714_H_ */