I2C not yet integrated
Tested working with single and differential voltages.
Connect SCL (pin 11) to D15 Connect SDA (pin 10) to D14 Connect pin 16 to +5v Connect pin 9 to gnd
Diff: LT_I2C.cpp
- Revision:
- 0:1473318f27b6
- Child:
- 1:4e4194db7cd6
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LT_I2C.cpp Wed Nov 16 15:54:08 2016 +0000 @@ -0,0 +1,527 @@ + +/*! +LT_I2C: Routines to communicate with ATmega328P's hardware I2C port. + +@verbatim + +LT_I2C contains the low level routines to communicate with devices using the +ATMega328's onboard hardware I2C port. Each routine checks the Two Wire Status +Register (TWSR) at the end of the transaction and returns 0 if successful and 1 +if not successful. + +I2C Frequency = (CPU Clock frequency)/(16+2(TWBR)*Prescaler) + +TWBR-Two Wire Bit Rate Register +TWCR=Two Wire Control Register (TWINT TWEA TWSTA TWSTO TWWC TWEN - TWIE) +TWSR=Two Wire Status Register + +Prescaler Values: +TWSR1 TWSR0 Prescaler + 0 0 1 + 0 1 4 + 1 0 16 + 1 1 64 + +Examples: +CPU Frequency = 16Mhz on Arduino Uno +I2C Frequency Prescaler TWSR1 TWSR0 TWBR + 1khz 64 1 1 125 + 10khz 64 1 1 12 + 50khz 16 1 0 10 + 100khz 4 0 1 18 + 400khz 1 0 0 12 + +@endverbatim + +REVISION HISTORY +$Revision: 5469 $ +$Date: 2016-07-22 17:01:32 -0700 (Fri, 22 Jul 2016) $ + +Copyright (c) 2013, Linear Technology Corp.(LTC) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of Linear Technology Corp. + +The Linear Technology Linduino is not affiliated with the official Arduino team. +However, the Linduino is only possible because of the Arduino team's commitment +to the open-source community. Please, visit http://www.arduino.cc and +http://store.arduino.cc , and consider a purchase that will help fund their +ongoing work. +*/ + +//! @defgroup LT_I2C LT_I2C: Routines to Communicate With ATmega328P's hardware I2C port. + +/*! @file + @ingroup LT_I2C + Library for LT_I2C: Routines to Communicate With ATmega328P's hardware I2C port. +*/ + +//#include <Arduino.h> +#include <stdint.h> +//#include <util/delay.h> +#include "Linduino.h" +#include "LT_I2C.h" + +//! CPU master clock frequency +#ifndef F_CPU +#define F_CPU 16000000UL +#endif + +// Read a byte, store in "value". +int8_t i2c_read_byte(uint8_t address, uint8_t *value) +{ + //uint8_t ret=0; +// if (i2c_start()!=0) //I2C START +// return(1); //Stop and return 0 if START fail +// ret |= i2c_write((address<<1)|I2C_READ_BIT); // Write the I2C 7-bit address with R bit +// if (ret != 0) // Returns 1 if failed +// return(1); +// +// *value = i2c_read(WITH_NACK); // Read byte from I2C Bus with NAK +// i2c_stop(); //I2C STOP +// return(0); // Return success + return 0; + +} + +// Write "value" byte to device at "address" +int8_t i2c_write_byte(uint8_t address, uint8_t value) +{ + //int8_t ret= 0 ; +// +// if (i2c_start()!=0) //I2C START +// return(1); //Stop and return 0 if START fail +// ret |= i2c_write((address<<1)|I2C_WRITE_BIT); //Write the I2C 7 bit address with W bit +// ret |= i2c_write(value); //Write value +// i2c_stop(); //I2C STOP +// if (ret!=0) // Returns 1 if failed +// return(1); +// return(0); // Returns 0 if success + return 0; +} + +// Read a byte of data at register specified by "command", store in "value" +int8_t i2c_read_byte_data(uint8_t address, uint8_t command, uint8_t *value) +{ + //int8_t ret = 0; +// if (i2c_start()!=0) //I2C START +// return(1); //Stop and return 0 if START fail +// ret |= i2c_write((address<<1)|I2C_WRITE_BIT); // Write 7 bit address with W bit +// ret|= i2c_write(command); // Set register to be read to command +// if (i2c_start()!=0) //I2C repeated START +// { +// i2c_stop(); //Attempt to issue I2C STOP +// return(1); //Stop and return 0 if START fail +// } +// ret |= i2c_write((address<<1)|I2C_READ_BIT); // Write 7 bit address with R bit +// *value = i2c_read(WITH_NACK); // Read byte from buffer with NAK +// i2c_stop(); // I2C STOP +// if (ret!=0) //If there was a NAK return 1 +// return(1); +// return(0); // Return success + return 0; +} + +// Write a byte of data to register specified by "command" +int8_t i2c_write_byte_data(uint8_t address, uint8_t command, uint8_t value) +{ + //int8_t ret = 0; +// +// if (i2c_start()!=0) //I2C START +// return(1); //Stop and return 0 if START fail +// ret |= i2c_write((address<<1)|I2C_WRITE_BIT); // Write 7 bit address with W bit +// ret|= i2c_write(command); // Set register to be read to command +// ret|= i2c_write(value); +// i2c_stop(); // I2C STOP +// +// if (ret!=0) //If there was a NAK return 1 +// return(1); +// return(0); // Return success + return 0; +} + +// Read a 16-bit word of data from register specified by "command" +int8_t i2c_read_word_data(uint8_t address, uint8_t command, uint16_t *value) +{ + //int8_t ret = 0; +// +// union +// { +// uint8_t b[2]; +// uint16_t w; +// } data; +// +// +// if (i2c_start()!=0) //I2C START +// return(1); //Stop and return 0 if START fail +// ret |= i2c_write((address<<1)|I2C_WRITE_BIT); // Write 7 bit address with W bit +// ret |= i2c_write(command); // Set register to be read to command +// if (i2c_start()!=0) //I2C START +// { +// i2c_stop(); //Attempt to issue I2C STOP +// return(1); //Stop and return 0 if START fail +// } +// ret |= i2c_write((address<<1)|I2C_READ_BIT); // Write 7 bit address with R bit +// +// data.b[1] = i2c_read(WITH_ACK); // Read MSB from buffer +// data.b[0] = i2c_read(WITH_NACK); // Read LSB from buffer +// i2c_stop(); //I2C STOP +// +// *value = data.w; +// +// if (ret!=0) //If NAK +// return (1); //return 1 +// return(0); // Return success + return 0; +} + +// Write a 16-bit word of data to register specified by "command" +int8_t i2c_write_word_data(uint8_t address, uint8_t command, uint16_t value) +{ + //int8_t ret=0; +// +// union +// { +// uint8_t b[2]; +// uint16_t w; +// } data; +// data.w = value; +// +// if (i2c_start()!=0) //I2C START +// return(1); //Stop and return 0 if START fail +// ret |= i2c_write((address<<1)|I2C_WRITE_BIT); // Write 7 bit address with W bit +// ret|= i2c_write(command); // Set register to be read to command +// ret|= i2c_write(data.b[1]); //Write MSB +// ret|= i2c_write(data.b[0]); //Write LSB; +// +// i2c_stop(); // I2C STOP +// +// if (ret!=0) //If there was a NAK return 1 +// return(1); +// return(0); + + return 0; +} + +// Read a block of data, starting at register specified by "command" and ending at (command + length - 1) +int8_t i2c_read_block_data(uint8_t address, uint8_t command, uint8_t length, uint8_t *values) +{ + //uint8_t i = (length-1); +// int8_t ret = 0; +// +// if (i2c_start()!=0) //I2C START +// return(1); //Stop and return 0 if START fail +// ret |= i2c_write((address<<1)|I2C_WRITE_BIT); //Write 7-bit address with W bit +// if (ret!=0) //If NACK return 1 +// { +// i2c_stop(); //I2C STOP +// return(1); +// } +// ret|= i2c_write(command); //Write 8 bit command word +// if (ret!=0) //If NACK return 1 +// { +// i2c_stop(); //I2C STOP +// return(1); +// } +// if (i2c_start()!=0) //I2C repeated START +// { +// i2c_stop(); //Attempt to issue I2C STOP +// return(1); //Stop and return 0 if START fail +// } +// ret |= i2c_write((address<<1)|I2C_READ_BIT); //Write 7-bit address with R bit +// +// if (ret!=0) //If NACK return 1 +// { +// i2c_stop(); //I2C STOP +// return(1); +// } +// while (i>0) //Begin read loop +// { +// values[i] = i2c_read(WITH_ACK); //Read from bus with ACK +// i--; +// } +// +// values[0] = i2c_read(WITH_NACK); //Read from bus with NACK for the last one; +// +// i2c_stop(); //I2C STOP +// +// +// return(0); // Success! + return 0; +} + + +// Read a block of data, no command byte, reads length number of bytes and stores it in values. +int8_t i2c_read_block_data(uint8_t address, uint8_t length, uint8_t *values) +{ + //uint8_t i = (length-1); +// int8_t ret = 0; +// +// if (i2c_start()!=0) //I2C START +// return(1); //Stop and return 0 if START fail +// ret |= i2c_write((address<<1)|I2C_READ_BIT); //Write 7-bit address with R bit +// +// if (ret!=0) //If NACK return 1 +// { +// i2c_stop(); //I2C STOP +// return(1); +// } +// while (i>0) //Begin read loop +// { +// values[i] = i2c_read(WITH_ACK); //Read from bus with ACK +// i--; +// } +// +// values[0] = i2c_read(WITH_NACK); //Read from bus with NACK for the last one; +// +// i2c_stop(); //I2C STOP +// +// +// return(0); // Success! + return 0; +} + + +// Write a block of data, starting at register specified by "command" and ending at (command + length - 1) +int8_t i2c_write_block_data(uint8_t address, uint8_t command, uint8_t length, uint8_t *values) +{ + // int8_t i = length-1; +// int8_t ret = 0; +// +// if (i2c_start()!=0) //I2C START +// return(1); //Stop and return 0 if START fail +// ret |= i2c_write((address<<1)|I2C_WRITE_BIT); // Write 7 bit address with W bit +// ret|= i2c_write(command); // Set register to be read to command +// +// while (i>=0) +// { +// ret|= i2c_write(values[i]); //Write Value +// i--; +// } +// i2c_stop(); // I2C STOP +// +// if (ret!=0) +// return(1); +// else +// return(0); // Success! + return 0; +} + +// Write two command bytes, then receive a block of data +int8_t i2c_two_byte_command_read_block(uint8_t address, uint16_t command, uint8_t length, uint8_t *values) +{ +// +// int8_t ret = 0; +// +// union +// { +// uint8_t b[2]; +// uint16_t w; +// } comm; +// comm.w = command; +// +// uint8_t i = (length-1); +// +// +// if (i2c_start()!=0) //I2C START +// return(1); //Stop and return 0 if START fail +// ret |= i2c_write((address<<1)|I2C_WRITE_BIT); //Write 7-bit address with W bit +// ret |= i2c_write(comm.b[1]); //Write MSB command word +// ret |= i2c_write(comm.b[0]); // Write LSB of command +// if (i2c_start()!=0) //I2C repeated START +// { +// i2c_stop(); //Attempt to issue I2C STOP +// return(1); //Stop and return 0 if START fail +// } +// ret |= i2c_write((address<<1)|I2C_READ_BIT); //Write 7-bit address with R bit +// if (ret!=0) //If NACK return 1 +// { +// i2c_stop(); +// return(1); +// } +// while (i> 0) //Begin read loop +// { +// values[i] = i2c_read(WITH_ACK); //Read from bus with ACK +// i--; +// } +// +// values[0] = i2c_read(WITH_NACK); //Read from bus with NACK for the last one; +// i2c_stop(); //I2C STOP +// +// +// return(0); // Success! + return 0; +} + +// Initializes Linduino I2C port. +// Before communicating to the I2C port throught the QuikEval connector, you must also run +// quikeval_I2C_connect to connect the I2C port to the QuikEval connector throught the +// QuikEval MUX (and disconnect SPI). +void quikeval_I2C_init(void) +{ +// i2c_enable(); //! 1) Enable the I2C port; +} + +// Switch MUX to connect I2C pins to QuikEval connector. +// This will disconnect SPI pins. +void quikeval_I2C_connect(void) +{ + //// Enable I2C +// pinMode(QUIKEVAL_MUX_MODE_PIN, OUTPUT); //! 1) Set Mux pin as an output +// if (digitalRead(QUIKEVAL_MUX_MODE_PIN) == LOW) //! 2) If pin is already high, do nothing +// { +// digitalWrite(QUIKEVAL_MUX_MODE_PIN, HIGH); //! 3) Set the Mux pin to high +// delay(55); //! 4) And wait for LTC4315 to connect (required for rev B) +// } +} + +// Setup the hardware I2C interface. +// i2c_enable or quikeval_I2C_init must be called before using any of the other I2C routines. +void i2c_enable() +{ + // // set these for 100KHz to match the DC590 +// TWSR = (HARDWARE_I2C_PRESCALER_4 & 0x03); //! 1) set the prescaler bits +// TWBR = 18; //! 2) set the bit rate + +} + + +// Write start bit to the hardware I2C port +// return 0 if successful, 1 if not successful +int8_t i2c_start() +{ + //uint8_t result; +// uint16_t timeout; +// TWCR=(1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //! 1) I2C start +// for (timeout = 0; timeout < HW_I2C_TIMEOUT; timeout++) //! 2) START the timeout loop +// { +// _delay_us(1); +// if (TWCR & (1 << TWINT)) break; //! 3) Check the TWINT bit in TWCR +// } +// result=(TWSR & 0xF8); //! 4) Mask the status +// if ((result == STATUS_START) || (result == STATUS_REPEATED_START)) +// return(0); //! 5) Return status +// else +// return(1); + return 0; +} + +// Write a repeat start bit to the hardware I2C port +// return 0 if successful, 1 if not successful +int8_t i2c_repeated_start() +{ + //uint8_t result; +// uint16_t timeout; +// TWCR=(1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //! 1) I2C repeated start +// for (timeout = 0; timeout < HW_I2C_TIMEOUT; timeout++) //! 2) START the timeout loop +// { +// _delay_us(1); +// if (TWCR & (1 << TWINT)) break; //! 3) Check the TWINT bit in TWCR +// } +// result=(TWSR & 0xF8); //! 4) Mask the status +// if (result == STATUS_REPEATED_START) +// return(0); //! 5) Return status +// else +// return(1); + return 0; +} + +// Write stop bit to the hardware I2C port +void i2c_stop() +{ + //TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWSTO); //! 1) I2C stop +// while (TWCR & (1<<TWSTO)); //! 2) Wait for stop to complete +} + +// Send a data byte to hardware I2C port +// return 0 if successful, 1 if not successful +int8_t i2c_write(uint8_t data) +{ + // uint8_t result; +// uint16_t timeout; +// TWDR = data; //! 1) Load data register +// TWCR =(1<<TWINT) | (1<<TWEN); //! 2) START transaction +// for (timeout = 0; timeout < HW_I2C_TIMEOUT; timeout++) //! 3) START the timeout loop +// { +// _delay_us(1); +// if (TWCR & (1 << TWINT)) break; //! 4) Check the TWINT bit in TWCR +// } +// result=(TWSR & 0xF8); //! 5) Update status +// // For a generic write, need to consider all three of these cases (processor specific, some may not be this detailed.) +// if ((result == STATUS_WRITE_ACK) || (result == STATUS_ADDRESS_WRITE_ACK) || (result == STATUS_ADDRESS_READ_ACK)) +// return(0); //! 6) Return status +// else +// return(1); + return 0; +} + +// Read a data byte from the hardware I2C port. +// Returns the data byte read. +uint8_t i2c_read(int8_t ack) +{ + //uint8_t result; +// uint8_t return_value = 1; +// uint16_t timeout; +// uint8_t data; +// if (ack == 0) +// { +// TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWEA); //! 1) START transaction with ack +// for (timeout = 0; timeout < HW_I2C_TIMEOUT; timeout++) //! 2) START timeout loop +// { +// _delay_us(1); +// if (TWCR & (1 << TWINT)) break; //! 3) Check the TWINT bit in TWCR +// } +// data = TWDR; //! 4) Get data +// result = TWSR & 0xF8; //! 5) Update status +// if (result == STATUS_READ_ACK) return_value = 0; +// } +// else +// { +// TWCR=(1<<TWINT) | (1<<TWEN); //! 6) START transaction with NACK +// for (timeout = 0; timeout < HW_I2C_TIMEOUT; timeout++) +// { +// _delay_us(1); +// if (TWCR & (1 << TWINT)) break; //! 7) Check the TWINT bit in TWCR +// } +// data = TWDR; //! 8) Get data +// result = TWSR & 0xF8; //! 9) Update status +// if (result == STATUS_READ_NACK) return_value = 0; +// } +// return(data); + return 0; +} + +// Poll the I2C port and look for an acknowledge +// Returns 0 if successful, 1 if not successful +int8_t i2c_poll(uint8_t i2c_address) + +{ + //int8_t ack=0; +// ack |= i2c_start(); //! 1) I2C start +// ack |= i2c_write((i2c_address<<1) | I2C_WRITE_BIT); //! 2) I2C address + !write +// i2c_stop(); //! 3) I2C stop +// return(ack); //! 4) Return ack status + return 0; +}