📄 drv_i2c.c
字号:
/*-------------------------------------------------------------------
FILE NAME:
drv_i2c.c
DESCRIPTION:
this file includes i2c bus driver.
AUTHOR:
WYF
VERSION:
2005.1122.00
COMPANY:
DATANG MICROELECTRONICS TECHNOLOGY CO,.LTD
HISTORY:
2005.1122 Creat this file
...
--------------------------------------------------------------------*/
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "nucleus.h"
#include "ADSmx21_defs.h"
#include "drv_defs.h"
#include "drv_extr.h"
#define I2C_I2CR_IEN 7
#define I2C_I2CR_IIEN 6
#define I2C_I2CR_MSTA 5
#define I2C_I2CR_MTX 4
#define I2C_I2CR_TXAK 3
#define I2C_I2CR_RSTA 2
#define I2C_I2SR_ICF 7
#define I2C_I2SR_IAAS 6
#define I2C_I2SR_IBB 5
#define I2C_I2SR_IAL 4
#define I2C_I2SR_SRW 2
#define I2C_I2SR_IIF 1
#define I2C_I2SR_RXAK 0
#define I2C_STOP() {I2CR &= ~(1<<5); }
#define I2C_PUT_BYTE(byData) {while(!(I2SR&(1<<7)));I2DR = byData;}
#define SET_TRANSMIT_MODE() {I2CR |= (1<<4);}
#define SET_MASTER_MODE() {while(I2SR&(1<<5));I2CR |= (1<<5);}
#define CLR_BITS(reg, bit) do{reg &= ~(1<<bit);}while(0)
#define SET_BITS(reg, bit) do{reg |= (1<<bit);}while(0)
static TDRV_I2C i2c;
void __DoTransfer(void)
{
TDRV_I2C *pI2C = &i2c;
int dwData;
while (pI2C->FbProgress) {
while (!(I2SR&(1<<I2C_I2SR_IIF)));
I2SR &= ~(1<<I2C_I2SR_IIF);
if (pI2C->FbProcessTxMode) {
// Processing Tx Mode
if (I2SR & (1<<I2C_I2SR_RXAK)) {
// No Acknowledge receive
I2C_STOP();
pI2C->FbProgress = FALSE;
}
else {
// Acknowledge Received
if (pI2C->FiTxProgressIndex == pI2C->FiTxBufferSize) {
// Last Byte Transmitted
if (pI2C->FbTxMode) {
// In Tx Mode and Last Byte Transmitted
// Every thing is OK, Bye bye
I2C_STOP();
pI2C->FbProgress = FALSE;
}
else {
// Switch to Rx Mode
pI2C->FbProcessTxMode = FALSE;
CLR_BITS(I2CR, I2C_I2CR_MTX);
if (pI2C->FiRxBufferSize == 1) {
// Disable Acknowledge
SET_BITS(I2CR, I2C_I2CR_TXAK);
}
else {
// Enable Acknowledge
CLR_BITS(I2CR, I2C_I2CR_TXAK);
}
// Dummy Read from I2DR
dwData = I2DR;
}
}
else {
// Still other Byte
dwData = pI2C->FpbyTxBuffer[pI2C->FiTxProgressIndex++];
I2DR = (char)dwData;
}
}
}
else {
// Processing Rx Mode
if (pI2C->FiRxProgressIndex == (pI2C->FiRxBufferSize - 1)) {
// Last Byte to be Read
I2C_STOP();
pI2C->FbProgress = FALSE;
}
else if (pI2C->FiRxProgressIndex == (pI2C->FiRxBufferSize - 2)) {
// 2nd Last Byte to be Read
// Disable Acknowledge
SET_BITS(I2CR, I2C_I2CR_TXAK);
}
dwData = I2DR;
pI2C->FpbyRxBuffer[pI2C->FiRxProgressIndex++] = (char)dwData;
}
}
}
static void __WriteMasterData(char byAddress, char* pbyDataBuffer, int iDataSize)
{
SET_MASTER_MODE();
SET_TRANSMIT_MODE();
/* indicate to the DoTransfer function that I2C is in transmiting mode */
i2c.FbTxMode = TRUE;
i2c.FbProcessTxMode = TRUE;
i2c.FbProgress = TRUE;
i2c.FpbyTxBuffer = pbyDataBuffer;
i2c.FiTxBufferSize = iDataSize;
i2c.FiTxProgressIndex = 0;
byAddress &= ~0x01;
I2C_PUT_BYTE(byAddress);
__DoTransfer();
}
static void __ReadMasterData(char byAddress, char* pbyRxDataBuffer, int iRxDataSize)
{
SET_MASTER_MODE();
SET_TRANSMIT_MODE();
/* indicate to the DoTransfer function that I2C is in receiving mode */
i2c.FbTxMode = FALSE;
i2c.FbProcessTxMode = TRUE;
i2c.FbProgress = TRUE;
i2c.FiTxBufferSize = 0;
i2c.FiTxProgressIndex = 0;
i2c.FpbyRxBuffer = pbyRxDataBuffer;
i2c.FiRxBufferSize = iRxDataSize;
i2c.FiRxProgressIndex = 0;
byAddress |= 0x01;
I2C_PUT_BYTE(byAddress);
__DoTransfer();
}
void I2C_init(void)
{
STATUS s;
PTD_GIUS &= ~0x60000;
PCCR0 |= 0x1000;
// IFDR = 0x3F; /* Clk: 66.5MHz/2048 */
IFDR = 0x38; /* Clk: 66.5MHz/640 */
I2CR |= 0x80; /* Enable I2C */
I2CR |= 0x08; /* Disable Ack */
s = NU_Create_Semaphore(&(i2c.lock), "i2c", 1, NU_PRIORITY);
assert(s == NU_SUCCESS);
}
void I2C_write(char I2CAddress, char* DataBuffer, int DataSize)
{
STATUS s;
s = NU_Obtain_Semaphore(&(i2c.lock), NU_NO_SUSPEND);
assert(s == NU_SUCCESS);
__WriteMasterData(I2CAddress, DataBuffer, DataSize);
s = NU_Release_Semaphore(&(i2c.lock));
assert(s == NU_SUCCESS);
}
void I2C_read(char I2CAddress, char* DataBuffer, int DataSize)
{
STATUS s;
s = NU_Obtain_Semaphore(&(i2c.lock), NU_NO_SUSPEND);
assert(s == NU_SUCCESS);
__ReadMasterData(I2CAddress, DataBuffer, DataSize);
s = NU_Release_Semaphore(&(i2c.lock));
assert(s == NU_SUCCESS);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -