I2C_ISR_STATE()是PIC CCS编译器中PIC单片机的专有函数。
语法: state=i2c_isr_state( );
参数: 没有.
返回值: 返回值是一个8位整型.
0---接收地址匹配,R/W位被清除;
1~0x7F---主机已写数据;i2c_read()将立即返回这个数据;
0x80---接收地址匹配,R/W位被置1;同i2c_write()响应;
0x81~0xff---发送完成; i2c_write()响应应答.
功能: 在一个SSP中断之后,在i2c的从机方式里,该函数返回的是i2c通讯的状态,该返回值在每次发送或接收一个字节时,都会产生中断.
有效性: 适合带有i2c硬件的设备.
要求: 必须使用#use i2c,才可使能i2c_isr_state( );
例子: #INT_SSP //SPI口或I2C被激活,指出下面的函数是一个中断服务函数
void i2c_isr(){
state=i2c_isr_state();
if(state>=0x80)
i2c_write( send_buffer[state-0x80] );
else if(state>0)
rcv_buffer[state-1]=i2c_read();
}
例子文件: ex_slave.c
文件ex_slave.c如下:
#if defined(__PCM__) //若使用了PCM编译器,则defined( __PCM__)返回值为1
#include <16F877.h> //包含16F877.h头文件
#fuses HS, NOWDT, NOPROTECT, NOLVP //HS:高速晶振/谐振器, NOWDT:不使用WDT
// NOPROTECT:程序存储器代码不保护
#use delay(clock=20000000) //使能内置函数的功能:delay_ms()和delay_us()
//#USE DELAY()必须在#use rs232()使用之前出现.
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
//使用波特率为9600,
//发送脚为PIN_ C6
//接收脚为PIN_ C7
//使能内置函数:GETC,PUTC和PRINTF, kbhit();
#elif defined(__PCH__)
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 12
#endif //结束if定义
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0)
// SLAVE指定本机为从机方式
//除非指定了FORCE_HW,否则会产生模拟I2C的软件函数.
//使能I2C_START, I2C_STOP直到下一个#USE I2C的出现为止.
//使能I2C_READ, I2C_WRITE直到下一个#USE I2C的出现为止.
//使能I2C_POLL直到下一个#USE I2C的出现为止.
//指定SDA脚为PIN_C4, 指定SCL脚为PIN_C3;
// address指定从机方式的地址为0xa0;
typedef enum {NOTHING, CONTROL_READ,
ADDRESS_READ, READ_COMMAND_READ} I2C_STATE;
I2C_STATE fState;
BYTE address, buffer[0x10]; //声明字节变量address,数组buffer[0x10]
#INT_SSP //SPI口或I2C被激活,指出下面的函数是一个中断服务函数
void ssp_interupt ()
{
BYTE incoming; //声明字节变量incoming;
if (i2c_poll() == FALSE) { //若主机读本从机时, i2c_poll()返回FALSE值,执行下面的语句
if (fState == ADDRESS_READ) { //若已读到数据的地址, 则执行下面的语句
i2c_write (buffer[address]); //将指定地址(address)处的数据发给主机
fState = NOTHING; //为接收下一个数据的地址做准备
}
}
else { // 若SSP缓冲器接收到一个字节,i2c_poll()的返回值为TRUE,执行下面的语句
incoming = i2c_read();
//通过i2c口读一个字节(该字节可能是器件的地址,数据的地址或数据,也可能什么都不是)
if (fState == NOTHING){
fState = CONTROL_READ;
}
else if (fState == CONTROL_READ) {
address = incoming; //接收存放数据的地址
fState = ADDRESS_READ;
}
else if (fState == ADDRESS_READ) {
buffer[address] = incoming; //向address地址处写数据
fState = NOTHING;
}
}
}
void main ()
{
int i; //声明整型变量i;
fState = NOTHING; //给fState赋初值
address = 0x00; //给address赋初值
for (i=0;i<0x10;i++)
buffer[i] = 0x00; //给数组buffer[0x10] 赋初值
enable_interrupts(GLOBAL); //开总中断允许
enable_interrupts(INT_SSP); //SPI口或I2C中断允许位置1
while (TRUE) {} //循环等待中断
}
上面的程序用PIC从机方式来模拟EEPROM(24C01),只能向地址0x00~0x10写数据.