?? iic.c
字號:
/******************************************************************************
*
* Purpose: IIC.c
*
* Creator: Rob Lansbergen
*
* Version: $Revision: 7 $
*
* File Name: $Workfile: iic.c $
*
* Author: Rob Lansbergen
*
* Check in: $Author: Chong.cheeleong $
*
* The information is provided 揳s is?without any express or implied warranty
* of any kind, * including warranties of merchantability, noninfringement of
* intellectual property, or fitness for any particular purpose. In no event sha
* Wireless Sound Solutions and/or its affiliate companies, or its suppliers be
* liable for any damages whatsoever arising out of the use of or inability to
* use the information or the materials. Wireless Sound Solutions, its affiliate
* companies, and its suppliers further do not warrant the accuracy or
* completeness of information, text, graphics, or other items contained within
* materials. Wireless Sound Solutions, Inc., may make changes to materials, or
* the products described within, at any time, without notice.
* ?007 Wireless Sound Solutions. All rights reserved. Wireless Sound Solutions
* STS and STS-wireless are trademarks of Wireless Sound Solutions.
******************************************************************************/
#include "pgmspace.h"
#include "defines.h"
#ifndef USE_ATMEL_I2C
unsigned char i2cSlaveAddress = 0x80;
/*
I2C wiring
SCL on SCL_PIN : uC output
SDA on SDA_PIN : uc input
*/
/** on AT128 use extra delay **/
#ifndef MCU_ATMEGA128
#define FAST_I2C /* slow version cost 100 Byte */
#endif /* END MCU_ATMEGA128 */
#ifdef FAST_I2C /* No delay */
#define i2c_half_delay()
#define i2c_delay()
#else
#define i2c_half_delay()
#define i2c_delay() {\
int i=0;\
while (i !=10) i++;\
} ;
/*
#define i2c_half_delay(){
int i=0;\
while (i !=10) i++;\
}
#define i2c_delay() {\
int i=0;\
while (i !=20) i++;\
} ;
*/
#endif /* END FAST_I2C */
// SET SCL to input instead of Output High
//#define SCL_H() {I2C_PORT = I2C_PORT |SCL_PIN;} /* SCL high */
//#define SCL_L() {I2C_PORT = I2C_PORT & ~SCL_PIN;} /* Pull SCL down */
#define SCL_H() {I2C_DDR = I2C_DDR & ~SCL_PIN; I2C_PORT = I2C_PORT & ~SCL_PIN;} /* SCL high using external pull-up (SDA is input)*/
#define SCL_L() {I2C_DDR = I2C_DDR | SCL_PIN; I2C_PORT = I2C_PORT & ~SCL_PIN;} /* Pull SCL down */
#define SDA_H() {I2C_DDR = I2C_DDR & ~SDA_PIN; I2C_PORT = I2C_PORT & ~SDA_PIN;} /* SDA high using external pull-up (SDA is input)*/
#define SDA_L() {I2C_DDR = I2C_DDR | SDA_PIN; I2C_PORT = I2C_PORT & ~SDA_PIN;} /* Pull SDA down */
unsigned char SDA_IN(void)
{
if ((I2C_PIN & SDA_PIN) == 0x00) return(0);
else return(1);
}
void SDA_OUT(unsigned char b)
{
if (b == 0) {SDA_L();}
else {SDA_H();}
}
unsigned char i2c_error = 0; /* Last error */
/*
* Makes sure that the bus is in a known condition. Returns 1 on success,
* 0 if some other device is pulling on the bus.
*/
void i2c_init(void)
{
SCL_H();
SDA_H();
i2c_error = 0;
return;
}
/*
* Generates a start condition on the bus. Returns 0 on success, 1 if some
* other device is holding the bus.
*/
unsigned char i2c_start(void)
{
SCL_H(); /* EHO: 15-07-2003 in case of repeated start, first scl high */
i2c_half_delay();
SDA_L(); /* Pull SDA down... */
i2c_half_delay();
SCL_L(); /* ...and then SCL -> start condition. */
i2c_half_delay();
return 0;
}
/*
* Generates a stop condition on the bus. Returns 0 on success, 1 if some
* other device is holding the bus.
*/
unsigned char i2c_stop(void)
{
SDA_L(); /* Pull SDA down if it was not down */
i2c_half_delay();
SCL_H(); /* Let SCL go up */
i2c_half_delay();
SDA_H(); /* ...and then SDA up -> stop condition. */
i2c_half_delay();
return (0);
}
/*
* Clock out one bit.
* Returns 0 on success, 1 if we lose arbitration.
*/
unsigned char i2c_bit_out(unsigned char bout)
{
int i = 0;
SDA_OUT(bout); /* Put data out on SDA */
i2c_half_delay();
SCL_H(); /* Let SCL go up */
i2c_delay();
while (i != 1) i++; /* SCL must be at least 500 ns High */
SCL_L(); /* Pull SCL back down */
i2c_delay();
return 0; /* OK */
}
/*
* Clock in one bit.
*/
unsigned char i2c_bit_in(void)
{
unsigned char bin;
int i = 0;
SDA_H();
i2c_half_delay();
SCL_H(); /* Let SCL go up */
i2c_delay();
bin = SDA_IN(); /* Read in data */
while (i != 1) i++; /* SCL must be at least 500 ns High */
i2c_delay();
SCL_L(); /* Pull SCL back up */
i2c_delay();
return bin; /* Return the sampled bit */
}
/*
* Send one byte on the bus. No start or stop conditions are generated here,
* but i2c_error will be set according to the result.
* Returns 0 on success, 1 if we lose arbitration or if the slave doesn't
* acknowledge the byte. Check i2c_error for the actual result on error.
*/
unsigned char i2c_byte_out(unsigned char dat)
{
unsigned char bit_count;
bit_count = 8;
while(bit_count)
{
if (dat & 0x80)
{
if (i2c_bit_out(1)) return 1;
}
else
{
if (i2c_bit_out(0)) return 1;
}
dat <<= 1;
bit_count--;
}
if (i2c_bit_in())
{
i2c_error = I2CERR_NAK;
return 1;
}
return 0;
}
/*
* Reads one byte in from the slave. Ack must be 1 if this is the last byte
* to be read during this transfer, 0 otherwise (as per I2C bus specification,
* the receiving master must acknowledge all but the last byte during a
* transfer).
*/
unsigned char i2c_byte_in(unsigned char ack)
{
unsigned char bit_count, byte_in;
bit_count = 8;
byte_in = 0;
while(bit_count)
{
byte_in <<= 1;
if (i2c_bit_in()) byte_in |= 0x01;
bit_count--;
}
i2c_bit_out(ack);
SDA_H();
return byte_in;
}
unsigned char I2C_Write_Byte(unsigned char map, unsigned char data)
{
return (I2C_Write_Buf(map, &data, 1, 0));
}
/* Value is returned And will not damage the Receive buffer */
/* This is to prevent a byte read can dammage the buffer that was read in I2C_read_buf*/
unsigned char I2C_Read_Byte(unsigned char map)
{
unsigned char tmp;
unsigned char result;
/* we do not want to overwrite RX_Data_recv_array[0] */
tmp = RX_Data_recv_array[0];
I2C_Read_Buf(map, 1);
result = RX_Data_recv_array[0];
/* set back the old data */
RX_Data_recv_array[0] = tmp;
return (result);
}
/* read data is availeble in RX_Data_recv_array */
unsigned char I2C_Read_Buf (unsigned char map, unsigned char rx_count)
{
if ( I2C_Write_Buf (map, &map, 0, 0))/* second map addres is dummy pointer no data writtten only i2cSlave address and map address*/
{
/* If send fails, abort but don't send a stop condition if we lost
arbitration */
if (i2c_error != I2CERR_LOST) i2c_stop();
return 1;
}
SDA_H(); /* One of these may be low now, in which case the next */
SCL_H(); /* start condition wouldn't be detected so make */
i2c_delay(); /* sure that they're up and wait for one delay slot */
if (i2c_recv(rx_count)) return 1;
return (i2c_error ? 1 : 0);
}
/*
* Read in 'count' bytes from slave 'addr'.
* Returns 0 on success.
*/
unsigned char i2c_recv(unsigned char count)
{
unsigned char byteptr, byte_in;
if (i2c_start()) return 1;
i2c_error = 0;
byteptr = 0;
byte_in = i2cSlaveAddress | 0x01;
if (i2c_byte_out(byte_in))
{
if (i2c_error == I2CERR_NAK) i2c_stop();
return i2c_error;
}
while(count)
{
if (--count)
{
byte_in = i2c_byte_in(0);
}
else
{
byte_in = i2c_byte_in(1); /* No ACK during last byte */
}
RX_Data_recv_array[byteptr] = byte_in;
byteptr++;
}
i2c_stop();
return (i2c_error ? 1 : 0);
}
unsigned char I2C_Write_Buf (unsigned char addr, unsigned char *buf, unsigned char count, unsigned char flash_type)
{
unsigned char byte_out;
const unsigned char __flash *fl_buf;
if (flash_type) fl_buf = (const unsigned char __flash *)buf;
if (i2c_start()) return 1;
i2c_error = 0;
byte_out = i2cSlaveAddress & 0xFE; /* Ensure that it's a write address */
if (i2c_byte_out(byte_out))
{
if (i2c_error == I2CERR_NAK )
{
i2c_stop();
putstring("NA ");
putdec(addr);
putchar('=');
if (flash_type) puthex(*fl_buf);
else puthex(*buf);
putchar('\r');
}
return i2c_error;
}
byte_out = addr;
count = count+1; /* Include map addres to byte count */
while(count)
{
if (Use_I2C_Log_Write == 1)
{
if (count != 1)
{
puthex(i2cSlaveAddress);
putchar('-');
putdec(addr++);
putchar('=');
if (flash_type) puthex(*fl_buf);
else puthex(*buf);
putstring(" (");
if (flash_type) putdec(*fl_buf);
else putdec(*buf);
putstring(")\r");
}
}
if (i2c_byte_out(byte_out))
{
if (i2c_error == I2CERR_NAK)
{
i2c_stop();
}
return i2c_error;
}
if (flash_type) byte_out = *fl_buf++;
else byte_out = *buf++;
count--;
}
i2c_stop();
return 0;
}
#endif /* USE_ATMEL_I2C */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -