📄 i2c.c
字号:
/******************************************************
FOR SAA7113 I2C
******************************************************/
#include "I2C.h"
//------------------------------------------------------------------------------
// I2C Peripheral Function Prototypes
//------------------------------------------------------------------------------
void Init(void); // Initialize I2C port
void Start(void); // Sends I2C Start Trasfer
void Stop(void); // Sends I2C Stop Trasfer
bool Write(unsigned char data_out); // Writes data over the I2C bus
bool Read(unsigned char *data_in, bool send_ack);// Reads data from the I2C bus
void SetSCLK(bool state); // Set SCLK to <state>
void SetSDATA(bool state); // Set SDATA to <state>
bool GetSDATA(); // Get SDATA state
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// I2C Peripheral Variables
//------------------------------------------------------------------------------
unsigned char IdentAddr = 0x00;
unsigned int Delay = 0x00000000;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Procedure: I2C_Init
// Inputs: identaddr
// Outputs: bool
// Description: Initialize I2C and setup Slave Ident Addr. then check the ident
// for response and returns true if ok.
//------------------------------------------------------------------------------
bool I2C_Init(unsigned char identaddr)
{
bool ret;
// Calculate Delay NEED FIX!!!
Delay = ((*pPLL_CTL & 0x7e00) >> 9);//jiapeng change 9 to 8;
if ((*pPLL_CTL & 0x0001) == 0x0001)
Delay /= 2;
//jiapeng adds it.
Delay *= 2;
IdentAddr = identaddr;
Init(); // Initialize I2C port
Start(); // Check Slave Ident Addr
ret = Write(IdentAddr);
Stop();
return ret; // Return true if Ident Addr. Ok
}
//------------------------------------------------------------------------------
// Procedure: I2C_Write
// Inputs: data out, address
// Outputs: bool
// Description: Writes a byte to the given address and return status.
//------------------------------------------------------------------------------
bool I2C_Write(unsigned char data_out, unsigned char address)
{
Start(); // Send start signal
if (!Write(IdentAddr)) // Send identifier I2C address
{
Stop(); // Send I2C Stop Transfer
return false;
}
if (!Write(address)) // Send address to device
{
Stop(); // Send I2C Stop Transfer
return false;
}
if (!Write(data_out)) // Send byte to device
{
Stop(); // Send I2C Stop Transfer
return false;
}
Stop(); // Send I2C Stop Transfer
return true;
}
//------------------------------------------------------------------------------
// Procedure: I2C_Read
// Inputs: *data_in, address
// Outputs: bool
// Description: Reads a byte from the given address and return status.
//------------------------------------------------------------------------------
bool I2C_Read(unsigned char *data_in, unsigned char address)
{
Start(); // Send start signal
if (!Write(IdentAddr)) // Send identifer I2C address
{
Stop(); // Send I2C Stop Transfer
return false;
}
if (!Write(address)) // Send address to device
{
Stop(); // Send I2C Stop Transfer
return false;
}
Start(); // Send I2C Start Transer
if (!Write(IdentAddr+1)) // Send identifer I2C address
{
Stop(); // Send I2C Stop Transfer
return false;
}
if (!Read(data_in, false)) // Read byte
{
Stop(); // Send I2C Stop Transfer
return false;
}
Stop(); // Send I2C Stop Transfer
return true;
}
//------------------------------------------------------------------------------
// I2C Functions - Master
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Routine: Init
// Inputs: none
// Outputs: none
// Purpose: Initialize I2C for the ADu812C
//------------------------------------------------------------------------------
void INL Init(void)
{
*pFIO0_DIR |= SCLK; // Set SCLK as output and SDATA as input/high
*pFIO0_POLAR &= ~SDATA; // Enable Active Hight
*pFIO0_EDGE &= ~SDATA; // Enable Level Sensitivity
*pFIO0_INEN |= SDATA; // Enable SDATA Input Buffer
SetSDATA(1); // Set SDATA as input/high
SetSCLK(1); // Set SCLK high
}
//------------------------------------------------------------------------------
// Routine: Start
// Inputs: none
// Outputs: none
// Purpose: Sends I2C Start Trasfer - "S"
//------------------------------------------------------------------------------
void INL Start(void)
{
// 11182003 - Following line has been added! (Fixed thanks to Andrew Seddon).
// Shouldn't Stop() be setting SCLK high?
SetSCLK(1); // Set SCLK high
SetSDATA(0); // Set SDATA output/low
SetSCLK(0); // Set SCLK low
}
//------------------------------------------------------------------------------
// Routine: Stop
// Inputs: none
// Outputs: none
// Purpose: Sends I2C Stop Trasfer - "P"
//------------------------------------------------------------------------------
void INL Stop(void)
{
SetSDATA(0); // Set SDATA output/low
SetSCLK(1); // Set SCLK high
SetSDATA(1); // Set SDATA as input/high
}
//------------------------------------------------------------------------------
// Routine: Write
// Inputs: data_out
// Outputs: bool
// Purpose: Writes data over the I2C bus and return status.
//------------------------------------------------------------------------------
bool INL Write(unsigned char data_out)
{
unsigned char index;
// An I2C output byte is bits 7-0 (MSB to LSB). Shift one bit at a time to
// the SDATA output, and then clock the data to the I2C Slave device.
// Send 8 bits out the port
for(index = 0; index < 8; index++)
{
// Output the data bit to the device
SetSDATA(((data_out & 0x80) ? 1 : 0));
data_out <<= 1; // Shift the byte by one bit
SetSCLK(1); // Set SCLK high
SetSCLK(0); // Set SCLK low
}
SetSDATA(1); // Set SDATA input/high
SetSCLK(1); // Set SCLK high
if (!GetSDATA())
{
SetSCLK(0); // Set SCLK low
return true; // ACK from slave
} else
{
SetSCLK(0); // Set SCLK low
return false; // NACK from slave
}
}
//------------------------------------------------------------------------------
// Routine: Read
// Inputs: *data_in, send_ack (if true send the ACK signal else send NACK)
// Outputs: bool
// Purpose: Reads data from the I2C bus and return it in data_in.
// Returns status.
//------------------------------------------------------------------------------
bool INL Read(unsigned char *data_in, bool send_ack)
{
unsigned char index;
*data_in = 0x00;
SetSDATA(1); // Set SDATA input/high
SetSCLK(0); // Set SCLK low
// Get 8 bits from the device
for(index = 0; index < 8; index++)
{
*data_in <<= 1; // Shift the data right 1 bit
SetSCLK(1); // Set SCLK high
// 11182003 - Line moved...
// SetSCLK(0); // Set SCLK low
*data_in |= GetSDATA(); // Read the data bit
// 11182003 - to here! (Fixed thanks to Andrew Seddon).
SetSCLK(0); // Set SCLK low
}
if (send_ack)
SetSDATA(0); // Set data pin to output/low to ACK the read
else
SetSDATA(1); // Set data pin to input/high to NACK the read
SetSCLK(1); // Set SCLK high
SetSCLK(0); // Set SCLK low
SetSDATA(0); // Set SDATA output/low
SetSDATA(1); // Set SDATA input/high
return true;
}
//------------------------------------------------------------------------------
// Routine: SetSDATA
// Inputs: state
// Outputs: none
// Purpose: Set the I2C port SDATA pin to <state>.
//------------------------------------------------------------------------------
void INL SetSDATA(bool state)
{
unsigned int i, d;
if (state)
{
*pFIO0_DIR &= ~SDATA; // Set SDATA as input/high.
} else
{
*pFIO0_INEN = 0x0;
*pFIO0_FLAG_C = SDATA;
*pFIO0_DIR |= SDATA;
*pFIO0_FLAG_C = SDATA;// Set SDATA as output.
*pFIO0_INEN |= SDATA;
}
// Delay
for (i = 0; i < Delay; i++) { asm("nop;"); }
}
//------------------------------------------------------------------------------
// Routine: SetSCLK
// Inputs: state
// Outputs: none
// Purpose: Set the I2C port SCLK pin to <state>.
//------------------------------------------------------------------------------
void INL SetSCLK(bool state)
{
unsigned int i, d;
if (state)
{
*pFIO0_FLAG_D |= SCLK; // Set SCLK high.
} else
{
*pFIO0_FLAG_D &= ~SCLK; // Set SCLK low.
}
// Delay
for (i = 0; i < Delay; i++) { asm("nop;"); }
}
//------------------------------------------------------------------------------
// Routine: GetSDATA
// Inputs: none
// Outputs: bool
// Purpose: Get the I2C port SDATA pin state.
//------------------------------------------------------------------------------
bool INL GetSDATA()
{
return ((*pFIO0_FLAG_D & SDATA) ? 1 : 0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -