i2c.c

来自「最新版IAR FOR ARM(EWARM)5.11中的代码例子」· C语言 代码 · 共 318 行

C
318
字号
/*************************************************************************
 *
 *    Used with ICCARM and AARM.
 *
 *    (c) Copyright IAR Systems 2007
 *
 *    File name   : i2c.c
 *    Description : Main file
 *
 *    History :
 *    1. Date        : September 4, 2007
 *       Author      : Stanimir Bonev
 *       Description : Create
 *
 *  This example project shows how to use the IAR Embedded Workbench for ARM
 * to develop code for the Samsung-S3F4A0K evaluation board. It shows
 * basic use of I2C. It use I2C channel 0 to write and read data from EEPROM
 * I2C memory 24C08.
 *
 * Jumpers:
 *  J31 - filled position 1-2
 *  J32 - filled position 1-2
 *  All other jumpers are in default position regarding board's manual
 *
 *    $Revision: 18084 $
 **************************************************************************/
#include <samsung\ios3f4a0k.h>
#include <assert.h>
#include "arm_comm.h"
#include "board.h"
#include "gic.h"

#define I2C_MEM_ADDR                0xA0
#define I2C_RD_WR_MASK              0x01
#define I2C_READ                    0x01
#define I2C_WRITE                   0x00

#define SEND_START_COND             0x08
#define SEND_REPEATED_START_COND    0x10
#define RECEIVE_SLAVE_ADDR_WR_AKN   0x18
#define RECEIVE_SLAVE_ADDR_WR_NAKN  0x20
#define RECEIVE_DATA_BYTE_AKN       0x28
#define RECEIVE_DATA_BYTE_NAKN      0x30
#define ARBITRATION_LOST            0x38
#define RECEIVE_SLAVE_ADDR_RD_AKN   0x40
#define RECEIVE_SLAVE_ADDR_RD_NAKN  0x48
#define AKN_DATA_BYTE               0x50
#define NAKN_DATA_BYTE              0x58
#define I2C_IDLE                    0xF8
#define I2C_BUS_ERROR               0x00

typedef enum _I2C_Status_t
{
  I2C_IDLY_STAT = 0, I2C_PROCESS_STAT, I2C_DONE_STAT, I2C_ERROR_STAT
} I2C_Status_t;

Int8U SlaveAddrHold;
volatile Int32U ByteCount;
pInt8U pDataBuffer;
volatile I2C_Status_t I2C_Status;
volatile Int8U I2C_State;

/*************************************************************************
 * Function Name: I2C0_IntrHandler
 * Parameters: none
 * Return: none
 *
 * Description: I2C interrupt handler
 *
 *************************************************************************/
__arm __irq void I2C0_IntrHandler (void)
{
Int8U  Temp;

  GIC_ClearIntr(INO_INT_I2C0);
  I2C_State = I2C0_SR;
  switch(I2C_State)
  {
  case SEND_START_COND:
  case SEND_REPEATED_START_COND:
    I2C0_DAT = SlaveAddrHold;
    break;
  case RECEIVE_SLAVE_ADDR_WR_AKN:
  case RECEIVE_DATA_BYTE_AKN:
    if(ByteCount)
    {
      I2C0_DAT = *pDataBuffer++;
      ByteCount--;
    }
    else
    {
      // Generate stop condition
      I2C0_CR_bit.STO = 1;
      I2C_Status = I2C_DONE_STAT;
    }
    break;
  case RECEIVE_SLAVE_ADDR_WR_NAKN:
    I2C_Status = I2C_ERROR_STAT;
    break;
  case RECEIVE_DATA_BYTE_NAKN:
    I2C_Status = I2C_ERROR_STAT;
    break;
  case ARBITRATION_LOST:
    I2C_Status = I2C_ERROR_STAT;
    break;
  case RECEIVE_SLAVE_ADDR_RD_AKN:
    I2C0_CR_bit.AA = (ByteCount > 1);
    break;
  case RECEIVE_SLAVE_ADDR_RD_NAKN:
    // Generate stop condition
    I2C_Status = I2C_ERROR_STAT;
    break;
  case AKN_DATA_BYTE:
    I2C0_CR_bit.AA = (--ByteCount > 1);
    *pDataBuffer++ = I2C0_DAT;
    break;
  case NAKN_DATA_BYTE:
    Temp = I2C0_DAT;
    if(pDataBuffer)
    {
      *pDataBuffer = Temp;
    }
    // Generate stop condition
    I2C0_CR_bit.STO = 1;
    I2C_Status = I2C_DONE_STAT;
    break;
  default:
    I2C_Status = I2C_ERROR_STAT;
  }
  // Clear interrupt flag
  I2C0_CR_bit.SI = 0;
  GIC_CompletIntr();
}

/*************************************************************************
 * Function Name: I2C_Init
 * Parameters: none
 * Return: none
 *
 * Description: Init I2C block
 *
 *************************************************************************/
void I2C_Init (void)
{
  // Enable PIO0 blocks for I2C0 I/O configuration
  PIO0_ECR = 1;
  // Disable PIO function for I2C signals - SCL and SDA  (P0.8, P0.9)
  PIO0_PDR = (1UL<<9) | (1UL << 8);
  // Disable PIO0 blocks
  PIO0_DCR = 1;
  // Assign P0.8, P0.9 to I2C pull-up disable
  IOCONF_MR1_bit.PIO0_8_F3EN =\
  IOCONF_MR1_bit.PIO0_8_PUENB  = 1;
  IOCONF_MR1_bit.PIO0_9_F3EN =\
  IOCONF_MR1_bit.PIO0_9_PUENB  = 1;

  // I2C init
  // Enable I2C block
  I2C0_ECR = (1UL << 31) | (1UL << 1);
  // software reset
  I2C0_CR = 1;
  // Set I2C0 clock frequency - 100kHz
  I2C0_MR_bit.FAST = 0;
  I2C0_MR_bit.PRV  = 200;
  // set setup/hold delay > 300ns
  I2C0_THOLD_bit.DL = 50;

  // Init I2C0 interrupts
  // Install I2C0 interrupt handler
  GIC_InstallIntr(INO_INT_I2C0,(void *)I2C0_IntrHandler,0,POS_EDGE_TRIG,FALSE);
  // Enable I2C0 interrupts
  GIC_IntrEnable(INO_INT_I2C0);
  // Enable I2C0 interrupt
  I2C0_IER = 1<< 4;
  // Enables the I2C Interface
  I2C0_CR_bit.ENA = 1;
}

/*************************************************************************
 * Function Name: I2C_SendData
 * Parameters: Int8U SlaveAddr, const Int8U * pBuffer, Int32U Size
 * Return: Boolean - TRUE slave ack
 *                   FALSE slave nack
 *
 * Description: Send data to the already addressed slave
 *
 *************************************************************************/
Boolean I2C_SendData (Int8U SlaveAddr, const Int8U * pBuffer, Int32U Size)
{
  SlaveAddrHold = SlaveAddr;
  ByteCount = Size;
  pDataBuffer = (pInt8U)pBuffer;
  I2C_Status = I2C_PROCESS_STAT;
  I2C0_CR_bit.STA = 1;
  while(I2C_Status == I2C_PROCESS_STAT);
  while(I2C0_CR_bit.STO);
  return(I2C_Status == I2C_DONE_STAT);
}

/*************************************************************************
 * Function Name: I2C_ReceiveData
 * Parameters: Int32U SlaveAddr, Int8U * pBuffer, Int32U Size
 * Return: Boolean - TRUE slave ack
 *                   FALSE slave nack
 *
 * Description: Receive data from a slave
 *
 *************************************************************************/
Boolean I2C_ReceiveData (Int32U SlaveAddr, Int8U * pBuffer, Int32U Size)
{
  assert(  ((SlaveAddr & I2C_RD_WR_MASK) == I2C_READ)
         &&(pBuffer != NULL
          && Size != 0));

  SlaveAddrHold = SlaveAddr;
  ByteCount = Size;
  pDataBuffer = pBuffer;
  I2C_Status = I2C_PROCESS_STAT;
  I2C0_CR_bit.STA = 1;
  while(I2C_Status == I2C_PROCESS_STAT);
  while(I2C0_CR_bit.STO);
  return(I2C_Status == I2C_DONE_STAT);
}

/*************************************************************************
 * Function Name: I2C_EEPROM_ByteWrire
 * Parameters: Int8U SlaveAddr, Int32U Addr, Int8U Data
 * Return: Boolean - TRUE command pass
 *                   FALSE command fault
 *
 * Description: Write byte to I2C EEPROM
 *
 *************************************************************************/
Boolean I2C_EEPROM_ByteWrire (Int8U SlaveAddr, Int32U Addr, Int8U Data)
{
Boolean Status;
Int8U Buffer[2];
  // Write data to slave
  Buffer[0] = Addr;
  Buffer[1] = Data;
  SlaveAddr = (SlaveAddr | (Addr>>7 & 0xE)) & ~I2C_RD_WR_MASK;
  Status = I2C_SendData(SlaveAddr, (pInt8U)&Buffer,2);
  if(!Status)
  {
    return(Status);
  }

  // wait until end of writing process
  while(!I2C_SendData(SlaveAddr, NULL, 0));
  return(Status);
}

/*************************************************************************
 * Function Name: I2C_EEPROM_ByteRead
 * Parameters: Int8U SlaveAddr, Int32U Addr, Int8U * pData
 * Return: Boolean - TRUE command pass
 *                   FALSE command fault
 *
 * Description: Read byte from I2C EEPROM
 *
 *************************************************************************/
Boolean I2C_EEPROM_ByteRead (Int8U SlaveAddr, Int32U Addr, Int8U * pData)
{
Boolean Status;

  SlaveAddr = (SlaveAddr | (Addr>>7 & 0xE)) & ~I2C_RD_WR_MASK;
  // Set Address
  Status = I2C_SendData(SlaveAddr, (pInt8U)&Addr,1);
  if(!Status)
  {
    return(Status);
  }
  // Read data from slave
  Status = I2C_ReceiveData(SlaveAddr | I2C_READ,
                           pData,
                           1);
  return(Status);
}

/*************************************************************************
 * Function Name: main
 * Parameters: none
 * Return: none
 *
 * Description: Main
 *
 *************************************************************************/
void main (void)
{
Boolean Status;

  I2C_Init();

  __enable_interrupt();

  // Write Data
  for(Int32U i = 0; i < 20; i++)
  {
    Status = I2C_EEPROM_ByteWrire(I2C_MEM_ADDR,i,i);
    assert(Status);
  }

  // Read data
  for(Int32U i = 0; i < 20; i++)
  {
    Int32U Data;
    Status = I2C_EEPROM_ByteRead(I2C_MEM_ADDR,i,(pInt8U)&Data);
    assert(Status);
    if(i != Data)
    {
      assert(0);
    }
  }
}



⌨️ 快捷键说明

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