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 + -
显示快捷键?