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

📄 lib_twi.c

📁 this document is source code for arm9 of atmel
💻 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_twi.c
* Object            : Basic TWI function driver
* Translator        :
* 1.0 25/11/02 NL   : Creation
* 1.1 31/Jan/05 JPP : Clean For basic
* 1.1 20/Oct/06 PFi : Twi bus clock parameter added to the AT91F_TWI_Open
*                   : function and in AT91F_SetTwiClock
* 1.1 23/Nov/06 PFi : Twi reset added in TWI Open function
* 1.2 19/Dec/06 PFi : Twi Bus recovery fnuction added.
*                   : configuration of TWD/TWCK in open drain mode
*                   : added in TWI_Open fct.
* 1.3 16/Mar/07 PFi : AT91F_SetTwiClock rewrite to set any clock with automatic
*                   : CKDIV computing.
*                   : All TWI read/write functions rewrite to match the new
*                   : flowcharts
*
* TO DO             : Add checking of (cldiv x 2pow*ckdiv) < 8192 in
*                     AT91F_SetTwiClock function according to errata the errata.
-----------------------------------------------------------------------------*/

#include "board.h"
#include "lib_twi.h"
//#include "init.h"
#include <math.h>

#define ERROR (AT91C_TWI_NACK)

/* value of the PIT value to have 333ns @ 48 MHz
3 -1 since real time out = PIV + 1 */
#define PIT_PIV_MICRO_SECOND_VALUE  0x2


/*-----------------------------------------------------------------------------
* Wait function with the Periodic Interval Timer (PIT)
* The wait time is from 1us to 999us.
-----------------------------------------------------------------------------*/
void AT91F_TWI_WaitMicroSecond (unsigned int MicroSecond)
{
   unsigned int PitStatus = 0;     /* Status register of the PIT */
   unsigned int PitLoop = 0;    /* Store the number of PIT Loop */

   AT91C_BASE_PITC->PITC_PIMR = AT91C_PITC_PITEN|PIT_PIV_MICRO_SECOND_VALUE;

   for( PitLoop=0; PitLoop <(MicroSecond);)   /* One PIT loop equals 333ns */
   {
    /* Wait for the PIT counter overflow occurs */
    while ((AT91C_BASE_PITC->PITC_PISR & AT91C_PITC_PITS)==0);
    /* Read the PIT Interval Value Reg. to clear it for the next overflow */
    PitStatus = AT91C_BASE_PITC->PITC_PIVR ;
    /* dummy access to avoid IAR warning */
    PitStatus = PitStatus ;
    PitLoop++;
   }
}


/*----------------------------------------------------------------------------
Function: AT91F_SetTwiClock (int TwiClock)
Arguments: - <TwiClock> TWI bus clock in Hertz
Comments : TO DO:

Return Value: none
-----------------------------------------------------------------------------*/
void AT91F_SetTwiClock(int TwiClock)
{
  unsigned int cldiv,ckdiv=1 ;

  /* CLDIV = ((Tlow x 2^CKDIV) -3) x Tmck */
  /* CHDIV = ((THigh x 2^CKDIV) -3) x Tmck */
  /* Only CLDIV is computed since CLDIV = CHDIV (50% duty cycle) */

  while ( ( cldiv = ( (MCK/(2*TwiClock))-3 ) / pow(2,ckdiv)) > 255 )
   ckdiv++ ;

  AT91C_BASE_TWI->TWI_CWGR =(ckdiv<<16)|((unsigned int)cldiv << 8)|(unsigned int)cldiv  ;
}

/*----------------------------------------------------------------------------
Function : AT91F_TWI_WriteSingle
Arguments: <AT91PS_TWI pTwi> : Pointer to the TWI structure.
           <SlaveAddr>: Address of the slave device to read from.
           <data>: Pointer to the data to write
Comments : Write a single data into a slave device without internal
           address.
           Takes into account the NACK errata.

Return Value: AT91C_TWI_NACK if so.
-----------------------------------------------------------------------------*/
int AT91F_TWI_WriteSingle(const AT91PS_TWI pTwi,
                        int SlaveAddr,
                        char *data)
{
    unsigned int end = 0, status, error=0;

    /* Enable Master Mode */
    pTwi->TWI_CR = AT91C_TWI_MSEN ;

    /* Set the TWI Master Mode Register */
    pTwi->TWI_MMR =  SlaveAddr & ~AT91C_TWI_MREAD;

    /* Write the data to send into THR. Start conditionn DADDR and R/W bit
       are sent automatically */
    pTwi->TWI_THR = *data;

    /* NACK errata handling */
    /* Do not poll the TWI_SR */
    /* Wait 3 x 9 TWCK pulse (max) 2 if IADRR not used, before reading TWI_SR */
    /* From 400Khz down to 1Khz, the time to wait will be in 祍 range.*/
    /* In this example the TWI period is 1/400KHz */
    AT91F_TWI_WaitMicroSecond (40) ;

    while (!end)
    {
      status = AT91C_BASE_TWI->TWI_SR;
      if ((status & AT91C_TWI_NACK) == AT91C_TWI_NACK)
      {
        error++;
        end=1;
      }
    /*  Wait for the Transmit ready is set */
      if ((status & AT91C_TWI_TXRDY) == AT91C_TWI_TXRDY)
        end=1;
    }

    /* Wait for the Transmit complete is set */
    status = AT91C_BASE_TWI->TWI_SR;
    while (!(status & AT91C_TWI_TXCOMP))
      status = AT91C_BASE_TWI->TWI_SR;

    return error;
}

/*----------------------------------------------------------------------------
Function : AT91F_TWI_WriteSingleIadr
Arguments: <AT91PS_TWI pTwi> : Pointer to the TWI structure.
           <SlaveAddr>: Address of the slave device to read from.
           <data>: Pointer to the data to write
           <IntAddr>: Internal slave device address. Set to 0 if no.
           <IntAddrSize>: Size of the internal address.Set to 0 if no.
 Comments : Write a single data into a slave device with an internal
            address.
            Takes into account the NACK errata.

Return Value: AT91C_TWI_NACK if so.
-----------------------------------------------------------------------------*/
int AT91F_TWI_WriteSingleIadr(const AT91PS_TWI pTwi,
                        int SlaveAddr,
                        int IntAddr,
                        int IntAddrSize,
                        char *data)
{
    unsigned int end = 0, status, error=0;

    /* Enable Master Mode */
    pTwi->TWI_CR = AT91C_TWI_MSEN ;

    /* Set the TWI Master Mode Register */
    pTwi->TWI_MMR =  SlaveAddr | IntAddrSize & ~AT91C_TWI_MREAD;

    /* Set TWI Internal Address Register if needed */
    pTwi->TWI_IADR = IntAddr;

    /* Write the data to send into THR. Start conditionn DADDR and R/W bit
       are sent automatically */
    pTwi->TWI_THR = *data;

    /* NACK errata handling */
    /* Do not poll the TWI_SR */
    /* Wait 3 x 9 TWCK pulse (max) 2 if IADRR not used, before reading TWI_SR */
    /* From 400Khz down to 1Khz, the time to wait will be in 祍 range.*/
    /* In this example the TWI period is 1/400KHz */
    AT91F_TWI_WaitMicroSecond (40) ;

    while (!end)
    {
      status = AT91C_BASE_TWI->TWI_SR;
      if ((status & AT91C_TWI_NACK) == AT91C_TWI_NACK)
      {
        error++;
        end=1;
      }
    /*  Wait for the Transmit ready is set */
      if ((status & AT91C_TWI_TXRDY) == AT91C_TWI_TXRDY)
        end=1;
    }

    /* Wait for the Transmit complete is set */
    status = AT91C_BASE_TWI->TWI_SR;
    while (!(status & AT91C_TWI_TXCOMP))
      status = AT91C_BASE_TWI->TWI_SR;

    return error;
}

/*----------------------------------------------------------------------------
Function : AT91F_TWI_WriteMultiple
Arguments: <AT91PS_TWI pTwi> : Pointer to the TWI structure.
           <SlaveAddr>: Address of the slave device to read from.
           <data>: Pointer to the data to write
           <NumOfBytes>: Number of data to write
Comments : Write multiple data into a slave device without internal address.
           Takes into account the NACK errata.

Return Value: AT91C_TWI_NACK if so.
-----------------------------------------------------------------------------*/
int AT91F_TWI_WriteMultiple(const AT91PS_TWI pTwi,
                        int SlaveAddr,
                        char *data,
                        unsigned int NumOfBytes)
{
    unsigned int end = 0, status, error=0, Count;

    /* Enable Master Mode */
    pTwi->TWI_CR = AT91C_TWI_MSEN ;

   /* Wait until TXRDY is high to transmit */
   status = AT91C_BASE_TWI->TWI_SR;
   while (!(status & AT91C_TWI_TXRDY))
        status = AT91C_BASE_TWI->TWI_SR;

    /* Set the TWI Master Mode Register */
    pTwi->TWI_MMR =  SlaveAddr & ~AT91C_TWI_MREAD;

   /* Send the data */
   for ( Count=0; Count < NumOfBytes ;Count++ )
   {
       /* Write the data to send into THR. Start conditionn DADDR and R/W bit
       are sent automatically */
       AT91C_BASE_TWI->TWI_THR = *data++;

       /* NACK errata handling */
       /* Do not poll the TWI_SR */
       /* Wait 3 x 9 TWCK pulse (max) before reading TWI_SR */
       /* From 400Khz down to 1Khz, the time to wait will be in 祍 range.*/
       /* In this example the TWI period is 1/400KHz */
       AT91F_TWI_WaitMicroSecond (40) ;

       while (!end)
       {
           status = AT91C_BASE_TWI->TWI_SR;
           if ((status & AT91C_TWI_NACK) == AT91C_TWI_NACK)
           {
               error++;
               end=1;
           }

           /*  Wait for the Transmit ready is set */
           if ((status & AT91C_TWI_TXRDY) == AT91C_TWI_TXRDY)
            end=1;
        }
    }

    /* Wait for the Transmit complete is set */
    status = AT91C_BASE_TWI->TWI_SR;
    while (!(status & AT91C_TWI_TXCOMP))
      status = AT91C_BASE_TWI->TWI_SR;

    return error;
}

/*----------------------------------------------------------------------------
Function : AT91F_TWI_WriteMultipleIadr
Arguments: <AT91PS_TWI pTwi> : Pointer to the TWI structure.
           <SlaveAddr>: Address of the slave device to read from.
           <data>: Pointer to the data to write
           <NumOfBytes>: Number of data to write

Comments : Write multiple data into a slave device with internal address.
           Takes into account the NACK errata.

Return Value: AT91C_TWI_NACK if so.
-----------------------------------------------------------------------------*/
int AT91F_TWI_WriteMultipleIadr(const AT91PS_TWI pTwi,
                        int SlaveAddr,
                        int IntAddr,
                        int IntAddrSize,
                        char *data,
                        unsigned int NumOfBytes)
{
    unsigned int end = 0, status, error=0, Count;

    /* Enable Master Mode */
    pTwi->TWI_CR = AT91C_TWI_MSEN ;

    /* Set the TWI Master Mode Register */
    pTwi->TWI_MMR =  SlaveAddr | IntAddrSize & ~AT91C_TWI_MREAD;

    /* Set TWI Internal Address Register if needed */
    pTwi->TWI_IADR = IntAddr;

   /* Wait until TXRDY is high to transmit */
   status = AT91C_BASE_TWI->TWI_SR;
   while (!(status & AT91C_TWI_TXRDY))
        status = AT91C_BASE_TWI->TWI_SR;

   /* Send the data */
   for ( Count=0; Count < NumOfBytes ;Count++ )
   {
       /* Write the data to send into THR. Start conditionn DADDR and R/W bit
       are sent automatically */
       AT91C_BASE_TWI->TWI_THR = *data++;

       /* NACK errata handling */
       /* Do not poll the TWI_SR */
       /* Wait 3 x 9 TWCK pulse (max) before reading TWI_SR */
       /* From 400Khz down to 1Khz, the time to wait will be in 祍 range.*/
       /* In this example the TWI period is 1/400KHz */
       AT91F_TWI_WaitMicroSecond (40) ;

       while (!end)
       {
           status = AT91C_BASE_TWI->TWI_SR;
           if ((status & AT91C_TWI_NACK) == AT91C_TWI_NACK)
           {
               error++;
               end=1;
           }

           /*  Wait for the Transmit ready is set */
           if ((status & AT91C_TWI_TXRDY) == AT91C_TWI_TXRDY)
            end=1;
        }
    }

    /* Wait for the Transmit complete is set */
    status = AT91C_BASE_TWI->TWI_SR;
    while (!(status & AT91C_TWI_TXCOMP))
      status = AT91C_BASE_TWI->TWI_SR;

    return error;
}


/*-----------------------------------------------------------------------------
Function: AT91F_TWI_ReadSingle

⌨️ 快捷键说明

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