Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of SoftwareI2C by
Revision 0:6f6cfcdfe3d8, committed 2012-04-01
- Comitter:
- p3p
- Date:
- Sun Apr 01 19:21:03 2012 +0000
- Child:
- 1:6966eacc5914
- Commit message:
- Initial Public Release
Changed in this revision
SoftwareI2C.cpp | Show annotated file Show diff for this revision Revisions of this file |
SoftwareI2C.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SoftwareI2C.cpp Sun Apr 01 19:21:03 2012 +0000 @@ -0,0 +1,211 @@ +/* + * mbed Library to use a software master i2c interface on any GPIO pins + * Copyright (c) 2012 Christopher Pepper + * Released under the MIT License: http://mbed.org/license/mit + */ + +#include "SoftwareI2C.h" + +/* + * @brief Initializes interface + * @param sda GPIO pin to use as I2C SDA + * @param scl GPIO pin to use as I2C SCL + */ + +SoftwareI2C::SoftwareI2C(PinName sda, PinName scl) : _sda(sda) , _scl(scl) { + _scl.output(); + _scl.mode(OpenDrain); + _sda.output(); + _sda.mode(OpenDrain); + + _device_address = 0; + + initialise(); +} + +SoftwareI2C::~SoftwareI2C() { + +} + +/* + * @brief Read 1 or more bytes from the I2C slave + * @param device_address The address of the device to read from + * @param data An allocated array to read the data into + * @param data_bytes Number of bytes to read (must be equal to or less then the allocated memory in data) + */ +void SoftwareI2C::read(uint8_t device_address, uint8_t* data, uint8_t data_bytes) { + if (data == 0 || data_bytes == 0) return; + + device_address = device_address | 0x01; + start(); + putByte(device_address); + getAck(); + for (int x = 0; x < data_bytes; ++x) { + data[x] = getByte(); + if ( x < (data_bytes -1)) { //ack all but the final byte + giveAck(); + } + } + stop(); +} + +/* + * @brief Write 1 or more bytes to the I2C slave + * @param device_address The address of the device to write to + * @param data An array to write the data from + * @param data_bytes Number of bytes to write from array + */ +void SoftwareI2C::write(uint8_t device_address, uint8_t* data, uint8_t data_bytes) { + if (data == 0 || data_bytes == 0) return; + + device_address = device_address & 0xFE; + start(); + putByte(device_address); + getAck(); + for ( int x = 0; x < data_bytes; ++x ) { + putByte(data[x]); + getAck(); + } + stop(); +} + +/* + * @brief Write 1 byte to the I2C slave + * @param device_address The address of the device to write to + * @param byte The data to write + */ +void SoftwareI2C::write(uint8_t device_address, uint8_t byte) { + device_address = device_address & 0xFE; + start(); + putByte(device_address); + getAck(); + putByte(byte); + getAck(); + stop(); +} + +/* + * @brief Read 1 or more bytes from the I2C slave at the specified memory address + * @param device_address The address of the device to read from + * @param start_address The memory address to read from + * @param data The allocated array to read into + * @param data_bytes The number of bytes to read + */ +void SoftwareI2C::randomRead(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes) { + if (data == 0 || data_bytes == 0) return; + + device_address = device_address & 0xFE; + start(); + putByte(device_address); + if (!getAck()) { + return; + } + putByte(start_address); + if (!getAck()) { + return; + } + + device_address=device_address | 0x01; + start(); + putByte(device_address); + if (!getAck()) { + return; + } + for ( int x = 0; x < data_bytes; ++x) { + data[x] = getByte(); + if (x != (data_bytes - 1)) giveAck(); + } + stop(); +} + +/* + * @brief Write 1 byte to the I2C slave at the specified memory address + * @param device_address The address of the device to write to + * @param start_address The memory address to write to + * @param byte The data to write + */ +void SoftwareI2C::randomWrite(uint8_t device_address, uint8_t start_address, uint8_t byte) { + device_address = device_address & 0xFE; + start(); + putByte(device_address); + getAck(); + putByte(start_address); + getAck(); + putByte(byte); + getAck(); + stop(); +} + +/* + * @brief Write 1 or more bytes to the I2C slave at the specified memory address + * @param device_address The address of the device to write to + * @param start_address The memory address to write to + * @param data The data to write + * @param data_bytes The number of bytes to write + */ +void SoftwareI2C::randomWrite(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes) { + if (data == 0 || data_bytes == 0) return; + + device_address = device_address & 0xFE; + start(); + putByte(device_address); + getAck(); + putByte(start_address); + getAck(); + for ( int x = 0; x <= data_bytes; ++x ) { + putByte(data[x]); + getAck(); + } + stop(); +} + +/* + * @brief Read 2 bytes from the I2C slave at the specified memory address and return them as an 16bit unsigned integer + * @param device_address The address of the device to read from + * @param start_address The memory address to read from + * @return MSB 16bit unsigned integer + */ +uint16_t SoftwareI2C::read16(uint8_t device_address, uint8_t start_address) { + uint8_t short_array[2] = {0, 0}; + randomRead(device_address, start_address, short_array, 2 ); + uint16_t value = 0; + value = short_array[0] << 8; + value |= short_array[1]; + + return value; +} + +/* + * @brief Read 3 bytes from the I2C slave at the specified memory address and return them as an 32bit unsigned integer + * @param device_address The address of the device to read from + * @param start_address The memory address to read from + * @return MSB 32bit unsigned integer + */ +uint32_t SoftwareI2C::read24(uint8_t device_address, uint8_t start_address) { + uint8_t value_array[4] = {0, 0, 0}; + randomRead(device_address, start_address, value_array, 3 ); + uint32_t value = 0; + value = value_array[0] << 16; + value |= value_array[1] << 8; + value |= value_array[2]; + + return value; +} + +/* + * @brief Read 4 bytes from the I2C slave at the specified memory address and return them as an 32bit unsigned integer + * @param device_address The address of the device to read from + * @param start_address The memory address to read from + * @return MSB 32bit unsigned integer + */ +uint32_t SoftwareI2C::read32(uint8_t device_address, uint8_t start_address) { + uint8_t value_array[4] = {0, 0, 0, 0}; + randomRead(device_address, start_address, value_array, 4 ); + uint32_t value = 0; + value = value_array[0] << 24; + value |= value_array[1] << 16; + value |= value_array[2] << 8; + value |= value_array[3]; + + return value; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SoftwareI2C.h Sun Apr 01 19:21:03 2012 +0000 @@ -0,0 +1,139 @@ +/* + * mbed Library to use a software master i2c interface on any GPIO pins + * Copyright (c) 2012 Christopher Pepper + * Released under the MIT License: http://mbed.org/license/mit + */ + +#ifndef _SOFTWARE_I2C_H_ +#define _SOFTWARE_I2C_H_ + +#include "mbed.h" + +/** + * @brief SoftwareI2C class + */ + +class SoftwareI2C { +public: + SoftwareI2C(PinName sda, PinName scl); + ~SoftwareI2C(); + + void read(uint8_t device_address, uint8_t* data, uint8_t data_bytes); + void write(uint8_t device_address, uint8_t* data, uint8_t data_bytes); + void write(uint8_t device_address, uint8_t byte); + void randomRead(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes); + void randomWrite(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes); + void randomWrite(uint8_t device_address, uint8_t start_address, uint8_t byte); + + uint8_t read8(uint8_t device_address, uint8_t start_address); + uint16_t read16(uint8_t device_address, uint8_t start_address); + uint32_t read24(uint8_t device_address, uint8_t start_address); + uint32_t read32(uint8_t device_address, uint8_t start_address); + + void setDeviceAddress(uint8_t address){ + _device_address = address; + } + + inline void initialise() { + _scl.output(); + _sda.output(); + + _sda = 1; + _scl = 0; + wait_us(10); + + for ( int n = 0; n <= 3; ++n ) { + stop(); + } + } + +private: + inline void start() { + _sda.output(); + wait_us(1); + _scl = 1; + _sda = 1; + wait_us(1); + _sda = 0; + wait_us(1); + _scl = 0; + wait_us(1); + } + + inline void stop() { + _sda.output(); + wait_us(1); + _sda = 0; + wait_us(1); + _scl = 1; + wait_us(1); + _sda = 1; + } + + inline void putByte(uint8_t byte) { + _sda.output(); + for ( int n = 8; n > 0; --n) { + wait_us(1); + _sda = byte & (1 << (n-1)); + _scl = 1; + wait_us(1); + _scl = 0; + } + _sda = 1; + } + + inline uint8_t getByte() { + uint8_t byte = 0; + + _sda.input(); //release the data line + _sda.mode(OpenDrain); + + wait_us(1); + + for ( int n = 8; n > 0; --n ) { + _scl=1; //set clock high + wait_us(1); + byte |= _sda << (n-1); //read the bit + wait_us(1); + _scl=0; //set clock low + wait_us(1); + } + + _sda.output(); //take data line back + + return byte; + } + + inline void giveAck() { + _sda.output(); + wait_us(1); + _sda = 0; + _scl = 1; + wait_us(1); + _scl = 0; + _sda = 1; + + } + + inline bool getAck() { + _sda.output(); + _sda = 1; + _scl = 1; + _sda.input(); + _sda.mode(OpenDrain); + wait_us(1); + _scl = 0; + + if(_sda != 0){return false;} + + wait_us(1); + return true; + } + + DigitalInOut _sda; + DigitalInOut _scl; + + uint8_t _device_address; +}; + +#endif \ No newline at end of file