📄 i2c_24c04.c
字号:
/*****************************************************************************
* i2c.c: I2C C file for Philips LPC214x Family Microprocessors
*
* Copyright(C) 2006, Philips Semiconductor
* All rights reserved.
*
* History
* 2005.10.01 ver 1.00 Prelimnary version, first Release
*
*****************************************************************************/
#include "LPC213x.h" /* LPC21xx definitions */
#include "type.h"
#include "irq.h"
//#include "i2c.h"
#define BUFSIZE 0x20
#define MAX_TIMEOUT 0x00FFFFFF
#define I2CMASTER 0x01
#define I2CSLAVE 0x02
/* For more info, read Philips's SE95 datasheet */
#define SE95_ADDR 0x9E
#define SE95_ID 0x05
#define SE95_CONFIG 0x01
#define SE95_TEMP 0x00
#define RD_BIT 0x01
#define GET_DEVICE_ID 0x01
#define GET_TEMPERATURE 0x02
#define SET_CONFIGURATION 0x03
#define I2C_IDLE 0
#define I2C_STARTED 1
#define I2C_RESTARTED 2
#define I2C_REPEATED_START 3
#define DATA_ACK 4
#define DATA_NACK 5
#define I2CONSET_I2EN 0x00000040 /* I2C Control Set Register */
#define I2CONSET_AA 0x00000004
#define I2CONSET_SI 0x00000008
#define I2CONSET_STO 0x00000010
#define I2CONSET_STA 0x00000020
#define I2CONCLR_AAC 0x00000004 /* I2C Control clear Register */
#define I2CONCLR_SIC 0x00000008
#define I2CONCLR_STAC 0x00000020
#define I2CONCLR_I2ENC 0x00000040
#define I2DAT_I2C 0x00000000 /* I2C Data Reg */
#define I2ADR_I2C 0x00000000 /* I2C Slave Address Reg */
#define I2SCLH_SCLH 0x000000c8 /* I2C SCL Duty Cycle High Reg */
#define I2SCLL_SCLL 0x000000c8 /* I2C SCL Duty Cycle Low Reg */
/*
DWORD I2CMasterState = I2C_IDLE;
DWORD I2CSlaveState = I2C_IDLE;
DWORD I2CCmd;
DWORD I2CMode;
BYTE I2CMasterBuffer[BUFSIZE];
BYTE I2CSlaveBuffer[BUFSIZE];
DWORD I2CCount = 0;
DWORD I2CReadLength;
DWORD I2CWriteLength;
DWORD RdIndex = 0;
DWORD WrIndex = 0;
*/
BYTE IIC_Chip_Addr; //第一个送至24C04的数据
//为24C04的地址以及读写操作的最高位地址,及读写控制信号
BYTE IIC_Addr; //第二个送至24C04的数据
//为读写操作的地址数据
BYTE IIC_Byte_Number; //数据个数
BYTE IIC_Data; //数据缓冲器
BOOL IIC_Busy = FALSE; //IIC忙标志位
/*
From device to device, the I2C communication protocol may vary,
in the example below, the protocol uses repeated start to read data from or
write to the device:
For master read: the sequence is: STA,Addr(W),offset,RE-STA,Addr(w),data...STO
for master write: the sequence is: STA,Addr(W),length,RE-STA,Addr(r),data...STO
Thus, in state 8, the address is always WRITE. in state 10, the address could
be READ or WRITE depending on the I2CCmd.
*/
/*****************************************************************************
** Function name: I2C0MasterHandler
**
** Descriptions: I2C0 interrupt handler, deal with master mode
** only.
**
** parameters: None
** Returned value: None
**
*****************************************************************************/
void I2C0MasterHandler (void) __irq
{
BYTE StatValue;
/* this handler deals with master read and master write only */
StatValue = I2C0STAT; //读取IIC状态,以便后面针对不同状态进行分支处理
// IENABLE;
//
switch ( StatValue )
{
case 0x08: //IIC 启动条件已发送完毕,紧接要发送从器件地址
I2C0DAT = IIC_Chip_Addr&(~0x01);//I2CMasterBuffer[0]; //发送从器件地址以及读写标志位
I2C0CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC); //清标志
break;
case 0x10: //读操作重发,当读操作时,在启动条件后发送完从器件地址
I2C0DAT = IIC_Chip_Addr;
I2C0CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
break;
case 0x18: //从器件地址发送完后,接收到ACK,接着要发送操作地址
I2C0DAT = IIC_Addr;
I2C0CONCLR = I2CONCLR_SIC;
break;
case 0x20:
I2C0CONSET = I2CONSET_STO;//
I2C0CONSET = I2CONSET_STA;
I2C0CONCLR = I2CONCLR_SIC;
break;
case 0x28: /* Data byte has been transmitted, regardless ACK or NACK */
case 0x30:
if(IIC_Byte_Number)
{
if(IIC_Chip_Addr&0x01)
{
I2C0CONSET = I2CONSET_STA; //读重发
}
else
{
I2C0DAT = IIC_Data; //发送有效数据
IIC_Byte_Number--;
}
}
else
{
if(IIC_Chip_Addr&0x01)
{
I2C0CONSET = I2CONSET_STA; //读重发
}
else
{
I2C0CONSET = I2CONSET_STO;//
IIC_Busy = FALSE;
}
}
I2C0CONCLR = I2CONCLR_SIC;
break;
case 0x40: //主接收器,读重发已发完,收到ACK,这里将设置在接收到数据后发NACK
I2C0CONCLR = I2CONCLR_AAC;
I2C0CONCLR = I2CONCLR_SIC;
break;
case 0x50: /* Data byte has been received, regardless following ACK or NACK */
case 0x58:
IIC_Data = I2C0DAT;
IIC_Busy = FALSE;
//这里也一样,应将IIC停掉
// I2C0CONSET = I2CONSET_AA; /* assert ACK after data is received */
I2C0CONSET = I2CONSET_STO;
I2C0CONCLR = I2CONCLR_SIC;
while( I2C0CONSET & I2CONSET_STO );
break;
case 0x48:
I2C0CONSET = I2CONSET_STO;//
I2C0CONSET = I2CONSET_STA;
I2C0CONCLR = I2CONCLR_SIC;
break;
case 0x38:
default:
I2C0CONSET = I2CONSET_STO;//
I2C0CONCLR = I2CONCLR_SIC;
break;
}
// IDISABLE;
VICVectAddr = 0; /* Acknowledge Interrupt */
}
/*****************************************************************************
** Function name: I2CStart
**
** Descriptions: Create I2C start condition, a timeout
** value is set if the I2C never gets started,
** and timed out. It's a fatal error.
**
** parameters: None
** Returned value: true or false, return false if timed out
**
*****************************************************************************/
/*
DWORD I2CStart( void )
{
DWORD timeout = 0;
DWORD returnValue = FALSE;
//--- Issue a start condition ---
I2C0CONSET = I2CONSET_STA; // Set Start flag //
//--- Wait until START transmitted ---
while( 1 )
{
if ( I2CMasterState == I2C_STARTED )
{
returnValue = TRUE;
break;
}
if ( timeout >= MAX_TIMEOUT )
{
returnValue = FALSE;
break;
}
timeout++;
}
return ( returnValue );
}
*/
/*****************************************************************************
** Function name: I2CStop
**
** Descriptions: Set the I2C stop condition, if the routine
** never exit, it's a fatal bus error.
**
** parameters: None
** Returned value: true or never return
**
*****************************************************************************/
/*
DWORD I2CStop( void )
{
I2C0CONSET = I2CONSET_STO; // Set Stop flag
I2C0CONCLR = I2CONCLR_SIC; // Clear SI flag
//--- Wait for STOP detected ---
while( I2C0CONSET & I2CONSET_STO );
return TRUE;
}*/
/*****************************************************************************
** Function name: I2CInit
**
** Descriptions: Initialize I2C controller
**
** parameters: I2c mode is either MASTER or SLAVE
** Returned value: true or false, return false if the I2C
** interrupt handler was not installed correctly
**
*****************************************************************************/
DWORD I2CInit( void)
{
PINSEL0 = 0x50; /* set PIO0.2 and PIO0.3 to I2C0 SDA and SCK */
IODIR0 = 0x0C; /* set port 0.2 and port 0.3 to output, high */
IOSET0 = 0x0C;
I2C0CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;
I2C0SCLL = I2SCLL_SCLL;
I2C0SCLH = I2SCLH_SCLH;
if ( install_irq( I2C0_INT, (void *)I2C0MasterHandler ) == FALSE )
{
return( FALSE );
}
I2C0CONSET = I2CONSET_I2EN;
return( TRUE );
}
//=====================================================================//
//函数:char SM_Receive (unsigned int byte_address)
//描述:读单字节数据从指定的AT24C04的地址空间
//参数:byte_address 地址,9位有效
//返回:Dat 数据
//注意:无
//=====================================================================//
unsigned char SM_Receive (unsigned int byte_address)
{
unsigned char ucTemp;
ucTemp = (unsigned char)(byte_address>>7);
ucTemp = ucTemp&0x02;
while (IIC_Busy); // 等待总线空闲
// I2CMasterState = I2C_IDLE;
IIC_Busy = TRUE; //占用SMBus(设置为忙)
// SMB0CN = 0x44; // 允许SMBus,应答周期发ACK
IIC_Byte_Number = 1; // 1 地址字节
IIC_Chip_Addr = (0xA0|0x01|ucTemp); // 片选+ READ + 一个高位的地址
IIC_Addr = (unsigned char)(byte_address&0x00FF); // 8 位地址
I2C0CONSET = I2CONSET_STA;//I2CStart(); // 启动传输过程
while (IIC_Busy==TRUE); // 等待传输结束
while( I2C0CONSET & I2CONSET_STO );
return IIC_Data;
}
//=====================================================================//
//函数:void SM_Send (unsigned int byte_address, unsigned char out_byte)
//描述:写单字节数据至指定的AT24C04的地址空间
//参数:byte_address 地址,9位有效
// out_byte 数据
//返回:无
//注意:无
//=====================================================================//
// SMBus 字节写函数-----------------------------------------------------
void SM_Send (unsigned int byte_address, unsigned char out_byte)
{
unsigned char ucTemp;
ucTemp = (unsigned char)(byte_address>>7);
ucTemp = ucTemp&0x02;
while (IIC_Busy==TRUE); // 等待SMBus 空闲
IIC_Busy = 1; // 占用SMBus(设置为忙)
IIC_Byte_Number = 1; // 1 地址字节
IIC_Chip_Addr = (0xA0|ucTemp); // 片选+ READ + 一个高位的地址
IIC_Addr = (unsigned char)(byte_address&0x00FF); // 8 位地址
IIC_Data = out_byte; // 待写数据
I2C0CONSET = I2CONSET_STA;//I2CStart(); // 启动传输过程
while (IIC_Busy==TRUE); // 等待传输结束
while( I2C0CONSET & I2CONSET_STO );
}
/*****************************************************************************
** Function name: I2CEngine
**
** Descriptions: The routine to complete a I2C transaction
** from start to stop. All the intermitten
** steps are handled in the interrupt handler.
** Before this routine is called, the read
** length, write length, I2C master buffer,
** and I2C command fields need to be filled.
** see i2cmst.c for more details.
**
** parameters: None
** Returned value: true or false, return false only if the
** start condition can never be generated and
** timed out.
**
*****************************************************************************/
/*
DWORD I2CEngine( void )
{
I2CMasterState = I2C_IDLE;
RdIndex = 0;
WrIndex = 0;
if ( I2CStart() != TRUE )
{
I2CStop();
return ( FALSE );
}
while ( 1 )
{
if ( I2CMasterState == DATA_NACK )
{
I2CStop();
break;
}
}
return ( TRUE );
} */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -