📄 i2c.c
字号:
/* **********************************************************************
Copyright (c) 2002-2006 Beyond Innovation Technology Co., Ltd
All rights are reserved. Reproduction in whole or in parts is
prohibited without the prior written consent of the copyright owner.
----------------------------------------------------------------------
Module: I2C.C
Purpose: Implementation of I2C module.
Version: 0.02 11:15AM 2005/12/09
Compiler: Keil 8051 C Compiler v8.01
Reference:
[1] I2C Peripherals data handbook IC12, 1996 Philips Semiconductors
[2] Display Driver and I2C-bus Peripherals data handbook IC12, 2000
Philips Semiconductors
----------------------------------------------------------------------
Modification:
R0.01 05:19PM 2004/10/25 Jeffrey Chang
Reason:
1. Original.
Solution:
----------------------------------------------------------------------
R0.02 11:14AM 2005/12/09 Jeffrey Chang
Reason:
1. Revised timing.
Solution:
********************************************************************** */
#define _I2C_C_
/* ------------------------------------
Header Files
------------------------------------ */
#include <intrins.h>
#include "common.h"
#include "i2c.h"
/* ------------------------------------
Macro Definitions
------------------------------------ */
#define NOP_24 { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();}
#define NOP_20 { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); }
#define NOP_18 { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); }
#define NOP_15 { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); }
#define NOP_12 { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); }
#define NOP_10 { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); }
#define NOP_3 { _nop_(); _nop_(); _nop_(); }
#define NOP_2 { _nop_(); _nop_(); }
#define NOP_1 { _nop_(); }
#define NOP_0 { }
// 6 / 14.318MHz = 419 ns !
#if (I2C_MODE_CFG == I2C_MODE_SLOW)
// 100 kHz
// [10]165 Standard Mode Start Set-up Time: Tsu,sta = 4.7 us
// [11]72 Standard Mode Start Set-up Time: Tsu,sta = 4.7 us
#define I2C_SU_STA NOP_24
// [10]165 Standard Mode Start Hold Time: Thd,dat = 4.0 us
// [11]72 Standard Mode Start Hold Time: Thd,dat = 4.0 us
#define I2C_HD_STA NOP_20
// [10]165 Standard Mode Data Set-Up Time: Tsu,dat = 250 ns
// [11]72 Standard Mode Data Set-Up Time: Tsu,dat = 250 ns
#define I2C_SU_DAT NOP_2
// [10]165 Standard Mode Data Hold Time: Thd,dat = 0 us
// [11]72 Standard Mode Data Hold Time: Thd,dat = 0 us
#define I2C_HD_DAT NOP_0
// [10]165 Standard Mode HIGH period of the SCL clock: Thigh = 4.0 us
// [11]72 Standard Mode HIGH period of the SCL clock: Thigh = 4.0 us
#define I2C_HIGH NOP_20
// [10]165 Standard Mode LOW period of the SCL clock: Tlow = 4.7 us
// [11]72 Standard Mode LOW period of the SCL clock: Tlow = 4.7 us
#define I2C_LOW NOP_24
// [10]165 Standard Mode Stop Set-up Time: Tsu,sto = 4.0 us
// [11]72 Standard Mode Stop Set-up Time: Tsu,sto = 4.0 us
#define I2C_SU_STO NOP_20
#elif (I2C_MODE_CFG == I2C_MODE_STANDARD)
// 100 kHz
// [10]165 Standard Mode Start Set-up Time: Tsu,sta = 4.7 us
// [11]72 Standard Mode Start Set-up Time: Tsu,sta = 4.7 us
#define I2C_SU_STA NOP_12
// [10]165 Standard Mode Start Hold Time: Thd,dat = 4.0 us
// [11]72 Standard Mode Start Hold Time: Thd,dat = 4.0 us
#define I2C_HD_STA NOP_10
// [10]165 Standard Mode Data Set-Up Time: Tsu,dat = 250 ns
// [11]72 Standard Mode Data Set-Up Time: Tsu,dat = 250 ns
#define I2C_SU_DAT NOP_1
// [10]165 Standard Mode Data Hold Time: Thd,dat = 0 us
// [11]72 Standard Mode Data Hold Time: Thd,dat = 0 us
#define I2C_HD_DAT NOP_0
// [10]165 Standard Mode HIGH period of the SCL clock: Thigh = 4.0 us
// [11]72 Standard Mode HIGH period of the SCL clock: Thigh = 4.0 us
#define I2C_HIGH NOP_10
// [10]165 Standard Mode LOW period of the SCL clock: Tlow = 4.7 us
// [11]72 Standard Mode LOW period of the SCL clock: Tlow = 4.7 us
#define I2C_LOW NOP_12
// [10]165 Standard Mode Stop Set-up Time: Tsu,sto = 4.0 us
// [11]72 Standard Mode Stop Set-up Time: Tsu,sto = 4.0 us
#define I2C_SU_STO NOP_10
#elif (I2C_MODE_CFG == I2C_MODE_FAST)
// 400 kHz
// [10]165 Fast Mode Start Set-up Time: Tsu,sta = 0.6 us
#define I2C_SU_STA NOP_2
// [10]165 Fast Mode Start Hold Time: Thd,dat = 0.6 us
#define I2C_HD_STA NOP_2
// [10]165 Fast Mode Data Set-Up Time: Tsu,dat = 100 ns
#define I2C_SU_DAT NOP_1
// [10]165 Fast Mode Data Hold Time: Thd,dat = 0 us
#define I2C_HD_DAT NOP_0
// [10]165 Fast Mode HIGH period of the SCL clock: Thigh = 0.6 us
#define I2C_HIGH NOP_2
// [10]165 Fast Mode LOW period of the SCL clock: Tlow = 1.3 us
#define I2C_LOW NOP_3
// [10]165 Fast Mode Stop Set-up Time: Tsu,sto = 0.6 us
#define I2C_SU_STO NOP_2
#elif (I2C_MODE_CFG == I2C_MODE_HIGHSPEED)
// 3.4 MHz
// [10]165 Highspeed Mode Start Set-up Time: Tsu,sta = 4.7 us
#define I2C_SU_STA NOP_0
// [10]165 Highspeed Mode Start Hold Time: Thd,dat = 4.0 us
#define I2C_HD_STA NOP_0
// [10]165 Highspeed Mode Data Set-Up Time: Tsu,dat = 250 ns
#define I2C_SU_DAT NOP_0
// [10]165 Highspeed Mode Data Hold Time: Thd,dat = 0 us
#define I2C_HD_DAT NOP_0
// [10]165 Highspeed Mode HIGH period of the SCL clock: Thigh = 4.0 us
#define I2C_HIGH NOP_0
// [10]165 Highspeed Mode LOW period of the SCL clock: Tlow = 4.7 us
#define I2C_LOW NOP_0
// [10]165 Highspeed Mode Stop Set-up Time: Tsu,sto = 4.0 us
#define I2C_SU_STO NOP_0
#else
#error I2C.C - Invalid I2C_MODE_CFG !
#endif // I2C_MODE_CFG
#define I2C_GET_DAT_HIGH ( I2C_ioSDA == HIGH )
#define I2C_SET_CLK(HiLo) { I2C_ioSCL = (HiLo) ? HIGH : LOW; }
#define I2C_SET_DAT(HiLo) { I2C_ioSDA = (HiLo) ? HIGH : LOW; }
/* ------------------------------------
Type Definitions
------------------------------------ */
/* ------------------------------------
Variables Definitions
------------------------------------ */
sbit I2C_ioSCL = P1 ^ 6;
sbit I2C_ioSDA = P1 ^ 7;
/* ------------------------------------
Function Prototypes
------------------------------------ */
/* -------------------------------------------------------------------
Name: I2C_GetACK -
Purpose: .
Passed: None.
Returns: LOW if OK
Notes:
------------------------------------------------------------------- */
BOOL I2C_GetACK (void)
{
BOOL fResult;
//I2C_SET_DAT(HIGH); // Removed by JC 01:48PM 2005/11/23
I2C_SU_DAT; // Added by JC 01:51PM 2005/11/23
I2C_SET_CLK(HIGH);
I2C_HIGH;
fResult = I2C_GET_DAT_HIGH;
I2C_SET_CLK(LOW);
I2C_LOW;
return( fResult );
} /* I2C_GetACK */
/* -------------------------------------------------------------------
Name: I2C_Init -
Purpose: .
Passed: None.
Returns: None.
Notes:
------------------------------------------------------------------- */
void I2C_Init (void)
{
I2C_SET_DAT(HIGH);
I2C_SET_CLK(HIGH);
} /* I2C_Init */
#if (I2C_RX_BURST)
/* -------------------------------------------------------------------
Name: I2C_RxBurst -
Purpose: To receive bulk data from I2C slave device.
Passed:
bIdx: 1..255. (Excludes slave address and sub-address)
Returns: None.
Notes:
The bSLA should be the slave device's 'WRITE' module addres,
not 'READ' one.
------------------------------------------------------------------- */
void I2C_RxBurst (
UB8 bSLA, /* I2C slave address */
UB8 bREG, /* I2C sub-address */
UB8 bCNT, /* The number of data which will be transmitted */
UB8 *pbDATA /* Point to the first DATA item */
)
{
UB8 bIdx;
I2C_Start();
/* --------------------------------
Write
-------------------------------- */
I2C_TxData(bSLA);
I2C_GetACK();
I2C_TxData(bREG);
I2C_GetACK();
/* --------------------------------
Read
-------------------------------- */
I2C_Start();
I2C_TxData(bSLA | 0x01);
I2C_GetACK();
for (bIdx = 0; bIdx < (bCNT - 1); bIdx++)
{
*pbDATA++ = I2C_RxData();
I2C_SetACK();
} /* for */
/* --------------------------------
Last Read
-------------------------------- */
*pbDATA = I2C_RxData();
I2C_SetNAK();
I2C_Stop();
} /* I2C_RxBurst */
#endif
#if (I2C_RX_BYTE)
/* -------------------------------------------------------------------
Name: I2C_RxByte -
Purpose: To receive one byte data from I2C slave device.
Passed:
UB8 bSLA, I2C slave address
UB8 bREG I2C sub-address
Returns:
One byte received data.
Notes:
The bSLA should be the slave device's 'WRITE' mode address,
not 'READ' one.
------------------------------------------------------------------- */
UB8 I2C_RxByte (
UB8 bSLA, /* I2C slave address */
UB8 bREG /* I2C sub-address */
)
{
UB8 bDATA;
I2C_Start();
/* --------------------------------
Write
-------------------------------- */
I2C_TxData(bSLA);
I2C_GetACK();
I2C_TxData(bREG);
I2C_GetACK();
/* --------------------------------
Read
-------------------------------- */
I2C_Start();
I2C_TxData(bSLA | 0x01);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -