This software drives a PCA9675 device via an I2C bus. Included functions allow you to read the device ID, set the IO direction, and read and write from the device.
Revision 0:3331b5950572, committed 2010-11-23
- Comitter:
- DavidGilesHitex
- Date:
- Tue Nov 23 10:59:14 2010 +0000
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Header/PCA9675.h Tue Nov 23 10:59:14 2010 +0000 @@ -0,0 +1,46 @@ +#include "mbed.h" + +#ifndef PCA9675__ +#define PCA9675__ +#endif + +/* Define a class for PCA9675 */ +class PCA9675 + { + /* Private members first */ + private: + uint8_t My_Lcoal_Slave_Address; + uint8_t My_Local_Port0_Direction; + uint8_t My_Local_Port1_Direction; + sint32_t reset(); /* Reset the device using a general call */ + I2C *My_Local_I2C; /* make use of the existing I2C class for i2C calls */ + + /* Public members next */ + public: + PCA9675(I2C *Selected_I2C_Channel, uint8_t Slave_Address); /* Constructor - create with the slave address */ + ~PCA9675(); /* Destructor */ + sint32_t init(uint8_t port0_Direction, uint8_t port1_Direction); /* Reset the device and setup the IO direction */ + sint32_t write_data(uint8_t port0_payload, uint8_t port1_payload); /* Write two bytes of data to the device */ + sint32_t read_data(uint8_t *read_port0, uint8_t *read_port1); /* Read two bytes from the device */ + sint32_t read_device_ID(uint8_t *manufacturer, uint16_t *part_ident, uint8_t *die_revision); + uint8_t read_slave_address(); /* Read the configured slave address */ + + + enum PCA9675_Defines + { + eI2C_ACK = 0, + ePCA9675_RESET_COMMAND = 6, + ePCA9675_RESET_ADDRESS = 0, + ePCA9675_PORT0 = 0, + ePCA9675_PORT1 = 1, + eI2C_REPEATED_START = 1, + eI2C_NO_REPEATED_START = 0 + }; + + + }; + + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Header/misra_types.h Tue Nov 23 10:59:14 2010 +0000 @@ -0,0 +1,32 @@ +/* Hitex Standard Header File */ +/* Types As Recommended By MISRA */ + + + +/* Bytes (8bit length) */ +typedef unsigned char uint8_t; +typedef char sint8_t; + +/* Half Words (16bit lengths) */ +typedef unsigned short uint16_t; +typedef short sint16_t; + +/* Words (32bit lengths) */ +/* Also int */ +typedef unsigned int uint32_t; +typedef long sint32_t; + +/* Double Words */ +/* Also long long and long double */ +typedef unsigned long long uint64_t; +typedef long long sint64_t; + + +/* + Constants should use the following suffixes also + +u - Unsigned +f - floating +L - Long double (64bit) + +*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Source/PCA9675.cpp Tue Nov 23 10:59:14 2010 +0000 @@ -0,0 +1,139 @@ +/* C++ Source Code for PCA9675 I2C 16bit IO latch */ +/* ********************************************** */ + + +#include "misra_types.h" +#include "mbed.h" +#include "PCA9675.h" + + + + +/* Constructor */ +PCA9675::PCA9675(I2C *Selected_I2C_Channel, uint8_t Slave_Address) + { + My_Local_I2C = Selected_I2C_Channel; + My_Lcoal_Slave_Address = Slave_Address; + } + +/* Destructor */ +PCA9675::~PCA9675() + { + } + + + +/* Setup and configure the I/O latch */ +sint32_t PCA9675::init(uint8_t Port0_Direction, uint8_t Port1_Direction) + { + sint32_t Ack_Status = eI2C_ACK; + + Ack_Status = reset(); /* Reset the device */ + My_Local_Port0_Direction = Port0_Direction; /* Keep a copy of the port0 direction */ + My_Local_Port1_Direction = Port1_Direction; /* Keep a copy of the port1 direction */ + + if (Ack_Status == eI2C_ACK) + { + Ack_Status = write_data(Port0_Direction, Port1_Direction); /* This configures the I/O direction: each bit: 0=output, 1=inout */ + } + + return Ack_Status; + } + + + + +/* Reset the device */ +sint32_t PCA9675::reset() + { + sint32_t Ack_Status = eI2C_ACK; + sint8_t reset_command = ePCA9675_RESET_COMMAND; /* Reset command following a general call, address 0 will reset the device */ + + Ack_Status = My_Local_I2C -> write(ePCA9675_RESET_ADDRESS << 1, &reset_command, 1, eI2C_NO_REPEATED_START); + + return Ack_Status; + } + + +/* Write two byte of data to the device */ +sint32_t PCA9675::write_data(uint8_t port0_payload, uint8_t port1_payload) + { + sint32_t Ack_Status = eI2C_ACK; + sint8_t tx_array[2]; /* Local array of data to be transmitted */ + + /* If we try and write a 0/1 to a pin that is designated an input we must force the state to a 1(input) */ + /* as the device is quasi birectional */ + /* This is to avoid turning the pin from a designated input into an output by mistake */ + /* If the pin is designated as input and we have logic 1 on the input we and indvertantly write a 0 to it */ + /* then we will have a large current flow input the pin */ + /* Hence the 'or' block below prevents unwanted damage to the pin */ + /* Quasi direction is: 1 = input, 0 = output */ + port0_payload = (port0_payload | My_Local_Port0_Direction); + port0_payload = (port1_payload | My_Local_Port1_Direction); + + tx_array[ePCA9675_PORT0] = port0_payload; /* First is for Port 0 */ + tx_array[ePCA9675_PORT1] = port1_payload; /* Second is for Port 1 */ + + Ack_Status = My_Local_I2C -> write(My_Lcoal_Slave_Address << 1, tx_array, 2, eI2C_NO_REPEATED_START); + return Ack_Status; + } + + +/* Read two bytes from the device */ +sint32_t PCA9675::read_data(uint8_t *read_port0, uint8_t *read_port1) + { + sint32_t Ack_Status = eI2C_ACK; + sint8_t rx_array[2]; /* Local reception array */ + + Ack_Status = My_Local_I2C -> read(My_Lcoal_Slave_Address << 1, rx_array, 2, eI2C_NO_REPEATED_START); + + *read_port0 = rx_array[ePCA9675_PORT0]; /* transfer data back to pointer */ + *read_port1 = rx_array[ePCA9675_PORT1]; /* transfer data back to pointer */ + return Ack_Status; + } + + +/* Read the device ID */ +sint32_t PCA9675::read_device_ID(uint8_t *manufacturer, uint16_t *part_ident, uint8_t *die_revision) + + { + sint32_t Ack_Status = eI2C_ACK; + sint8_t rx_array[3] = {0,0,0}; + uint32_t temp_value = 0; + sint8_t tx_array = (My_Lcoal_Slave_Address << 1); + + + Ack_Status = My_Local_I2C -> write(0xF8, &tx_array, 1, eI2C_REPEATED_START); + Ack_Status = My_Local_I2C -> read(0xF9, rx_array, 3, eI2C_NO_REPEATED_START); + + temp_value = rx_array[0]; + temp_value = (temp_value << 8); + + temp_value = (temp_value | rx_array[1]); + temp_value = (temp_value << 8); + + temp_value = (temp_value | rx_array[2]); + + + *die_revision = (uint8_t) (temp_value & 0x00000003); /* 3 LSB bits are die revision */ + temp_value = (temp_value >> 3); + + *part_ident = (uint16_t) (temp_value & 0x00001FFF); /* Next 13 bits are part identification */ + temp_value = (temp_value >> 13); + + *manufacturer = (uint8_t) (temp_value & 0x000000FF); /* Next 8 bits are manufacturers name */ + + return Ack_Status; + } + + + + +/* Read the configured slave address */ +uint8_t PCA9675::read_slave_address() + { + return My_Lcoal_Slave_Address; + } + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Source/main.cpp Tue Nov 23 10:59:14 2010 +0000 @@ -0,0 +1,91 @@ +/* PCA9675 Device Driver C++ Example */ +/* ********************************* */ + +#include "mbed.h" +#include "misra_types.h" /* MISRA Types */ +#include "PCA9675.h" + + +#define PCA9675_BASE_BOARD_SLAVE_ADDRESS 0x20 + + +/* I2C Interface */ +/* Create a master I2C bus called CNTRL_i2C using pins 9 and 10 for SDA, & SCL respectively */ +/* This I2C bus can be used fr many peripherals and not just the PCA9675 */ +I2C CNTRL_i2c(p9, p10); + +/* Configure the USB as a virtual communications port */ +Serial pc(USBTX, USBRX); + +/* Create a global object of PCA96755 class called BaseBoardLatch */ +/* this device will use CNTRL_i2c bus and has a slave address of PCA9675_BASE_BOARD_SLAVE_ADDRESS*/ +PCA9675 BaseBoardLatch(&CNTRL_i2c, PCA9675_BASE_BOARD_SLAVE_ADDRESS); + + +int main() + { + uint8_t port0_payload = 0; + uint8_t port1_payload = 0; + uint8_t manufacturer = 0; + uint16_t part_ident = 0; + uint8_t die_revision = 0; + uint8_t MySlaveAddress = 0; + sint32_t Ack_Status = 0; + + pc.baud(115000); /* Baud rate should be 115k baud */ + pc.format(8,Serial::None,1); /* format is 8 data bits, no stop bit, no parity */ + pc.printf("\n\n\n\n\n\n\n\rWelcome to the I2C PCA9675 Driver Test Routines for mbed\n\r\n"); + + CNTRL_i2c.frequency(400000); /* Set the I2C to be 400kHz */ + + /* Read the PCA9575 device ID */ + pc.printf("Reading the device ID\n\r"); + Ack_Status = BaseBoardLatch.read_device_ID(&manufacturer, &part_ident, &die_revision); + pc.printf("Read ID: Ack status = "); + if (Ack_Status == BaseBoardLatch.eI2C_ACK) pc.printf("ACK\n\r"); + else pc.printf ("NACK\n\r"); + pc.printf("The stored identification for this device is:\n\r"); + pc.printf(" * Manufacturer Code = 0x%.2x\n\r", manufacturer); + pc.printf(" * Part Idenfification = 0x%.4x\n\r", part_ident); + pc.printf(" * Die Revision = 0x%.1x\n\r", die_revision); + + + /* Use this code for output */ + + /* Setup the I/O direction : for each bit 1=input and 0=output */ + /* Order is Port0 and Port1 */ + pc.printf("\nSetting the device for quasi output mode\n\r"); + Ack_Status = BaseBoardLatch.init(0x00, 0x00); + pc.printf("Initialise: Ack status = "); + if (Ack_Status == BaseBoardLatch.eI2C_ACK) pc.printf("ACK\n\r"); + else pc.printf ("NACK\n\r"); + + pc.printf("Writing data to the latch\n\r"); + Ack_Status = BaseBoardLatch.write_data(port0_payload, port1_payload); /* Write two bytes of data to the device */ + pc.printf("Write data: Ack status = "); + if (Ack_Status == BaseBoardLatch.eI2C_ACK) pc.printf("ACK\n\r"); + else pc.printf ("NACK\n\r"); + + + /* Use this code for input */ + + /* Setup the I/O direction : for each bit 1=input and 0=output */ + /* Order is Port0 and Port1 */ + pc.printf("\nSetting the device for quasi input mode\n\r"); + Ack_Status = BaseBoardLatch.init(0xff, 0xff); + pc.printf("Initialise: Ack status = "); + if (Ack_Status == BaseBoardLatch.eI2C_ACK) pc.printf("ACK\n\r"); + else pc.printf ("NACK\n\r"); + + Ack_Status = BaseBoardLatch.read_data(&port0_payload, &port1_payload); /* Read two bytes from the device */ + pc.printf("Read data: Ack status = ", Ack_Status); + if (Ack_Status == BaseBoardLatch.eI2C_ACK) pc.printf("ACK\n\r"); + else pc.printf ("NACK\n\r"); + pc.printf("Port0 = 0x%.2x, Port1 = 0x%.2x\n\r", port0_payload, port1_payload); + + + /* Read back the slave address of the PCA9675 object if we need to recall it */ + MySlaveAddress = BaseBoardLatch.read_slave_address(); + pc.printf("\nThe 7 bit Slave address: is = 0x%.2x\n\r", MySlaveAddress); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Tue Nov 23 10:59:14 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e