⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 atmel avr hardwire i2c source
💻 C
📖 第 1 页 / 共 2 页
字号:
/***********************************************************************/
/*  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 + -