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

📄 lib_i2c.c

📁 ARM入门的好帮手.包含了从简单到相对较复杂的程序.
💻 C
📖 第 1 页 / 共 2 页
字号:
//*-----------------------------------------------------------------------------
//*      ATMEL Microcontroller Software Support  -  ROUSSET  -
//*-----------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*-----------------------------------------------------------------------------
//* File Name           : lib_i2c.c
//* Object              : I2C driver functions
//*
//* 1.0 29/05/00  EL    : Creation
//* 2.0 06/09/00  EL    : Clean up
//* 2.1 21/11/00  JPP   : Change Timer interrupt in LEVEL
//* 2.2 14/01/02  JPP   : Send NACK at for read, and add wait function
//*-----------------------------------------------------------------------------

//* --------------------------- include file ----------------------------------

#include    "lib_i2c.h"
#include    "periph/power_saving/lib_power_save.h"
#include    "periph/timer_counter/lib_tc.h"


//*-----------------------------------------------------------------------------
//*                    Internal function prototype
//*-----------------------------------------------------------------------------

void  at91_I2CError(I2Cdesc *I2C_pt);
void  at91_I2CSendStartSDA (I2Cdesc *I2C_pt);
void  at91_I2CTxSendByte (I2Cdesc *I2C_pt);
void  at91_I2CTxSendDeviceAddress (I2Cdesc *I2C_pt);
void  at91_I2CTxSendBit (I2Cdesc *I2C_pt);
void  at91_I2CRxReceiveByte (I2Cdesc *I2C_pt);
void  at91_I2CRxReceiveBit (I2Cdesc *I2C_pt);

void  at91_I2CSendStartSDA (I2Cdesc *I2C_pt);
void  at91_I2CSendStartSCL (I2Cdesc *I2C_pt);
void  at91_I2CPrepareSTOP (I2Cdesc *I2C_pt);

void  at91_I2CPrepareACK (I2Cdesc *I2C_pt);
void  at91_I2CTxWaitACK (I2Cdesc *I2C_pt);
void  at91_I2CRxDoACK (I2Cdesc *I2C_pt);

void  at91_I2CTxSetSCL (I2Cdesc *I2C_pt);
void  at91_I2CTxClearSCL (I2Cdesc *I2C_pt);
void  at91_I2CRxSetSCL (I2Cdesc *I2C_pt);
void  at91_I2CRxClearSCL (I2Cdesc *I2C_pt);

//*-----------------------------------------------------------------------------
//*                    Internal function definition
//*-----------------------------------------------------------------------------

//*-----------------------------------------------------------------------------
//* Function Name       : at91_I2C (I2Cdesc *I2C_pt, u_short loadAddress, u_char nbByte)
//* Object              : I2C
//* Input Parameters    : <I2C_pt> = I2C Peripheral Descriptor pointer
//*         : loadAddress
//*         : nbByte
//* Output Parameters   : none
//*-----------------------------------------------------------------------------
void at91_I2CDeviceRead (I2Cdesc *I2C_pt)
{ //* Begin
    I2C_pt->pioa_base->PIO_OER = I2C_pt->SDA_line;          //* set SDA line as an output
    I2C_pt->pioa_base->PIO_SODR = I2C_pt->SDA_line;         //* set SDA line
    I2C_pt->pioa_base->PIO_SODR = I2C_pt->SCL_line;         //* set SCL line

    //* get byte to transmit
    I2C_pt->I2CByte = I2C_pt->deviceAddress | READ_BIT ;
    I2C_pt->mode = DATA_READ;                               //* next mode
    I2C_pt->countBit = 8;                                   //* initialize countBit

    //* initialize nb_ACK
    I2C_pt->nb_ACK = 10;

    //* change interrupt handler to at91_I2CSendStartSDA
    I2C_pt->I2CTCHandler = at91_I2CSendStartSDA;

} //* End

//*-----------------------------------------------------------------------------
//* Function Name       : at91_I2CTxSendByte (I2Cdesc *I2C_pt)
//* Object              : I2C
//* Input Parameters    : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters   : none
//*-----------------------------------------------------------------------------
void at91_I2CTxSendByte (I2Cdesc *I2C_pt)
{ //* Begin
    I2C_pt->pioa_base->PIO_OER = I2C_pt->SDA_line;      //* set SDA line as an output
    I2C_pt->pioa_base->PIO_SODR = I2C_pt->SDA_line;     //* set SDA line

    //* get byte to transmit
    switch(I2C_pt->mode)
    {
    case DATA :
            I2C_pt->I2CByte = *(I2C_pt->TxEnd++);

            I2C_pt->nbI2CByte--;
            if(I2C_pt->nbI2CByte == 0)
            //* next mode
                I2C_pt->mode = STOP;
        break;

    case HIGH_ADDRESS_WRITE :
            I2C_pt->I2CByte = (u_char) (I2C_pt->loadAddress >> 8);

            //* next mode
            I2C_pt->mode = LOW_ADDRESS_WRITE;
        break;

    case LOW_ADDRESS_WRITE :
            I2C_pt->I2CByte = (u_char) I2C_pt->loadAddress;

            //* next mode
            I2C_pt->mode = DATA;
        break;

    case HIGH_ADDRESS_READ :
            I2C_pt->I2CByte = (u_char) (I2C_pt->loadAddress >> 8);

            //* next mode
            I2C_pt->mode = LOW_ADDRESS_READ;
        break;

    case LOW_ADDRESS_READ :
            I2C_pt->I2CByte = (u_char) I2C_pt->loadAddress;

            //* next mode
            I2C_pt->mode = DEVICE_READ;
        break;
    }

    I2C_pt->countBit = 8;                   //* initialize countBit
    I2C_pt->nb_ACK = 10;                     //* initialize nb_ACK

    //* change interrupt handler to at91_I2CTxSendBit
    I2C_pt->I2CTCHandler = at91_I2CTxSendBit;

} //* End


//*-----------------------------------------------------------------------------
//* Function Name       : at91_I2CTxSendBit (I2Cdesc *I2C_pt)
//* Object              :
//* Input Parameters    : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters   : none
//*-----------------------------------------------------------------------------
void at91_I2CTxSendBit (I2Cdesc *I2C_pt)
{//* Begin

    u_char bit_val;

    I2C_pt->pioa_base->PIO_CODR = I2C_pt->SCL_line;      //* Clear SCL line

    //* decrement countBit
    I2C_pt->countBit--;

    //* if bit counter = 0
    if(I2C_pt->countBit >= 0)
    {
    //* get bit to transfert
    bit_val = (I2C_pt->I2CByte >> I2C_pt->countBit) & 1;

    //* Send 0 or 1
    if (bit_val)
        //* Set SDA line
        I2C_pt->pioa_base->PIO_SODR = I2C_pt->SDA_line;

        else
        //* Clear SDA line
        I2C_pt->pioa_base->PIO_CODR = I2C_pt->SDA_line;

    //* change interrupt handler to at91_I2CTxSetSCL
    I2C_pt->I2CTCHandler = at91_I2CTxSetSCL;
    }
    else
    {
    //* set SDA line as an input
    I2C_pt->pioa_base->PIO_ODR = I2C_pt->SDA_line;

    //* change interrupt handler to at91_I2CPrepareACK
    I2C_pt->I2CTCHandler = at91_I2CPrepareACK;
    }
}//* End

//*-----------------------------------------------------------------------------
//* Function Name       : at91_I2CSendStartSDA (I2Cdesc *I2C_pt)
//* Object              : clear SDA line
//* Input Parameters    : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters   : none
//*-----------------------------------------------------------------------------
void at91_I2CSendStartSDA (I2Cdesc *I2C_pt)
{//* Begin

    I2C_pt->pioa_base->PIO_CODR = I2C_pt->SDA_line;     //* clear SDA line

    //* change interrupt handler to at91_I2CSendStartSCL
    I2C_pt->I2CTCHandler = at91_I2CSendStartSCL;

}//* End

//*-----------------------------------------------------------------------------
//* Function Name       : at91_I2CTxSendStart (I2Cdesc *I2C_pt)
//* Object              : clear SCL line
//* Input Parameters    : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters   : none
//*-----------------------------------------------------------------------------
void at91_I2CSendStartSCL (I2Cdesc *I2C_pt)
{//* Begin

    I2C_pt->pioa_base->PIO_CODR = I2C_pt->SCL_line;     //* clear SCL line

    //* change interrupt handler to at91_I2CTxSendBit
    I2C_pt->I2CTCHandler = at91_I2CTxSendBit;

}//* End

//*-----------------------------------------------------------------------------
//* Function Name       : at91_I2CPrepareSTOP (I2Cdesc *I2C_pt)
//* Object              :
//* Input Parameters    : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters   : none
//*-----------------------------------------------------------------------------
void at91_I2CPrepareSTOP (I2Cdesc *I2C_pt)
{//* Begin

    I2C_pt->pioa_base->PIO_OER = I2C_pt->SDA_line;          //* set SDA line as an output
    I2C_pt->pioa_base->PIO_CODR = I2C_pt->SDA_line;         //* clear SDA line
    I2C_pt->pioa_base->PIO_SODR = I2C_pt->SCL_line;         //* set SCL line

    //* change interrupt handler to at91_I2CSendStopSDA
    I2C_pt->I2CTCHandler = at91_I2CSendStopSDA;

}//* End

//*-----------------------------------------------------------------------------
//* Function Name       : at91_I2CSendStopEND (I2Cdesc *I2C_pt)
//* Object              : end of transmistion
//* Input Parameters    : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters   : none
//*-----------------------------------------------------------------------------
void at91_I2CSendStopEND (I2Cdesc *I2C_pt)
{//* Begin

    //* Disable RC compare interrupt
    I2C_pt->timerBase->TC_IDR = TC_CPCS;

    //* change interrupt handler to
    I2C_pt->I2CTCHandler = no_handler_tc;

    //* set the End state
    I2C_pt->state = OK;

}//* End
//*-----------------------------------------------------------------------------
//* Function Name       : at91_I2CSendStopSDA (I2Cdesc *I2C_pt)
//* Object              : set SDA and  ans load end for stop
//* Input Parameters    : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters   : none
//*-----------------------------------------------------------------------------
void at91_I2CSendStopSDA (I2Cdesc *I2C_pt)
{//* Begin

    I2C_pt->pioa_base->PIO_SODR = I2C_pt->SDA_line;         //* set SDA line

    //* change interrupt handler to
    I2C_pt->I2CTCHandler = at91_I2CSendStopEND;

}//* End


//*-----------------------------------------------------------------------------
//* Function Name       : at91_I2CPrepareACK (I2Cdesc *I2C_pt)
//* Object              : set SCL line and load at91_I2CTxWaitACK
//* Input Parameters    : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters   : none
//*-----------------------------------------------------------------------------
void at91_I2CPrepareACK (I2Cdesc *I2C_pt)
{//* Begin

    I2C_pt->pioa_base->PIO_SODR = I2C_pt->SCL_line;         //* set SCL line

    //* change interrupt handler to at91_I2CTxWaitACK
    I2C_pt->I2CTCHandler = at91_I2CTxWaitACK;

}//* End

//*-----------------------------------------------------------------------------
//* Function Name       : at91_I2CRxPrepareACK (I2Cdesc *I2C_pt)
//* Object              :
//* Input Parameters    : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters   : none
//*-----------------------------------------------------------------------------
void at91_I2CRxPrepareACK (I2Cdesc *I2C_pt)
{//* Begin


    I2C_pt->pioa_base->PIO_SODR = I2C_pt->SCL_line;         //* set SCL line

    if(I2C_pt->mode == STOP)
        //* change interrupt handler to
        I2C_pt->I2CTCHandler = at91_I2CPrepareSTOP;
    else
        //* change interrupt handler to at91_I2CRxDoACK
        I2C_pt->I2CTCHandler = at91_I2CRxDoACK;

}//* End

//*-----------------------------------------------------------------------------
//* Function Name       : at91_I2CTxWaitACK (I2Cdesc *I2C_pt)
//* Object              :
//* Input Parameters    : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters   : none
//*-----------------------------------------------------------------------------
void at91_I2CTxWaitACK (I2Cdesc *I2C_pt)
//* Begin
{
    //* if ACK (SDA = 0)
    if((I2C_pt->pioa_base->PIO_PDSR & I2C_pt->SDA_line) == 0)
    {
    switch(I2C_pt->mode)
    {
        case STOP :
            //* clear SCL line
            I2C_pt->pioa_base->PIO_CODR = I2C_pt->SCL_line;

            //* change interrupt handler to
            I2C_pt->I2CTCHandler = at91_I2CPrepareSTOP;
        break;

        case DEVICE_READ :
            //* clear SCL line
            I2C_pt->pioa_base->PIO_CODR = I2C_pt->SCL_line;

            //* change interrupt handler to
            I2C_pt->I2CTCHandler = at91_I2CDeviceRead;
        break;

        case DATA_READ :
            //* change interrupt handler to
            I2C_pt->I2CTCHandler = at91_I2CRxReceiveByte;
        break;

        default :
            //* clear SCL line
            I2C_pt->pioa_base->PIO_CODR = I2C_pt->SCL_line;

            //* change interrupt handler to
            I2C_pt->I2CTCHandler = at91_I2CTxSendByte;
        break;
    } //* End switch
    }
    else
    {
        I2C_pt->nb_ACK--;
    if(I2C_pt->nb_ACK == 0)
        //* change interrupt handler to at91_I2C
        I2C_pt->I2CTCHandler = at91_I2CError;
   }
}//* End

//*-----------------------------------------------------------------------------
//* Function Name       : at91_I2CRxDoACK (I2Cdesc *I2C_pt)
//* Object              : clear SCL line and load RxReceiveByte
//* Input Parameters    : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters   : none
//*-----------------------------------------------------------------------------
void at91_I2CRxDoACK (I2Cdesc *I2C_pt)
{//* Begin

    I2C_pt->pioa_base->PIO_CODR = I2C_pt->SCL_line;     //* clear SCL line

    //* change interrupt handler to
    I2C_pt->I2CTCHandler = at91_I2CRxReceiveByte;

}//* End

//*-----------------------------------------------------------------------------
//* Function Name       : at91_I2CTxSetSCL (I2Cdesc *I2C_pt)
//* Object              : set SCL line
//* Input Parameters    : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters   : none
//*-----------------------------------------------------------------------------
void at91_I2CTxSetSCL (I2Cdesc *I2C_pt)
{//* Begin

    I2C_pt->pioa_base->PIO_SODR = I2C_pt->SCL_line;     //* set SCL line

    //* change interrupt handler to at91_I2CTxSendBit
     I2C_pt->I2CTCHandler = at91_I2CTxSendBit;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -