📄 i2c.c
字号:
//===================================================================
// 文件名称: i2c.c
//===================================================================
#define I2C_SCL PIN_C0
#define I2C_SDA PIN_C1
//------------------- 私有宏定义 开始-------------------------
#define I2CWAIT8 delay_us(8)
#define I2CWAIT4 delay_us(5)
//#define EMAX_POLL 10 // Maximum nunber of polls
#define EMAX_POLL 0x96 // Maximum nunber of polls
//------------------- 私有宏定义 结束-------------------------
//===================================================================
//= 函数原型: void i2c_start()
//= 参 数: 无
//= 返 回 值: 无
//= 功 能: 提供I2C总线工作时序中的起始位
//= 函数性质: 私有函数
//= SDA ----_____
//= I2C_SCL ------____
//===================================================================
void i2c_start()
{
output_high(I2C_SDA);
I2CWAIT8;
output_high(I2C_SCL);
I2CWAIT8;
output_low(I2C_SDA);
I2CWAIT4;
output_low(I2C_SCL);
I2CWAIT4;
}
//===================================================================
//= 函数原型: void i2c_stop()
//= 参 数: 无
//= 返 回 值: 发送停止位后DSA线的状态 是'低'则返回
//= 功 能: 提供I2C总线工作时序中的停止位
//= 函数性质: 私有函数
//= SDA ______----
//= I2C_SCL ___-------
//===================================================================
void i2c_stop()
{
// int8 i;
output_low(I2C_SDA);
I2CWAIT4;
output_high(I2C_SCL);
I2CWAIT8;
output_high(I2C_SDA);
I2CWAIT4;
// i = SDA; // Put port pin into HiZ
}
//===================================================================
//= 函数原型: bit i2c_clock()
//= 参 数: 无
//= 返 回 值: 在时钟电平为高期间SDA信号线上的状态
//= 功 能: 提供I2C总线的时钟信号,并返回在时钟电平为高期间SDA
//= 信号线上的状态.本函数可用于数据发送或数据接收
//= 函数性质: 私有函数
//===================================================================
int1 i2c_clock()
{
int1 sample;
output_high(I2C_SCL);
I2CWAIT8;
sample = input(I2C_SDA);
output_low(I2C_SCL);
return(sample);
}
//===================================================================
//= 函数原型: bit i2c_send_8bit(int8 I_data)
//= 参 数: I_data 写入 EEPROM 8_bit
//= 返 回 值: 如果收到应答信号返回TRUE 否则返回FALSE
//= 功 能: 向I2C总线发送8位数据,并请求一个应答信号ACK
//= 函数性质: 私有函数
//===================================================================
int1 i2c_send_8bit(int8 I_data)
{
int8 i;
int1 test_bit;
set_tris_c(0x00); // I2C_SDA output
I2CWAIT4;
for (i=0;i<8;i++)
{
output_bit(I2C_SDA, bit_test(I_data,7));
I_data <<= 1;
I2CWAIT4;
i2c_clock();
I2CWAIT4;
}
// output_high(I2C_SDA); // 请求应答信号ACK
set_tris_c(0x02); // I2C_SDA input
test_bit=i2c_clock();
set_tris_c(0x00); // I2C_SDA input
return(~test_bit); // 如果收到应答信号返回1 否则返回0
}
//===================================================================
//= 函数原型: int8 i2c_receive_8bit(bit ack)
//= 参 数: 应答信号 0/1(仅在最后一个字节时ACK为1)
//= 返 回 值: I2C总线上收到的一个字节
//= 功 能: 从I2C总线上接收8位数据信号,并将收到的8位数据作为一个字节返回
//= 函数性质: 私有函数
//===================================================================
int8 i2c_receive_8bit(int1 ack)
{
int8 I_data = 0;
int8 i;
/*
SDA = 1;
for (i=0;i<8;i++)
{
I2CWAIT8;
I_data <<= 1; // '高位在前读数据'经典'
if (i2c_clock())
I_data++;
}
I2CWAIT4;
SDA = ack; // 发送应答信号
i2c_clock();
return(I_data);
*/
set_tris_c(0x02); // I2C_SDA input
delay_cycles(1);
for(i=0;i<8;i++)
{
I2CWAIT8;
I_data <<= 1; // '高位在前读数据'经典'
if (i2c_clock())
I_data++;
}
I2CWAIT4;
set_tris_c(0x00); // I2C_SDA output
delay_cycles(1);
output_bit(I2C_SDA,ack); // 发送应答信号
i2c_clock();
return(I_data);
}
//===================================================================
//= 函数原型: bit i2c_pkt_write(u_int addr,int8 *s,int8 size)
//= 参 数: ipw_ch:器件地址 ipw_addr:单元地址 *s写数据指针 size:写入数据的个数
//= 返 回 值: 写数据成功返回'TRUE',否则返回'FALSE'
//= 功 能: 从启动总线到发送地址,数据,结束总线的全过程
//= 函数性质: 公有函数
//===================================================================
int1 i2c_pkt_write(int8 ipw_ch,int8 ipw_addr,int8 *s,int8 size)
{
int8 i;
// int8 *buf_pt = s;
// int8 *buf_pt;
// buf_pt = s;
if (size == 0) return FALSE;
for (i=EMAX_POLL;;)
{
i2c_start();
if (i2c_send_8bit(ipw_ch)==TRUE) // 送器件地址,同时检查是否连接
break; // receive ACK => write finished
i2c_stop();
if (--i == 0) // Try it 1msec
return FALSE; // 等待1msec 还没有写完则返回出错
}
i2c_send_8bit(ipw_addr);
do {
i2c_send_8bit(*s);
s++;
} while (--size);
i2c_stop();
}
//===================================================================
//= 函数原型: bit i2c_pkt_read(int8 ipw_ch,int8 ipw_addr,int8 *s,int8 size)
//= 参 数: addr:EEPROM地址 *s:读数据指针 size:读数据的个数
//= 返 回 值: 读数据成功返回'TRUE',否则返回'FALSE'
//= 功 能: 从启动总线到发送地址,读数据,结束总线的全过程
//= 函数性质: 公有函数
//===================================================================
int1 i2c_pkt_read(int8 ipw_ch,int8 ipw_addr,int8 *s,int8 size)
{
// int8 *buf_pt = s;
// int8 *buf_pt;
int1 ack;
// buf_pt= s;
if (size == 0) return FALSE;
i2c_start();
if (i2c_send_8bit(ipw_ch)==FALSE) { // 送器件地址,同时检查是否连接
i2c_stop();
return FALSE;
}
i2c_send_8bit(ipw_addr);
i2c_stop();
i2c_start();
i2c_send_8bit(ipw_ch+1); // 送读命令
for (;;)
{
ack = --size; // last byte or last in page
*s = i2c_receive_8bit(!ack); // NACK on last byte
s++;
if (!ack) break; // 正常情况下ACK应该是1
}
i2c_stop();
return TRUE;
}
//======================= 函数原型定义完毕 ==========================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -