📄 i2c.c
字号:
//-----------------------------------------------------------------------------
//
// Code modified from eeprom.c by Cypress Semiconductor
// Modified by Nick Merryman, GRASPR team, 2005
//
// Copyright (c) 2002 Cypress Semiconductor
//
//
//-----------------------------------------------------------------------------
#include <ezusb.h>
#include <ezregs.h>
#include "i2c.h"
// user shouldnt call these
void WaitForI2CWrite();
bit I2CWaitForAck();
bit I2CWaitForDone();
void I2CWaitForStop();
//
#define ADCAddr 0x20
BYTE xdata I2CWriteBuf[5];
BYTE xdata I2CReadBuf[5];
void I2CWaitForStop()
{
// Data should not be written to I2CS or I2DAT until the STOP bit returns low.
while (I2CS & bmSTOP)
;
}
// Return 0 for ok, 1 for error
bit I2CWaitForDone()
{
BYTE i;
while (!((i = I2CS) & bmDONE)) // Poll the done bit
;
if (i & bmBERR)
return 1;
else
return 0;
}
// Return 0 for ok, 1 for error
// Same as wait for done, but checks for ACK as well
bit I2CWaitForAck()
{
BYTE i;
while (!((i = I2CS) & bmDONE)) // Poll the done bit
;
if (i & bmBERR)
return 1;
else if (!(i & bmACK))
return 1;
else
return 0;
}
//I2CREAD or I2CWRITE
void I2CStartAndAddr(BYTE op)
{
I2CS = bmSTART;
I2DAT = (ADCAddr << 1) | op;
}
// 0x2e in assembly, less than 0x20 with compiler optimization!!
void WaitForI2CWrite()
{
I2CWaitForStop();
waitForBusy:
I2CStartAndAddr(I2CWRITE);
I2CWaitForDone();
I2CS |= bmSTOP; // ; Set the STOP bit
I2CWaitForStop();
if (!(I2CS & bmACK)) // If no ACK, try again.
goto waitForBusy;
}
// Write up to one page of data to the ADC.
// Returns 0 on success, 1 on failure
// Normally called within a while() loop so that errors are retried:
// while (ADCWriteBlock(....))
// ;
bit I2CWrite(BYTE addr, BYTE xdata * ptr, BYTE len)
{
// BYTE retval;
// Make sure the i2c interface is idle
I2CWaitForStop();
// write the START bit and i2c device address
I2CStartAndAddr(I2CWRITE);
if(I2CWaitForAck())
{
I2CS |= bmSTOP; // ; Set the STOP bit
I2CWaitForStop();
return(1);
}
// write the ADC offset
I2DAT = addr;
// If the ADC doesn't respond, set the STOP bit to idle the bus, then return error
if(I2CWaitForAck())
{
I2CS |= bmSTOP; // ; Set the STOP bit
I2CWaitForStop();
return(1);
}
// Write the data block
for(; len != 0; len--)
{
I2DAT = *ptr++;
if(I2CWaitForAck())
{
I2CS |= bmSTOP; // ; Set the STOP bit
I2CWaitForStop();
return(1);
}
}
I2CS |= bmSTOP;
WaitForI2CWrite();
return 0;
}
// Returns 0 on success, 1 on failure
BYTE I2CRead(BYTE addr, BYTE xdata *buf, BYTE length)
{
BYTE i;
// Make sure the i2c interface is idle
I2CWaitForStop();
// write the START bit and i2c device address
I2CStartAndAddr(I2CWRITE);
if(I2CWaitForAck())
{
I2CS |= bmSTOP; // ; Set the STOP bit
I2CWaitForStop();
return(1);
}
I2DAT = addr; // write which register we're going to read from
// If the ADC doesn't respond, set the STOP bit to idle the bus, then return error
if(I2CWaitForAck())
{
I2CS |= bmSTOP; // ; Set the STOP bit
I2CWaitForStop();
return(1);
}
I2CS |= bmSTOP;
I2CWaitForStop();
//start the read operation here
I2CStartAndAddr(I2CREAD);
if(I2CWaitForAck())
{
I2CS |= bmSTOP; // ; Set the STOP bit
I2CWaitForStop();
return(1);
}
// why are we doing this? -- because the manual says so
// read dummy byte
i = I2DAT;
if(I2CWaitForDone())
{
I2CS |= bmSTOP; // ; Set the STOP bit
I2CWaitForStop();
return(1);
}
for (i=0; i < (length - 1); i++)
{
*(buf+i) = I2DAT;
if(I2CWaitForDone())
{
I2CS |= bmSTOP; // ; Set the STOP bit
I2CWaitForStop();
return(1);
}
//this is apparently taken care of for us -- tricksy microcontroller
/*
I2CS |= bmACK; //send ack from master to device
if(I2CWaitForDone())
return(1);
*/
}
I2CS = bmLASTRD;
if(I2CWaitForDone())
return(1);
*(buf+i) = I2DAT;
if(I2CWaitForDone())
return(1);
I2CS = bmSTOP;
i = I2DAT;
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -