Test application for the library MCP23017_I2C
Dependencies: DebugLibrary MCP23017_I2C mbed
Revision 1:e981573db063, committed 2015-01-09
- Comitter:
- Yann
- Date:
- Fri Jan 09 14:37:46 2015 +0000
- Parent:
- 0:1d91b4046326
- Child:
- 2:83b9df729e73
- Commit message:
- Add support of interruptions
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MCP23017_I2C.lib Fri Jan 09 14:37:46 2015 +0000 @@ -0,0 +1,1 @@ +MCP23017_I2C#ebd3a7cc9b92
--- a/MCP23017_I2C/AbstractGpioExpender.h Wed Jan 07 09:49:59 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -#pragma once - -#include <list> - -#include <mbed.h> - -#define GPA0 0 -#define GPA1 1 -#define GPA2 2 -#define GPA3 3 -#define GPA4 4 -#define GPA5 5 -#define GPA6 6 -#define GPA7 7 -#define GPB0 8 -#define GPB1 9 -#define GPB2 10 -#define GPB3 11 -#define GPB4 12 -#define GPB5 13 -#define GPB6 14 -#define GPB7 15 - -class AbstractGpioExpender { -public: - virtual void reset() = 0; - - virtual void setupInterrupts(const unsigned char p_mirroring, const unsigned char p_open, const unsigned char p_polarity) = 0; - virtual void setupInterruptPin(const unsigned char p_pinId, const unsigned char p_mode) = 0; - - virtual int read(const unsigned char p_pinId) = 0; - virtual int write(const unsigned char p_pinId, const unsigned char p_value) = 0; - - virtual unsigned char createBus(const std::list<unsigned char> p_lines, const PinMode p_mode = PullNone) = 0; - virtual void deleteBus(const unsigned char p_busId) = 0; - virtual int busRead(const unsigned char p_busId) = 0; - virtual int busWrite(const unsigned char p_busId, const unsigned char p_value) = 0; - -protected: - virtual bool writeRegister(const unsigned char p_registerId, const unsigned char p_value) = 0; - virtual bool readRegister(const unsigned char p_registerId, unsigned char * p_value) = 0; - -}; // End of class AbstractGpioExpender \ No newline at end of file
--- a/MCP23017_I2C/MCP23017_I2C.cpp Wed Jan 07 09:49:59 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,268 +0,0 @@ -/* mbed simplified access to Microchip MCP28x17 GPIO expender devices (I2C) - * Copyright (c) 2010-2012 ygarcia, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial pinions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#include <iostream> -#include <sstream> - -#include "MCP23017_I2C.h" - -#define IODIRA 0x00 -#define IODIRB 0x01 -#define IPOLA 0x02 -#define IPOLB 0x03 -#define GPINTENA 0x04 -#define GPINTENB 0x05 -#define DEFVALA 0x06 -#define DEFVALB 0x07 -#define INTCONA 0x08 -#define INTCONB 0x09 -#define IOCON 0x0a -#define GPPUA 0x0c -#define GPPUB 0x0d -#define INTFA 0x0e -#define INTFB 0x0f -#define INTCAPA 0x10 -#define INTCAPB 0x11 -#define GPIOA 0x12 -#define GPIOB 0x13 -#define OLATA 0x14 -#define OLATB 0x15 - -namespace MCP23017_I2C { - - unsigned char CMCP23017_I2C::I2CModuleRefCounter = 0; - - CMCP23017_I2C::CMCP23017_I2C(const PinName p_sda, const PinName p_scl, const unsigned char p_address, const PinName p_intA, const PinName p_intB, const PinName p_reset, const bool p_internalPullUp, const unsigned int p_frequency) : _gpioAFlags(0x00), _gpioBFlags(0x00), _internalId("") { - DEBUG_ENTER("CMCP23017_I2C") - - if (CMCP23017_I2C::I2CModuleRefCounter != 0) { - error("CMCP23017_I2C: Wrong params"); - } -#ifdef __DEBUG - std::ostringstream out(std::ostringstream::out); - out << "CMCP23017_I2C #" << CMCP23017_I2C::I2CModuleRefCounter; - _internalId.assign(out.str()); - DEBUG("CMCP23017_I2C: _internalId='%s'", _internalId.c_str()) -#endif // __DEBUG - _i2cInstance = new I2C(p_sda, p_scl); - CMCP23017_I2C::I2CModuleRefCounter += 1; - DEBUG_ENTER("CMCP23017_I2C: refCounter=%d", CMCP23017_I2C::I2CModuleRefCounter) - - _slaveAddress = (p_address << 1) | 0x40; // Slave address format is: 0 0 1 0 A3 A2 A1 R/W - DEBUG("CMCP23017_I2C: I2C slave adress: 0x%02x", _slaveAddress) - _i2cInstance->frequency(p_frequency); // Set the frequency of the I2C interface - - if (p_intA != NC) { - DEBUG("CMCP23017_I2C: INTA managed"); - _intA = new InterruptIn(p_intA); - if (p_internalPullUp) _intA->mode(PullDown); - _intA->enable_irq(); // Enable interrupt - } else { - DEBUG("CMCP23017_I2C: INTA not managed"); - _intA = NULL; // Not used - } - if (p_intB != NC) { - DEBUG("CMCP23017_I2C: INTB managed"); - _intB = new InterruptIn(p_intB); - if (p_internalPullUp) _intB->mode(PullDown); - _intB->enable_irq(); // Enable interrupt - } else { - DEBUG("CMCP23017_I2C: INTB not managed"); - _intB = NULL; // Not used - } - if (p_reset != NC) { - DEBUG("CMCP23017_I2C: RESET managed"); - _reset = new DigitalOut(p_reset); - _reset->write(1); // Disable reset - } else { - DEBUG("CMCP23017_I2C: RESET not managed"); - _reset = NULL; // Not used - } - - DEBUG_LEAVE("CMCP23017_I2C") - } - - CMCP23017_I2C::~CMCP23017_I2C() { - DEBUG_ENTER("~CMCP23017_I2C") - - // Release I2C instance - DEBUG_ENTER("~CMCP23017_I2C: refCounter=%d", CMCP23017_I2C::I2CModuleRefCounter) - CMCP23017_I2C::I2CModuleRefCounter -= 1; - if (CMCP23017_I2C::I2CModuleRefCounter == 0) { - delete _i2cInstance; - _i2cInstance = NULL; - } - // Release _wp if required - if (_intA != NULL) { - delete _intA; - } - if (_intB != NULL) { - delete _intB; - } - if (_reset != NULL) { - delete _reset; - } - - DEBUG_LEAVE("~CMCP23017_I2C") - } - - bool CMCP23017_I2C::Initialize(const unsigned char p_gpioAFlags, const unsigned char p_gpioBFlags) { - - // Configure default behavior - _gpioAFlags = p_gpioAFlags; - _gpioBFlags = p_gpioBFlags; - configure(_gpioAFlags, _gpioBFlags); - - return true; - } - - void CMCP23017_I2C::reset() { - DEBUG_ENTER("CMCP23017_I2C::reset") - if (_reset != NULL) { - _reset->write(0); - wait_us(1); - _reset->write(1); - wait_us(1); - configure(_gpioAFlags, _gpioBFlags); - } - DEBUG_LEAVE("CMCP23017_I2C::reset") - } - - void CMCP23017_I2C::setupInterrupts(const unsigned char p_mirroring, const unsigned char p_open, const unsigned char p_polarity) { - } - - void CMCP23017_I2C::setupInterruptPin(const unsigned char p_pinId, const unsigned char p_mode) { - } - - int CMCP23017_I2C::read(const unsigned char p_pinId) { - DEBUG_ENTER("CMCP23017_I2C::read") - DEBUG_LEAVE("CMCP23017_I2C::read") - return -1; - } - - int CMCP23017_I2C::write(const unsigned char p_pinId, const unsigned char p_value) { - DEBUG_ENTER("CMCP23017_I2C::write") - - DEBUG_LEAVE("CMCP23017_I2C::write") - return -1; - } - - unsigned char CMCP23017_I2C::createBus(const std::list<unsigned char> p_lines, const PinMode p_mode) { - return 0xff; - } - - void CMCP23017_I2C::deleteBus(const unsigned char p_busId) { - } - - int CMCP23017_I2C::busRead(const unsigned char p_busId) { - return -1; - } - - int CMCP23017_I2C::busWrite(const unsigned char p_busId, const unsigned char p_value) { - return -1; - } - - void CMCP23017_I2C::configure(const unsigned char p_gpioAFlags, const unsigned char p_gpioBFlags) { // TODO Optimization with sequential access - DEBUG_ENTER("CMCP23017_I2C::configure") - - // Setup IOCON - See REGISTER 1-6: IOCON – I/O EXPANDER CONFIGURATION REGISTER - unsigned char vregister = 0x08; - writeRegister(IOCON, vregister); - // Setup IODIR - See REGISTER 1-1: IODIR – I/O DIRECTION REGISTER (ADDR 0x00) - writeRegister(IODIRA, p_gpioAFlags); - writeRegister(IODIRB, p_gpioBFlags); - // Setup IPOL - See REGISTER 1-2: IPOL – INPUT POLARITY PORT REGISTER - vregister = 0x00; // GPIO register bit will reflect the same logic state of the input pin - writeRegister(IPOLA, vregister); - writeRegister(IPOLB, vregister); - // Setup GPPU - See REGISTER 1-7: GPPU – GPIO PULL-UP RESISTOR REGISTER - writeRegister(GPPUA, p_gpioAFlags); - writeRegister(GPPUB, p_gpioBFlags); - - // Setup interrupt - if (_intA != NULL) { - DEBUG("CMCP23017_I2C::configure: Setup INTA") - // Setup GPINTEN - See GPINTEN – INTERRUPT-ON-CHANGE PINS - writeRegister(GPINTENA, p_gpioAFlags); // Enable GPIO input pin for interrupt-on-change event - // Setup DEFVAL - See REGISTER 1-4: DEFVAL – DEFAULT VALUE REGISTER - vregister = 0x00; // Pin level change from 0 to 1 raises an interrupt - writeRegister(DEFVALA, vregister); - // Setup INTCON - REGISTER 1-5: INTCON – INTERRUPT-ON-CHANGE CONTROL REGISTER - vregister = 0xff; // Pin level change from 0 to 1 raises an interrupt - writeRegister(INTCONA, vregister); - } - if (_intB != NULL) { - DEBUG("CMCP23017_I2C::configure: Setup INTB") - // Setup GPINTEN - See GPINTEN – INTERRUPT-ON-CHANGE PINS - writeRegister(GPINTENB, p_gpioBFlags); // Enable GPIO input pin for interrupt-on-change event - // Setup DEFVAL - See REGISTER 1-4: DEFVAL – DEFAULT VALUE REGISTER - vregister = 0x00; // Pin level change from 0 to 1 raises an interrupt - writeRegister(DEFVALB, vregister); - // Setup INTCON - REGISTER 1-5: INTCON – INTERRUPT-ON-CHANGE CONTROL REGISTER - vregister = 0xff; // Pin level change from 0 to 1 raises an interrupt - writeRegister(INTCONB, vregister); - } - - DEBUG_LEAVE("CMCP23017_I2C::configure") - } - - bool CMCP23017_I2C::writeRegister(const unsigned char p_registerId, const unsigned char p_value) { - DEBUG_ENTER("CMCP23017_I2C::writeRegister: Memory address: 0x%02x - 0x%02x", p_registerId, p_value) - - // 1.Prepare buffer - char i2cBuffer[2]; // Register address + one byte of data - // 1.1. Memory address - i2cBuffer[0] = p_registerId; - // 1.2. Datas - i2cBuffer[1] = p_value; - DEBUG("CMCP23017_I2C::writeRegister: Data=0x%02x 0x%02x", i2cBuffer[0], i2cBuffer[1]) - - // 2. Send I2C start + I2C address + Memory Address + Datas + I2C stop - int result = _i2cInstance->write(_slaveAddress, i2cBuffer, 2); - wait(0.02); - - DEBUG_LEAVE("CMCP23017_I2C::writeRegister %x", (bool)(result == 0)) - return (bool)(result == 0); - } - - bool CMCP23017_I2C::readRegister(const unsigned char p_registerId, unsigned char * p_value) { - DEBUG_ENTER("CMCP23017_I2C::readRegister: Memory address: 0x%02x", p_registerId) - - // 1.Prepare buffer - char i2cBuffer[1]; // Register address + one byte of data - // 1.1. Memory address - i2cBuffer[0] = p_registerId; - DEBUG("CMCP23017_I2C::readRegister: Data=0x%02x", i2cBuffer[0]) - - // 2. Send I2C start + memory address - if (_i2cInstance->write(_slaveAddress, i2cBuffer, 1, true) == 0) { - wait(0.02); -// DEBUG("CMCP23017_I2C::readRegister: Write memory done") - // 2. Read data + I2C stop - int result = _i2cInstance->read(_slaveAddress, (char *)p_value, 1); - wait(0.02); - - DEBUG_LEAVE("C24LCXX_I2C::readRegister (byte): %x", (bool)(result == 0)) - return (bool)(result == 0); - } - - DEBUG_LEAVE("CMCP23017_I2C::readRegister false") - return false; - } - -} // End of namespace MCP23017_I2C
--- a/MCP23017_I2C/MCP23017_I2C.h Wed Jan 07 09:49:59 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -/* mbed simplified access to Microchip MCP28x17 GPIO expender devices (I2C) - * Copyright (c) 2014-2015 ygarcia, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#pragma once - -#include "Debug.h" - -#include "AbstractGpioExpender.h" - -namespace MCP23017_I2C { - /** This class provides simplified I2C access to a Microchip 2MCP28x17 GPIO expender. V0.0.0.1 - * - * Note that if the LPC1768 is powered in 3.3V and Microchip MCP28x17 GPIO expender device could be powered at 3.3V or 5V. - * In this case, you shall use a bi-directional level shifter for I2C-bus. Please refer to AN97055 (http://ics.nxp.com/support/documents/interface/pdf/an97055.pdf) - * Microchip MCP28x17 GPIO expender device reference: DS21952B - * - * Note that for I2C details, please visit http://www.datelec.fr/fiches/I2C.htm - * - * Note that this header file include following headers: - * - <string> - * - <vector> - * - <mbed.h> - * - * @author Yann Garcia (Don't hesitate to contact me: garcia.yann@gmail.com) - */ - class CMCP23017_I2C : public AbstractGpioExpender { - /** Reference counter used to guarentee unicity of the instance of I2C class - */ - static unsigned char I2CModuleRefCounter; - - /** Device address input: A0, A1, A2 (Pins <1,3>). See DS21203K/DS21189D - Figure 5-1: Control Byte Format for address format details - */ - unsigned char _slaveAddress; - /** Interrupt on GPIOA - */ - InterruptIn *_intA; - /** Interrupt on GPIOB - */ - InterruptIn *_intB; - /** Device reset pin - */ - DigitalOut *_reset; - /** PortA config - */ - unsigned char _gpioAFlags; - /** PortB config - */ - unsigned char _gpioBFlags; - /** An unique instance of I2C class - */ - I2C *_i2cInstance; - public: - /** Constructor with Write Protect command pin wired. Use it to manage the first I2C module on 3.3V or 5V network - * - * @param p_sda: MBed pin for SDA - * @param p_scl: MBed pin for SCL - * @param p_address: Device address input: A0, A1, A2 (Pins <1,3>) - * @param p_intA: MBed pin to manage interrupt on GPIOA, default value is NC, not connected - * @param p_intB: MBed pin to manage device reset. If NC, WP is not managed, default value is NC, not connected - * @param p_reset: MBed pin to manage Write Protect input. If NC, WP is not managed, default value is NC, not connected - * @param p_internalPullUp: Set to true to use internal pull-up resistor, default value is true - * @param p_frequency: Frequency of the I2C interface (SCL), default value is 400KHz - * Example: - * - If A1 and A2 pins are tired to Vdd and A0 is tired to Vss, address shall '00000110'B - * - If A0 and A1 pins are tired to Vss and A2 is tired to Vdd, address shall '00000100'B - */ - CMCP23017_I2C(const PinName p_sda, const PinName p_scl, const unsigned char p_address, const PinName p_intA = NC, const PinName p_intB = NC, const PinName p_reset = NC, const bool p_internalPullUp = true, const unsigned int p_frequency = 400000); - - /** Destructor - */ - virtual ~CMCP23017_I2C(); - - /** Initialize the module, configuring the module and starting the clock - * @param p_gpioAFlags GPIO A port configuration: bit set for input mode, 0 for output mode. Default: ports as outputs - * @param p_gpioBFlags GPIO B port configuration: bit set for input mode, 0 for output mode. Default: ports as outputs - * - * @return true on success, false otherwise - */ - bool Initialize(const unsigned char p_gpioAFlags = 0x00, const unsigned char p_gpioBFlags = 0x00); - - /** Used to return the unique instance of I2C instance - */ - inline const I2C * operator * () { return (const I2C *)_i2cInstance; }; - - /** Reset the device - */ - virtual void reset(); - - virtual void setupInterrupts(const unsigned char mirroring, const unsigned char open, const unsigned char polarity); - virtual void setupInterruptPin(const unsigned char p_pinId, const unsigned char mode); - - virtual int read(const unsigned char p_portId); - virtual int write(const unsigned char p_portId, const unsigned char p_value); - - virtual unsigned char createBus(const std::list<unsigned char> p_lines, const PinMode p_mode = PullNone); - virtual void deleteBus(const unsigned char p_busId); - virtual int busRead(const unsigned char p_busId); - virtual int busWrite(const unsigned char p_busId, const unsigned char p_value); - - private: - - /** Configure the device: - * BANK0 (A register followed by B register) - * INTs: active low - * INTs for all ports - * INTs are not mirrored - * @param p_gpioAFlags GPIO A port configuration: bit set for input mode, 0 for output mode. Default: ports as outputs - * @param p_gpioBFlags GPIO B port configuration: bit set for input mode, 0 for output mode. Default: ports as outputs - */ - void configure(const unsigned char p_gpioAFlags, const unsigned char p_gpioBFlags); - - /** Write value to a register - * @param p_address The register address - * @param p_byte The value to write to the register - * @return 1 on success, false otherwise - */ - virtual bool writeRegister(const unsigned char p_registerId, const unsigned char p_value); - - virtual bool readRegister(const unsigned char p_registerId, unsigned char * p_value); - - private: - /** Internal reference identifier - */ - std::string _internalId; - - }; // End of class CMCP23017_I2C - -} // End of namespace _MCP23017_I2C - -using namespace MCP23017_I2C;
--- a/main.cpp Wed Jan 07 09:49:59 2015 +0000 +++ b/main.cpp Fri Jan 09 14:37:46 2015 +0000 @@ -11,6 +11,7 @@ DigitalOut g_availableLed(LED1); // To verify if program in running Ticker g_available; // LED1 will flash with a period of 2s char DisplayMenuAndGetChoice(); +void GpioAIntr(); // Interrupt on GPIOA static CMCP23017_I2C g_gpioExp(p9, p10, 0x27, p15, p16, p17); @@ -18,7 +19,9 @@ // Launch available indicator g_available.attach(&AvailableIndicator, 2.0); - g_gpioExp.Initialize(); + g_gpioExp.Initialize(0x01); // GpioA<0> as input port, no interrupt mirroring, Active low + g_gpioExp.setupInterruptPin(GPA0, AbstractGpioExpender::OnFalling); // A switch with pull-up is connected to GPIOA<0>, interrupt on falling mode + g_gpioExp.setIntrACallback(GpioAIntr); // Set callback for interrup on GPIOA<0> while(true) { switch (DisplayMenuAndGetChoice()) { @@ -34,6 +37,18 @@ case 'd': g_gpioExp.write(GPB2, 0); break; + case 'e': + g_gpioExp.write(GPB3, 1); + break; + case 'f': + g_gpioExp.write(GPB3, 0); + break; + case 'g': + g_gpioExp.write(GPB7, 1); + break; + case 'h': + g_gpioExp.write(GPB7, 0); + break; case 'r': g_gpioExp.reset(); break; @@ -56,11 +71,23 @@ std::cout << "\r" << std::endl << "\r" << std::endl << "MCP23017_I2C v0.1\r" << std::endl; std::cout << "\tSet PortB-0 :\t\ta\r" << std::endl; std::cout << "\tUnset PortB-0 :\t\tb\r" << std::endl; - std::cout << "\tUnset PortB-2 :\t\tc\r" << std::endl; + std::cout << "\tSet PortB-2 :\t\tc\r" << std::endl; std::cout << "\tUnset PortB-2 :\t\td\r" << std::endl; + std::cout << "\tSet PortB-3 :\t\te\r" << std::endl; + std::cout << "\tUnset PortB-3 :\t\tf\r" << std::endl; + std::cout << "\tSet PortB-7 :\t\tg\r" << std::endl; + std::cout << "\tUnset PortB-7 :\t\th\r" << std::endl; std::cout << "\tReset device :\t\tr\r" << std::endl; std::cout << "Enter your choice: " << std::flush; value = getchar(); std::cout << "\r" << std::endl; return value; } + +void GpioAIntr() { + unsigned char gpioId, gpioValue; + wait(0.6); // Debounce timer + g_gpioExp.getLastInterruptPin(&gpioId, &gpioValue); // Get interrupt info and clear it + std::cout << "\r" << std::endl << "GpioAIntr: interrupt on pin #" << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(gpioId) << " - value: " << static_cast<unsigned int>(gpioValue) << "\r" << std::endl; +} +