📄 m_i2c_1.c
字号:
//*************************************************************************
// m_i2c_1.c
// Version 1.00
//
// Mikes simple software driven I2C routine - hopefully done for compactness.
// Master Only mode - output only in this version
//
// Author: Michael Pearce
// Chemistry Department, University of Canterbury
//
// Started: 2 June 1999
//
//*************************************************************************
// Version 1.1.0 - 15 June 2000
// Added I2C_Read and i2cgetbyte routines - hope they work
//*************************************************************************
// Version 1.0.0 - 2 June 1999
// Single routine to write data to i2c
//*************************************************************************
//******** REQUIRED DEFINES ***********
// #define BITNUM(adr, bit) ((unsigned)(&adr)*8+(bit))
// static bit SCL @ BITNUM(PORTA,0) //-- The SCL output pin
// #define SCL_TRIS //-- The SCL Direction Register Bit
// #define SDA //-- The SDA output pin
// #define SDA_TRIS //-- The SDA Direction Register Bit
// #define XTAL_FREQ 8MHZ //-- Define the crystal frequency
#define I2CLOW 0 //-- Puts pin into output/low mode
#define I2CHIGH 1 //-- Puts pin into Input/high mode
#ifndef MHZ
#define MHZ *1000 /* number of kHz in a MHz */
#endif
#ifndef KHZ
#define KHZ *1 /* number of kHz in a kHz */
#endif
//********* I2C Bus Timing - uS ************
#define I2CSTARTDELAY 50
#define I2CSTOPDELAY 50
#define I2CDATASETTLE 20
#define I2CCLOCKHIGH 100
#define I2CHALFCLOCK 50
#define I2CCLOCKLOW 100
#define I2CACKWAITMIN 50
//********************* FUNCTIONS ************************
char I2C_Send(char Address,char *Data,char Num);
char I2C_Read(char Address,char *Data,char Num);
char i2csendbyte(char byte);
char i2cgetbyte(void);
char i2cgetack(void);
void i2csendack(void);
void i2cdelay(char delay);
void i2cstart(void);
void i2cstop(void);
void i2cclock(void);
char i2creadbit(void);
//*************************************************************************
// I2C_Send
//
// Inputs:
// char Address - Address to write data to
// char *Data - Pointer to buffer
// char Num - Number of bytes to send
//*************************************************************************
char I2C_Send(char Address,char *Data,char Num)
{
i2cstart();
//-- Send Address
i2csendbyte(Address & 0xFE); //-- Lowest bit = 0 => WRITE
if(!i2cgetack())
{
i2cstop();
return(0);
}
while(Num--)
{
i2csendbyte(*Data);
if(!i2cgetack())
{
i2cstop();
return(0);
}
Data++;
}
i2cstop();
return(1);
}
//************** END OF I2C_Send
//*************************************************************************
// char I2C_Read(char Address,char *data, char Num)
//*************************************************************************
char I2C_Read(char Address,char *Data, char Num)
{
i2cstart();
//-- Send Address
i2csendbyte(Address | 0x01); //-- Lowest bit = 1 => READ
if(!i2cgetack())
{
i2cstop();
return(0);
}
while(Num--)
{
*Data=i2cgetbyte();
Data++;
if(Num > 0)
{
i2csendack();
}
}
i2cstop();
return(1);
}
//*************************************************************************
// i2csendbyte
//*************************************************************************
char i2csendbyte(char Byte)
{
char count;
SDA=I2CLOW;
SCL=I2CLOW;
i2cdelay(I2CCLOCKLOW); //-- Minimum Clock Low Time
for(count=8;count>0;count--) //-- Send 8 bits of data
{
if( (Byte & 0x80)== 0) //-- Get the Bit
{
SDA=I2CLOW; //-- Ensure Port pin is low
SDA_TRIS=I2CLOW; //-- Lower pin if bit = 0
}
else
{
SDA_TRIS=I2CHIGH; //-- Release pin if bit = 1
}
Byte=Byte<<1; //-- Shift next bit into position
i2cclock(); //-- Pulse the clock
}
SDA_TRIS=I2CHIGH; //-- Release data pin for ACK
return(1);
}
//************** END OF i2csendbyte
//*************************************************************************
// char i2cgetbyte(void)
//
// Reads in a byte from the I2C Port
//*************************************************************************
char i2cgetbyte(void)
{
char count,Byte=0;
SDA=I2CLOW;
SCL=I2CLOW;
i2cdelay(I2CCLOCKLOW); //-- Minimum Clock Low Time
for(count=8;count>0;count--) //-- Read 8 bits of data
{
Byte=Byte <<1;
SDA_TRIS=I2CHIGH; //-- Release pin so data can be recieved
if(i2creadbit())
{
Byte +=1;
}
}
return(Byte);
}
//*************************************************************************
// i2cstart
//*************************************************************************
void i2cstart(void)
{
//-- Ensure pins are in high impedance mode --
SDA_TRIS=I2CHIGH;
SCL_TRIS=I2CHIGH;
SCL=I2CLOW;
SDA=I2CLOW;
i2cdelay(I2CSTARTDELAY);
//-- Generate the start condition
SDA_TRIS=I2CLOW;
SDA=I2CLOW;
i2cdelay(I2CSTARTDELAY);
SCL_TRIS=I2CLOW;
i2cdelay(I2CCLOCKLOW); //-- Minimum Clock Low Time
}
//************** END OF i2cstart
//*************************************************************************
// i2cstop
//*************************************************************************
void i2cstop(void)
{
//-- Generate Stop Condition --
SDA_TRIS=I2CLOW;
SCL_TRIS=I2CHIGH;
i2cdelay(I2CSTOPDELAY);
SDA_TRIS=I2CHIGH;
}
//************** END OF i2cstop
//*************************************************************************
// i2cclock
//*************************************************************************
void i2cclock(void)
{
i2cdelay(I2CDATASETTLE); //-- Minimum Clock Low Time
SCL_TRIS=I2CHIGH; //-- Release clock
i2cdelay(I2CCLOCKHIGH); //-- Minimum Clock High Time
SCL_TRIS=I2CLOW; //-- Lower the clock
i2cdelay(I2CCLOCKLOW); //-- Minimum Clock Low Time
}
//************** END OF i2cclock
//*************************************************************************
// i2creadbit
//*************************************************************************
char i2creadbit(void)
{
char Data=0;
i2cdelay(I2CDATASETTLE); //-- Minimum Clock Low Time
SCL_TRIS=I2CHIGH; //-- Release clock
i2cdelay(I2CHALFCLOCK); //-- 1/2 Minimum Clock High Time
if(SDA !=0 ) Data=1; //-- READ in the data bit
i2cdelay(I2CHALFCLOCK); //-- 1/2 Minimum Clock High Time
SCL_TRIS=I2CLOW; //-- Lower the clock
i2cdelay(I2CCLOCKLOW); //-- Minimum Clock Low Time
return(Data);
}
//************** END OF i2cclock
//*************************************************************************
// i2cgetack
//*************************************************************************
char i2cgetack(void)
{
SDA=I2CLOW;
SCL=I2CLOW;
SCL_TRIS=I2CLOW; //-- Ensure clock is low
SDA_TRIS=I2CHIGH; //-- Release the Data pin so slave can ACK
SCL_TRIS=I2CHIGH; //-- raise the clock pin
i2cdelay(I2CHALFCLOCK); //-- wait for 1/2 the clock pulse
if(SDA) //-- sample the ACK signal
{
return(0); //-- No ACK so return BAD
}
i2cdelay(I2CHALFCLOCK); //-- Else wait for rest of clock
SCL_TRIS=I2CLOW; //-- Finish the clock pulse
i2cdelay(I2CCLOCKLOW); //-- Minimum Clock Low Time
i2cdelay(I2CCLOCKLOW); //-- Minimum Clock Low Time
return(1);
}
//************** END OF i2cgetack
//*************************************************************************
// void i2csendack(void)
//*************************************************************************
void i2csendack(void)
{
//--- Send Ack to slave except for last time ---
SDA=0;
SDA_TRIS=I2CLOW; //-- Send ACK
i2cdelay(I2CDATASETTLE); //-- Give it time to settle
i2cclock(); //-- Pulse the clock
SDA_TRIS=I2CHIGH; //-- Release ACK
i2cdelay(I2CDATASETTLE); //-- Gap between next byte
}
//************** END OF i2csendack
//*************************************************************************
// i2cdelay
//
// This delay is approx us plus the function call delays
// Should be close enough for I2C
//*************************************************************************
void i2cdelay(const char delay)
{
DelayUs(delay);
// DelayMs(delay); //-- For Debug
}
//************** END OF i2cdelay
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -