Показать сообщение отдельно
Старый 18.01.2015, 12:50   #5
Bill
Senior Member
 
Аватар для Bill
 
Регистрация: 26.02.2007
Адрес: Челябинск
Возраст: 69
Сообщений: 2,215
Вес репутации: 1898/87
Bill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant future
По умолчанию Было такое дело дело когда-то.

Код:
/*
        I2C service routines

        File:        I2CMaster.c

        27-Jan-01 BK        Initial edit
        08-Aug-01 BK        Last  update
*/

#include "vguard.h"     // Project header file
#include "I2Cmaster.h"

/*        Function ptototypes        */

static void     _delay(void),
                _delay2(void);
static void     I2CStart(void);
static void     _txByte(char);
static void     I2C_WrAddr(void);
static void     I2CStop(void);

/*        Global variables definition        */

volatile char           I2C_Flags;      // I2C flags
volatile char           I2C_Slave;      // I2C slave device address
volatile unsigned       I2C_Addr;       // I2C device data address
volatile char           I2C_Buffer[8];  // Buffer

//
//  ** I2CInit        -- the routine to initiate I2C ports
//
void I2CInit(void)
        {
        I2C_Flags       = 0;            // Reset flags
        I2C_Output      |= (SDA_BIT | SCL_BIT);
        I2C_DDR         |= (SDA_BIT | SCL_BIT);
        }
//
// ** I2C_Rd1Byte        -- Read 1st byte from I2C
//
char I2C_Rd1Byte(void)
        {
        I2C_WrAddr();                   // Write the required address info
        I2CStart();                     //
        _txByte(I2C_Slave | 0x01);      // Specify READ mode for the slave device
        return I2C_RdByte(1);           // Read data
        }
//
// ** I2C_RdByte   -- the routine receives 8 data bits
//
char I2C_RdByte(char _flag)
        {
        char    _count = 8, _byte = 0;

        I2C_DDR &= ~SDA_BIT;    // Make SDA line as input
        I2C_Output |= SDA_BIT;  // Enable pull-up resistor
        do      {               // Reception
                _byte <<= 1;
                I2C_Output |= SCL_BIT;  // Set clock to high
                _delay();              //
                if (I2C_Input & SDA_BIT)//
                        _byte |= 0x01;
                I2C_Output &= ~SCL_BIT; // Return clock to low
                _delay();              //
                }
        while (--_count);
        I2C_DDR |= SDA_BIT;     // Make SDA line as output
        _delay();               //
        if (!_flag)              // For the last received byte send NACK signal
                I2C_Output |= SDA_BIT;
        else                    // otherwise send ACK signal
                I2C_Output &= ~SDA_BIT;
        I2C_Output |= SCL_BIT;  // Set clock to high
        _delay();
        I2C_Output &= ~SCL_BIT; // Return clock to low
        _delay();
        return _byte;
        }
//
// ** I2C_RdLastByte   -- the routine reads the last byte from I2C
//
char I2C_RdLastByte(void)
        {
        char _byte;

        _byte = I2C_RdByte(0);     // Read the data
        I2CStop();                      // Generate STOP condition
        return _byte;                   // and return
        }
//
// ** I2C_Wr1Byte        -- Write 1st byte to I2C
//
void I2C_Wr1Byte(char _byte)
        {
        I2C_WrAddr();           // Write the required address info
        _txByte(_byte);         // Write the data
        }
//
// ** I2C_Wr1LastByte        -- Write only 1 byte to I2C
//
void I2C_Wr1LastByte(char _byte)
        {
        I2C_Wr1Byte(_byte);     // Write the byte
        I2CStop();              // Generate STOP condition
        }
//
// ** I2C_WrLastByte        -- Write last byte to I2C
//
void I2C_WrLastByte(char _byte)
        {
        _txByte(_byte);         // Write the data
        I2CStop();              // Generate STOP condition
        }
//
// ** I2C_WrAddr        -- Write the Slave and Slave data addresses to I2C
//
static void I2C_WrAddr(void)
        {
        I2CStart();                     // Generate START bit
        _txByte(I2C_Slave);             // Send the slave device address
        if (I2C_Flags & FLASH_BIT )     // Flash memory access
                _txByte(I2C_Addr>>8);   // then send the flash data address high
        _txByte(I2C_Addr);              // then low
        }
//
// ** _txByte   -- the routine transmits 8 data bits
//
static void _txByte(char _byte)
        {
        char    _count;

        I2C_Output &= ~SCL_BIT; // Set clock to low
        _count = 8;
        I2C_DDR |= SDA_BIT;     // Make SDA line as output
        do      {               // Transmission
                _delay();
                if (_byte & (1<<7))
                        I2C_Output      |= SDA_BIT;
                else
                        I2C_Output      &= ~SDA_BIT;
                _byte <<= 1; _NOP(); _NOP();
                I2C_Output |= SCL_BIT;  // Set clock to high
                _delay();               //
                I2C_Output &= ~SCL_BIT; // Return clock to low
                }
        while (--_count);
        _delay();              //
        I2C_DDR &= ~SDA_BIT;    // Make SDA line as input
        _byte   = 0;
        I2C_Output |= SCL_BIT;  // Set clock to high
        _delay();              //
        if (I2C_Input & SDA_BIT)// For ACK high
                _byte = 0xFF;
        I2C_Output &= ~SCL_BIT; // Return clock to low
//        return _byte;
        }
//
// ** I2CStart        -- the function asserts start condition
//
static void I2CStart(void)
        {
        I2C_Output      |= SDA_BIT;                // Make sure SDA is high
        I2C_DDR         |= SDA_BIT;                // Return SDA line to output state
        I2C_Output      &= ~SCL_BIT;                // Set SCL low
        _delay();                                //
        I2C_Output      |= SCL_BIT;                // Set SCL high
        _delay();                                //
        I2C_Output      &= ~SDA_BIT;                // SDA goes low during SCL high
        _delay();                                //
        I2C_Output      &= ~SCL_BIT;                // Set SCL low
        }
//
// ** I2CStop        -- the function asserts stop condition
//
static void I2CStop(void)
        {
        I2C_DDR         |= SDA_BIT;                // Return SDA line to output state
        I2C_Output      &= ~SCL_BIT;                // Force SCL
        I2C_Output      &= ~SDA_BIT;                // and SDA low
        _delay();                                // Half period delay
        I2C_Output      |= SCL_BIT;                // Set SCL high
        _delay();                                // Quarter period delay
        I2C_Output      |= SDA_BIT;                // Set SDA high
        _delay();                                // Half period delay
        }
//
// ** _delay2       -- I2C clock half period delay
//
static void _delay2(void)
        {
        _delay();
        _delay();
        }
//
// ** _delay        -- I2C clock quarter period delay
//
static void _delay(void)
        {
        char    _count = 9;
        while (--_count);
        }
//
// ** I2C_RdBlock       -- the routine reads a data block (8 bytes)
//                      from a I2C slave device to I2C buffer
//
void I2C_RdBlock(void)
        {
        char    *_cp = I2C_Buffer,      // a pointer to buffer
                _cnt = 6;               // and byte counter

        *_cp++  = I2C_Rd1Byte();        // Read the 1st byte
        do      {
                *_cp++ = I2C_RdByte(1); // Read all others excluding the last byte
                }
        while (--_cnt);
        *_cp    = I2C_RdLastByte();     // Read the last byte
        }

//
// ** I2C_WrBlock       -- the routine writes a data block (8 bytes)
//                      to a I2C slave device to I2C buffer
//
void I2C_WrBlock(void)
        {
        char    *_cp = I2C_Buffer,      // a pointer to buffer
                _cnt = 6;               // and byte counter

        I2C_Wr1Byte(*_cp++);            // Write the 1st byte
        do      {
                _txByte(*_cp++);         // Write all others excluding the last byte
                }
        while (--_cnt);
        I2C_WrLastByte(*_cp);           // Write the last byte
        }
Bill вне форума   Ответить с цитированием