📄 i2c.c
字号:
/***********************************************************************/
/* FILE :I2C.c */
/* DATE :2004 04 07 */
/* DESCRIPTION :Program of snake */
/* Test TWI ATmega 128 */
/* Original File is Pascal Stang */
/* This file is generated by Sysonchip . */
/***********************************************************************/
/*HISTORY */
/*---------------------------------------------------------------------*/
/*YYYY-MM-DD version name description */
/*2003-06-25 0.0.9 Pascal Stang Creates the file */
/*2004-04-07 0.0.9 snake modyfy for ATmega 128 */
/***********************************************************************/
#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <util/twi.h>
#include <string.h>
#include "i2c.h"
#include "main.h"
extern unsigned char i2c_data,i2c_code,twi_had_isr;
u08 twst;
// I2C state and address variables
static eI2cStateType I2cState;
static unsigned char I2cDeviceAddrRW;
// send/transmit buffer (outgoing i2c_data)
static unsigned char I2cSendData[I2C_SEND_DATA_BUFFER_SIZE];
static unsigned char I2cSendDataIndex;
static unsigned char I2cSendDataLength;
// receive buffer (incoming i2c_data)
static unsigned char I2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE];
static unsigned char I2cReceiveDataIndex;
static unsigned char I2cReceiveDataLength;
// function pointer to i2c receive routine
//! I2cSlaveReceive is called when this processor
// is addressed as a slave for writing
static void (*i2cSlaveReceive)(unsigned char receiveDataLength, unsigned char* recieveData);
//! I2cSlaveTransmit is called when this processor
// is addressed as a slave for reading
static unsigned char (*i2cSlaveTransmit)(unsigned char transmitDataLengthMax, unsigned char* transmitData);
// functions
void i2cInit(void)
{
// set pull-up resistors on I2C bus pins
//sbi(PORTC, 0); // i2c SCL on ATmega163,323,16,32,etc
//sbi(PORTC, 1); // i2c SDA on ATmega163,323,16,32,etc
sbi(PORTD, 0); // i2c SCL on ATmega128,64
sbi(PORTD, 1); // i2c SDA on ATmega128,64
// clear SlaveReceive and SlaveTransmit handler to null
i2cSlaveReceive = 0;
i2cSlaveTransmit = 0;
// set i2c bit rate to 100KHz
i2cSetBitrate(100);
// enable TWI (two-wire interface)
sbi(TWCR, TWEN);
// set state
I2cState = I2C_IDLE;
// enable TWI interrupt and slave address ACK
sbi(TWCR, TWIE);
sbi(TWCR, TWEA);
// enable interrupts
sei();
}
void i2cSetBitrate(unsigned int bitrateKHz)
{
unsigned char bitrate_div;
// set i2c bitrate
// SCL freq = F_CPU/(16+2*TWBR))
// for processors with additional bitrate division (mega128)
// SCL freq = F_CPU/(16+2*TWBR*4^TWPS)
// set TWPS to zero
cbi(TWSR, TWPS0);
cbi(TWSR, TWPS1);
// calculate bitrate division
bitrate_div = ((F_CPU/1000l)/bitrateKHz);
if(bitrate_div >= 16)
bitrate_div = (bitrate_div-16)/2;
outb(TWBR, bitrate_div);
}
void i2cSetLocalDeviceAddr(unsigned char deviceAddr, unsigned char genCallEn)
{
// set local device address (used in slave mode only)
outb(TWAR, ((deviceAddr&0xFE) | (genCallEn?1:0)) );
}
void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(unsigned char receiveDataLength, unsigned char* ecieveData))
{
i2cSlaveReceive = i2cSlaveRx_func;
}
void i2cSetSlaveTransmitHandler(unsigned char (*i2cSlaveTx_func)(unsigned char transmitDataLengthMax, unsigned char* transmitData))
{
i2cSlaveTransmit = i2cSlaveTx_func;
}
inline void i2cSendStart(void)
{
// send start condition
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));
}
inline void i2cSendStop(void)
{
// transmit stop condition
// leave with TWEA on for slave receiving
outb(TWCR,(inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)|BV(TWSTO));
}
inline void i2cWaitForComplete(void)
{
// wait for i2c interface to complete operation
while( !(inb(TWCR) & BV(TWINT)) );
}
inline void i2cSendByte(unsigned char i2c_data)
{
// save i2c_data to the TWDR
outb(TWDR, i2c_data);
// begin send
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
}
inline void i2cReceiveByte(unsigned char ackFlag)
{
// begin receive over i2c
if( ackFlag )
{
// ackFlag = TRUE: ACK the recevied i2c_data
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
}
else
{
// ackFlag = FALSE: NACK the recevied i2c_data
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
}
}
inline unsigned char i2cGetReceivedByte(void)
{
// retieve received i2c_data byte from i2c TWDR
return( inb(TWDR) );
}
inline unsigned char i2cGetStatus(void)
{
// retieve current i2c status from i2c TWSR
return( inb(TWSR) );
}
void i2cMasterSend(unsigned char deviceAddr, unsigned char length, unsigned char* i2c_data)
{
unsigned char i;
// wait for interface to be ready
while(I2cState);
// set state
I2cState = I2C_MASTER_TX;
// save i2c_data
I2cDeviceAddrRW = (deviceAddr & 0xFE); // RW cleared: write operation
for(i=0; i<length; i++)
I2cSendData[i] = *i2c_data++;
I2cSendDataIndex = 0;
I2cSendDataLength = length;
// send start condition
i2cSendStart();
}
void i2cMasterReceive(unsigned char deviceAddr, unsigned char length, unsigned char* i2c_data)
{
unsigned char i;
// wait for interface to be ready
while(I2cState);
// set state
I2cState = I2C_MASTER_RX;
// save i2c_data
I2cDeviceAddrRW = (deviceAddr|0x01); // RW set: read operation
I2cReceiveDataIndex = 0;
I2cReceiveDataLength = length;
// send start condition
i2cSendStart();
// wait for i2c_data
while(I2cState);
// return i2c_data
for(i=0; i<length; i++)
*i2c_data++ = I2cReceiveData[i];
}
void i2cMasterSendNI(unsigned char deviceAddr, unsigned char length, unsigned char* i2c_data)
{
// disable TWI interrupt
cbi(TWCR, TWIE);
// send start condition
i2cSendStart();
i2cWaitForComplete();
// send device address with write
i2cSendByte( deviceAddr & 0xFE );
i2cWaitForComplete();
// send i2c_data
while(length)
{
i2cSendByte( *i2c_data++ );
i2cWaitForComplete();
length--;
}
// transmit stop condition
// leave with TWEA on for slave receiving
i2cSendStop();
while( !(inb(TWCR) & BV(TWSTO)) );
// enable TWI interrupt
sbi(TWCR, TWIE);
}
void i2cMasterReceiveNI(unsigned char deviceAddr, unsigned char length, unsigned char *i2c_data)
{
// disable TWI interrupt
cbi(TWCR, TWIE);
// send start condition
i2cSendStart();
i2cWaitForComplete();
// send device address with read
i2cSendByte( deviceAddr | 0x01 );
i2cWaitForComplete();
// accept receive i2c_data and ack it
while(length > 1)
{
i2cReceiveByte(TRUE);
i2cWaitForComplete();
*i2c_data++ = i2cGetReceivedByte();
// decrement length
length--;
}
// accept receive i2c_data and nack it (last-byte signal)
i2cReceiveByte(TRUE);
i2cWaitForComplete();
*i2c_data++ = i2cGetReceivedByte();
// transmit stop condition
// leave with TWEA on for slave receiving
i2cSendStop();
// enable TWI interrupt
sbi(TWCR, TWIE);
}
void i2cMasterTransferNI(unsigned char deviceAddr, unsigned char sendlength, unsigned char* senddata, unsigned char receivelength, unsigned char* receivedata)
{
// disable TWI interrupt
cbi(TWCR, TWIE);
// send start condition
i2cSendStart();
i2cWaitForComplete();
// if there's i2c_data to be sent, do it
if(sendlength)
{
// send device address with write
i2cSendByte( deviceAddr & 0xFE );
i2cWaitForComplete();
// send i2c_data
while(sendlength)
{
i2cSendByte( *senddata++ );
i2cWaitForComplete();
sendlength--;
}
}
// if there's i2c_data to be received, do it
if(receivelength)
{
// send repeated start condition
i2cSendStart();
i2cWaitForComplete();
// send device address with read
i2cSendByte( deviceAddr | 0x01 );
i2cWaitForComplete();
// accept receive i2c_data and ack it
while(receivelength > 1)
{
i2cReceiveByte(TRUE);
i2cWaitForComplete();
*receivedata++ = i2cGetReceivedByte();
// decrement length
receivelength--;
}
// accept receive i2c_data and nack it (last-byte signal)
i2cReceiveByte(TRUE);
i2cWaitForComplete();
*receivedata++ = i2cGetReceivedByte();
}
// transmit stop condition
// leave with TWEA on for slave receiving
i2cSendStop();
while( !(inb(TWCR) & BV(TWSTO)) );
// enable TWI interrupt
sbi(TWCR, TWIE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -