Rev 139 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/** i2cbb.c** Bit Banging I2C code for any Atmel device* The I2CBB_DELAY delay (in header) may need to be tweaked* for different clock speeds, 10 if a fast enough* speed, 100 if your having problems and dont need* the speed. 7 seems to work well with an Attiny85* running the PLL 16.5Mhz clock.** Base code from Raul* http://codinglab.blogspot.com.au/2008/10/i2c-on-avr-using-bit-banging.html*/#include <avr/io.h>#include <util/delay.h>#include "config.h"#include "avrutil.h"#include "i2cbb.h"#define I2CBB_DATA_HI()\I2CBB_DDR &= ~ (1 << I2CBB_DAT);\I2CBB_PORT |= (1 << I2CBB_DAT);#define I2CBB_DATA_LO()\I2CBB_DDR |= (1 << I2CBB_DAT);\I2CBB_PORT &= ~ (1 << I2CBB_DAT);#define I2CBB_CLOCK_HI()\I2CBB_DDR &= ~ (1 << I2CBB_CLK);\I2CBB_PORT |= (1 << I2CBB_CLK);#define I2CBB_CLOCK_LO()\I2CBB_DDR |= (1 << I2CBB_CLK);\I2CBB_PORT &= ~ (1 << I2CBB_CLK);void i2cbb_WriteBit(unsigned char c) {if (c > 0) {I2CBB_DATA_HI();}else {I2CBB_DATA_LO();}I2CBB_CLOCK_HI();while ((I2CBB_PIN & (1 << I2CBB_CLK)) == 0);_delay_us(I2CBB_DELAY);I2CBB_CLOCK_LO();//_delay_us(I2CBB_DELAY);if (c > 0) {_delay_us(I2CBB_DELAY); // AddedI2CBB_DATA_LO();}// _delay_us(I2CBB_DELAY);}unsigned char i2cbb_ReadBit() {I2CBB_DATA_HI();_delay_us(I2CBB_DELAY);I2CBB_CLOCK_HI();while ((I2CBB_PIN & (1 << I2CBB_CLK)) == 0);_delay_us(I2CBB_DELAY);unsigned char c = I2CBB_PIN;I2CBB_CLOCK_LO();//_delay_us(I2CBB_DELAY);return (c >> I2CBB_DAT) & 1;}// Inits bitbanging port, must be called before using the functions below//void i2cbb_Init() {I2CBB_PORT &= ~ ((1 << I2CBB_DAT) | (1 << I2CBB_CLK));I2CBB_CLOCK_HI();I2CBB_DATA_HI();_delay_us(I2CBB_DELAY);}// Send a START Condition//void i2cbb_Start() {// set both to high at the same timeI2CBB_DDR &= ~ ((1 << I2CBB_DAT) | (1 << I2CBB_CLK));_delay_us(I2CBB_DELAY);I2CBB_DATA_LO();_delay_us(I2CBB_DELAY);I2CBB_CLOCK_LO();_delay_us(I2CBB_DELAY);}// Send a STOP Condition//void i2cbb_Stop() {I2CBB_DATA_LO();I2CBB_CLOCK_LO();_delay_us(I2CBB_DELAY);_delay_us(I2CBB_DELAY);I2CBB_CLOCK_HI();_delay_us(I2CBB_DELAY);_delay_us(I2CBB_DELAY);I2CBB_DATA_HI();//_delay_us(I2CBB_DELAY);}// write a byte to the I2C slave deviceunsigned char i2cbb_Write(unsigned char c) {uint8_t i;for (i=0; i < 8; i++) {i2cbb_WriteBit(c & 128);c <<= 1;}return i2cbb_ReadBit();//return 0;}// read a byte from the I2C slave device//unsigned char i2cbb_Read(unsigned char ack) {unsigned char res = 0;uint8_t i;for (i = 0; i < 8; i++) {res <<= 1;res |= i2cbb_ReadBit();}if (ack > 0) {i2cbb_WriteBit(0);}else {i2cbb_WriteBit(1);}//_delay_us(I2CBB_DELAY);return res;}