📄 maxqi2c.c
字号:
/*
* maxqi2c.c v0.1
*
* Author: Paul Holden
*
*/
#include "maxqi2c.h"
#include <intrinsics.h>
// At 20MHz, a NOP requires 50nS
#define NOP __no_operation()
// I2C Timing Info for 400KHz and 100KHz
#ifdef I2C_400_KHZ
#define I2C_WAIT_SU_STA /* 600nS*/_i2c_wait_600ns()
#define I2C_WAIT_HD_STA /* 600nS*/_i2c_wait_600ns()
#define I2C_WAIT_T_LOW /*1300ns*/_i2c_wait_1300ns()
#define I2C_WAIT_HD_DAT /* 300nS*/NOP;NOP;NOP;NOP;NOP;NOP
#define I2C_WAIT_SU_DAT /* 100nS*/NOP;NOP
#define I2C_WAIT_SU_STO /* 600nS*/_i2c_wait_600ns()
#define I2C_WAIT_T_HIGH /* 600nS*/_i2c_wait_600ns()
void _i2c_wait_600ns() {NOP;NOP;NOP;NOP;}
void _i2c_wait_1300ns() {NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;}
#else
#define I2C_WAIT_SU_STA /*4700nS*/_i2c_wait_4700ns()
#define I2C_WAIT_HD_STA /*4000nS*/_i2c_wait_4000ns()
#define I2C_WAIT_T_LOW /*4700ns*/_i2c_wait_4700ns()
#define I2C_WAIT_HD_DAT /*5000nS*/_i2c_wait_5000ns()
#define I2C_WAIT_SU_DAT /* 250nS*/NOP;NOP;NOP;NOP;NOP
#define I2C_WAIT_SU_STO /*4000nS*/_i2c_wait_4000ns()
#define I2C_WAIT_T_HIGH /*4000nS*/_i2c_wait_4000ns()
void _i2c_wait_4000ns() {volatile unsigned int i=0x04; do{i--;}while(i);}
void _i2c_wait_4700ns() {volatile unsigned int i=0x05; do{i--;}while(i);}
void _i2c_wait_5000ns() {volatile unsigned int i=0x05; do{i--;}while(i);}
#endif
/* Variables used for I2C driver */
__no_init volatile unsigned char *i2cData; // Pointer to I2C data
__no_init volatile unsigned int i2cDataLen; // I2C data length (not incl addr)
__no_init volatile unsigned char i2cDataAddr; // I2C address
__no_init volatile unsigned char i2cDataTerm; // I2C termination
__no_init volatile unsigned char ack; // acknowledge result
/* Prototypes for low-level I2C commands */
void _i2c_low_level_send_start ();
void _i2c_low_level_send_addr ();
void _i2c_low_level_send_dir_read ();
void _i2c_low_level_send_dir_write();
void _i2c_low_level_send_byte (unsigned char i2cByte);
unsigned char _i2c_low_level_recv_byte ();
void _i2c_low_level_recv_ack ();
void _i2c_low_level_send_ack ();
void _i2c_low_level_send_nack ();
void _i2c_low_level_send_rep_start();
void _i2c_low_level_send_stop ();
/*
* i2cInit() - see maxqi2c.h for documentation...
*/
void i2cInit()
{
SDA = 0;
SCL = 0;
SDA_PULLUP = 0;
SCL_PULLUP = 0;
}
/*
* i2cIsAddrPresent() - see maxqi2c.h for documentation...
*/
unsigned char i2cIsAddrPresent()
{
_i2c_low_level_send_start();
_i2c_low_level_send_addr();
_i2c_low_level_send_dir_write();
_i2c_low_level_recv_ack();
_i2c_low_level_send_stop();
return ack;
}
/*
* i2cSend() - see maxqi2c.h for documentation...
*/
unsigned char i2cSend()
{
__no_init unsigned int i;
// 1. Send addr
if (i2cDataAddr)
{
_i2c_low_level_send_start();
_i2c_low_level_send_addr();
_i2c_low_level_send_dir_write();
_i2c_low_level_recv_ack();
if (!ack)
{
_i2c_low_level_send_stop();
return I2C_XMIT_FAILED;
}
}
// 2. Send data
for(i=0x0000; i<i2cDataLen; i++)
{
_i2c_low_level_send_byte(i2cData[i]);
_i2c_low_level_recv_ack();
if (!ack)
{
_i2c_low_level_send_stop();
return I2C_XMIT_FAILED;
}
}
// 3. Send termination
if (i2cDataTerm == I2C_TERM_STOP)
_i2c_low_level_send_stop();
// 4. Return successful I2C transmit indicator
return I2C_XMIT_OK;
}
/*
* i2cRecv() - see maxqi2c.h for documentation...
*/
unsigned char i2cRecv()
{
__no_init unsigned int i;
// 1. Send addr
if (i2cDataAddr)
{
_i2c_low_level_send_start();
_i2c_low_level_send_addr();
_i2c_low_level_send_dir_read();
_i2c_low_level_recv_ack();
if (!ack)
{
_i2c_low_level_send_stop();
return I2C_XMIT_FAILED;
}
}
#ifdef I2C_CLOCK_STRETCHING
SCL = 0;
while (SCL_IN == 0);
#endif
// 2. Send data
if (i2cDataLen)
i2cData[0x0000] = _i2c_low_level_recv_byte();
for(i=0x0001; i<i2cDataLen; i++)
{
_i2c_low_level_send_ack();
i2cData[i] = _i2c_low_level_recv_byte();
}
// 3. Send termination
if (i2cDataTerm == I2C_TERM_ACK)
{
_i2c_low_level_send_ack();
}
else if (i2cDataTerm == I2C_TERM_NACK_AND_STOP)
{
_i2c_low_level_send_nack();
_i2c_low_level_send_stop();
}
// 4. Return successful I2C transmit indicator
return I2C_XMIT_OK;
}
/*
* _i2c_low_level_send_start() - LOW-LEVEL FUNCTION
*/
void _i2c_low_level_send_start()
{
SDA = 1;
I2C_WAIT_HD_STA;
SCL = 1;
}
/*
* _i2c_low_level_send_start() - LOW-LEVEL FUNCTION
*/
void _i2c_low_level_send_addr()
{
volatile unsigned char mask = 0x80;
do
{
I2C_WAIT_HD_DAT;
SDA = ((i2cDataAddr&mask)==0);
I2C_WAIT_SU_DAT;
SCL = 0;
I2C_WAIT_T_HIGH;
SCL = 1;
mask>>=1;
} while (mask!=0x0001);
}
/*
* _i2c_low_level_send_dir_read() - LOW-LEVEL FUNCTION
*/
void _i2c_low_level_send_dir_read()
{
I2C_WAIT_HD_DAT;
SDA = 0;
I2C_WAIT_SU_DAT;
SCL = 0;
I2C_WAIT_T_HIGH;
SCL = 1;
I2C_WAIT_T_LOW;
}
/*
* _i2c_low_level_send_dir_write() - LOW-LEVEL FUNCTION
*/
void _i2c_low_level_send_dir_write()
{
I2C_WAIT_HD_DAT;
SDA = 1;
I2C_WAIT_SU_DAT;
SCL = 0;
I2C_WAIT_T_HIGH;
SCL = 1;
SDA = 0;
I2C_WAIT_T_LOW;
}
/*
* _i2c_low_level_send_byte() - LOW-LEVEL FUNCTION
*/
void _i2c_low_level_send_byte(unsigned char i2cByte)
{
unsigned char mask = 0x80;
do
{
I2C_WAIT_HD_DAT;
SDA = ((i2cByte&mask)==0);
I2C_WAIT_SU_DAT;
SCL = 0;
I2C_WAIT_T_HIGH;
SCL = 1;
mask>>=1;
} while (mask!=0x0000);
}
/*
* _i2c_low_level_recv_byte() - LOW-LEVEL FUNCTION
*/
unsigned char _i2c_low_level_recv_byte()
{
unsigned char mask = 0x80;
ack = 0x00;
do
{
I2C_WAIT_HD_DAT;
I2C_WAIT_SU_DAT;
SCL = 0;
I2C_WAIT_T_HIGH;
ack += (SDA_IN)?mask:0;
SCL = 1;
mask>>=1;
} while (mask!=0x0000);
return ack;
}
/*
* _i2c_low_level_recv_ack() - LOW-LEVEL FUNCTION
*/
void _i2c_low_level_recv_ack()
{
SDA = 0;
SCL = 0;
I2C_WAIT_T_HIGH;
ack = (SDA_IN==0);
SCL = 1;
}
/*
* _i2c_low_level_send_ack() - LOW-LEVEL FUNCTION
*/
void _i2c_low_level_send_ack()
{
SDA = 1;
SCL = 0;
I2C_WAIT_T_HIGH;
SCL = 1;
SDA = 0;
}
/*
* _i2c_low_level_send_nack() - LOW-LEVEL FUNCTION
*/
void _i2c_low_level_send_nack()
{
SDA = 0;
SCL = 0;
I2C_WAIT_T_HIGH;
SCL = 1;
}
/*
* _i2c_low_level_send_rep_start() - LOW-LEVEL FUNCTION
*/
void _i2c_low_level_send_rep_start()
{
I2C_WAIT_SU_STA;
SDA = 1;
I2C_WAIT_HD_STA;
SCL = 1;
}
/*
* _i2c_low_level_send_stop() - LOW-LEVEL FUNCTION
*/
void _i2c_low_level_send_stop()
{
SDA = 1;
I2C_WAIT_T_LOW;
SCL = 0;
I2C_WAIT_SU_STO;
SDA = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -