📄 i2c.c
字号:
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006-2007 MStar Semiconductor, Inc.
// All rights reserved.
//
// Unless otherwise stipulated in writing, any and all information contained
// herein regardless in any format shall remain the sole proprietary of
// MStar Semiconductor Inc. and be kept in strict confidence
// (¨MStar Confidential Information〃) by the recipient.
// Any unauthorized act including without limitation unauthorized disclosure,
// copying, use, reproduction, sale, distribution, modification, disassembling,
// reverse engineering and compiling of the contents of MStar Confidential
// Information is unlawful and strictly prohibited. MStar hereby reserves the
// rights to any and all damages, losses, costs and expenses resulting therefrom.
//
////////////////////////////////////////////////////////////////////////////////
#pragma OPTIMIZE(8)
#include "mreg51.h"
#include "board.h"
#if ( ENABLE_EEPROM )
#include "hwreg.h"
#include "i2c.h"
#include <intrins.h>
#define mcuSetIntEn() ;//(EA = 1)
#define mcuClrIntEn() ;//(EA = 0)
#ifndef EEPROM_CLK_SEL
#define EEPROM_CLK_SEL EEPROM_CLK_100KHZ
#endif
#if EEPROM_CLK_SEL == EEPROM_CLK_400KHZ
#define i2c_Delay() \
{ \
_nop_(); _nop_(); _nop_(); _nop_(); \
_nop_(); _nop_(); _nop_(); _nop_(); \
_nop_(); _nop_(); _nop_(); _nop_(); \
_nop_(); _nop_(); _nop_(); _nop_(); \
_nop_(); _nop_(); _nop_(); _nop_(); \
_nop_(); _nop_(); _nop_(); _nop_(); \
_nop_(); _nop_(); _nop_(); _nop_(); \
_nop_(); \
}
#elif EEPROM_CLK_SEL == EEPROM_CLK_200KHZ
void i2c_Delay(void)
{
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_();
}
#else
void i2c_Delay(void)
{
U8 u8Loop;
u8Loop = 30; // 99Khz
while (u8Loop-- > 0)
{
_nop_();
}
}
#endif
#if ( _EEPROM_ACCESS == IIC_BY_SW )
////////////////////////////////////////////////////////////////////////////////
// Set I2C SCL pin high/low.
//
// Arguments: bSet - high/low bit
////////////////////////////////////////////////////////////////////////////////
void i2cSetSCL_Chk(bit bSet)
{
BYTE ucDummy; // loop dummy
i2cSCL_PIN_OUT();
i2cSetSCL(bSet); // set SCL pin
if (bSet == _HIGH) // if set pin high
{
ucDummy = I2C_CHECK_PIN_DUMMY; // initialize dummy
i2cSCL_PIN_IN();
while ((GetPinI2cSCL() == _LOW) && (ucDummy--)) ; // check SCL pull high
i2cSCL_PIN_OUT();
}
}
////////////////////////////////////////////////////////////////////////////////
// Set I2C SDA pin high/low
//
// Arguments: bSet - high/low bit
////////////////////////////////////////////////////////////////////////////////
void i2cSetSDA_Chk(bit bSet)
{
BYTE ucDummy; // loop dummy
i2cSDA_PIN_OUT();
i2cSetSDA(bSet); // set SDA pin
if (bSet == _HIGH) // if set pin high
{
ucDummy = I2C_CHECK_PIN_DUMMY; // initialize dummy
i2cSDA_PIN_IN();
while ((GetPinI2cSDA() == _LOW) && (ucDummy--)) ; // check SDA pull high
i2cSDA_PIN_OUT();
}
}
////////////////////////////////////////////////////////////////////////////////
// I2C start signal.
// <comment>
// SCL ________
// \_________
// SDA _____
// \____________
//
// Return value: None
////////////////////////////////////////////////////////////////////////////////
BOOL i2c_Start(void)
{
BOOL bStatus = TRUE; // success status
mcuClrIntEn(); // disable all interrupt
i2cSetSDA_Chk(_HIGH);
i2c_Delay();
i2cSetSCL_Chk(_HIGH);
i2c_Delay();
// check pin error
i2cSCL_PIN_IN();
i2cSDA_PIN_IN();
if ((GetPinI2cSCL() == _LOW) || (GetPinI2cSDA() == _LOW))
{
i2cSCL_PIN_OUT();
i2cSDA_PIN_OUT();
bStatus = FALSE;
}
else // success
{
i2cSDA_PIN_OUT();
i2cSetSDA(_LOW);
i2c_Delay();
i2cSCL_PIN_OUT();
i2cSetSCL(_LOW);
}
mcuSetIntEn(); // release EA bit
return bStatus;
}
////////////////////////////////////////////////////////////////////////////////
// I2C stop signal.
// <comment>
// ____________
// SCL _______/
// _________
// SDA __________/
////////////////////////////////////////////////////////////////////////////////
void i2c_Stop(void)
{
mcuClrIntEn(); // disable all interrupt
i2cSetSCL(_LOW);
i2c_Delay();
i2cSetSDA(_LOW);
i2c_Delay();
i2cSetSCL_Chk(_HIGH);
i2c_Delay();
i2cSetSDA_Chk(_HIGH);
i2c_Delay();
mcuSetIntEn(); // release EA bit
}
////////////////////////////////////////////////////////////////////////////////
// I2C receive byte from device.
//
// Return value: receive byte
////////////////////////////////////////////////////////////////////////////////
BYTE i2c_ReceiveByte(BOOL bAck)
{
BYTE ucReceive = 0;
BYTE ucMask = 0x80;
mcuClrIntEn();
i2cSDA_PIN_IN();
while ( ucMask )
{
i2cSetSCL_Chk(_HIGH);
i2c_Delay();
if (GetPinI2cSDA() == _HIGH)
{
ucReceive |= ucMask;
}
i2cSetSCL(_LOW);
i2c_Delay();
ucMask >>= 1; // next
}
i2cSDA_PIN_OUT();
if (bAck)
{
// acknowledge
i2cSetSDA_Chk(I2C_ACKNOWLEDGE);
}
else
{
// non-acknowledge
i2cSetSDA_Chk(I2C_NON_ACKNOWLEDGE);
}
i2c_Delay();
i2cSetSCL_Chk(_HIGH);
i2c_Delay();
i2cSetSCL(_LOW);
i2c_Delay();
mcuSetIntEn(); // release EA bit
return ucReceive;
}
////////////////////////////////////////////////////////////////////////////////
// I2C send byte to device.
//
// Arguments: ucVal - send byte
// Return value: I2C acknowledge bit
// I2C_ACKNOWLEDGE/I2C_NON_ACKNOWLEDGE
////////////////////////////////////////////////////////////////////////////////
bit i2c_SendByte(BYTE ucVal)
{
BYTE ucMask = 0x80;
bit bAck; // acknowledge bit
mcuClrIntEn();
while ( ucMask )
{
if (ucVal & ucMask)
{
i2cSetSDA_Chk(_HIGH);
}
else
{
i2cSetSDA_Chk(_LOW);
}
i2c_Delay();
i2cSetSCL_Chk(_HIGH); // clock
i2c_Delay();
i2cSetSCL(_LOW);
i2c_Delay();
ucMask >>= 1; // next
}
// recieve acknowledge
i2cSDA_PIN_IN();
i2c_Delay();
i2cSetSCL_Chk(_HIGH);
i2c_Delay();
bAck = GetPinI2cSDA(); // recieve acknowlege
i2cSDA_PIN_OUT();
i2cSetSCL(_LOW);
i2c_Delay();
mcuSetIntEn(); // release EA bit
return (bAck);
}
////////////////////////////////////////////////////////////////////////////////
// I2C access start.
//
// Arguments: ucSlaveAdr - slave address
// trans_t - I2C_TRANS_WRITE/I2C_TRANS_READ
////////////////////////////////////////////////////////////////////////////////
BOOL i2c_AccessStart(BYTE ucSlaveAdr, I2cIoTransType trans_t)
{
BYTE ucDummy; // loop dummy
if (trans_t == I2C_TRANS_READ) // check i2c read or write
{
ucSlaveAdr = I2C_DEVICE_ADR_READ(ucSlaveAdr); // read
}
else
{
ucSlaveAdr = I2C_DEVICE_ADR_WRITE(ucSlaveAdr); // write
}
// enlarge retry count to cover internal write period
ucDummy = 60; //I2C_ACCESS_DUMMY_TIME;
while (ucDummy--)
{
if (i2c_Start() == FALSE)
{
continue;
}
if (i2c_SendByte(ucSlaveAdr) == I2C_ACKNOWLEDGE) // check acknowledge
{
return TRUE;
}
i2c_Stop();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -