📄 i2c.h
字号:
/* I2C.H
Implements shared buffer via I2C
Wrapper (ex.):
#define i2cbuflen 20
#define i2c_addr 0xF0
setup_i2c(); enable_interrupts(INT_SSP);
*/
// ------------ I2C Variables --------------------
#DEFINE __I2C__
#use i2c(slave,sda=PIN_C4,scl=PIN_C3,address=i2c_addr,NOFORCE_SW)
typedef enum {NOTHING, CONTROL_READ,
ADDRESS_READ, READ_COMMAND_READ} I2C_STATE;
// I2C buffer is safe when fstate is NOTHING (at least)
#define wait_safe_i2c() while (fstate!=NOTHING) {} ;
I2C_STATE fState; // State of I2C communication
byte i2cadr; // I2c address and index in buffer
#IFNDEF exti2cbuf
byte i2cbuf[i2cbuflen]; // i2c buffer
#ENDIF
char* i2cidx; // i2c driver internal buffer to idx
int16 i2cscllow; // Count of i2c clock low - to avoid stuck i2c - call scl_stuck() in main loop.
#byte SSPCON = 0x14
#byte SSPCON2 = 0x91
#byte SSPSTAT = 0x94
// Bits interesting for interrupt routine
#define i2c_rd bit_test(SSPSTAT,2) /* Set when read operation */
#define i2c_s bit_test(SSPSTAT,3) /* Set when s received last */
#define i2c_p bit_test(SSPSTAT,4) /* Set when p received last */
#define i2c_ckp bit_test(SSPCON,4) /* reset when hw holds clk low */
#define i2c_data bit_test(SSPSTAT,5) /* Set when data (not address) operation */
#int_ssp
ssp_isr() {
char incoming;
i2cscllow=0; // Something received, scl did something, do not time out.
if (!i2c_poll()) { //i2c_poll() returns false on rw=1, read
if (i2c_ckp) fstate=NOTHING; else { i2c_write(*(i2cidx++)); fstate=ADDRESS_READ; }; // NAK - end or read more
} else {
incoming=i2c_read(); if (!i2c_data) fstate=NOTHING; // Here an address (write) was read.
if (fState == ADDRESS_READ) { *(i2cidx++) = incoming; return; } // More data to store
if (fState == NOTHING ) { i2cadr=incoming; fState = CONTROL_READ; return; } // The address of the PIC was read.
if (fState == CONTROL_READ) { i2cidx=&i2cbuf[0]+incoming; fState = ADDRESS_READ; return; } // Address to buffer in i2cidx
}
}
void setup_i2c() { // Initialize the I2c bus.
fState = NOTHING;
memset(i2cbuf,0,sizeof(i2cbuf)); // Start all zero
i2cscllow=0;
}
int16 scl_stuck() { // returns number of calls of itself with scl found low and no chars received
if (input(PIN_C3)) i2cscllow=0; else i2cscllow++; // Poll I2c to see if stuck
return i2cscllow;
}
void i2c_flush() { // Clears the i2c input buffer. Should be called before mainloop to prevent stuck interrupts.
if (i2c_poll()) i2c_read();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -