124 lines
2.6 KiB
C
124 lines
2.6 KiB
C
#include "iic.h"
|
||
|
||
|
||
// 延时函数(2us)
|
||
void IIC_Delay(void) {
|
||
// 软件延时
|
||
// _nop_();_nop_();_nop_();_nop_();_nop_();// 30个nop约1us@30MHz
|
||
// _nop_();_nop_();_nop_();..............
|
||
|
||
DelayUs(1);
|
||
}
|
||
void IIC_Init(void) {
|
||
// 配置P2.6和P2.7为开漏模式
|
||
P2M1 |= 0xC0; // 1100 0000
|
||
P2M0 |= 0xC0; // 开漏模式
|
||
SDA = 1;
|
||
SCL = 1;
|
||
}
|
||
|
||
void IIC_Start(void) {
|
||
SDA = 1;
|
||
SCL = 1;
|
||
IIC_Delay();
|
||
SDA = 0;
|
||
IIC_Delay();
|
||
SCL = 0;
|
||
}
|
||
|
||
void IIC_Stop(void) {
|
||
SDA = 0;
|
||
SCL = 1;
|
||
IIC_Delay();
|
||
SDA = 1;
|
||
IIC_Delay();
|
||
}
|
||
|
||
void IIC_SendByte(u8 dat) {
|
||
u8 i;
|
||
for(i=0; i<8; i++) {
|
||
SDA = (dat & 0x80) ? 1 : 0;
|
||
dat <<= 1;
|
||
IIC_Delay();
|
||
SCL = 1;
|
||
IIC_Delay();
|
||
SCL = 0;
|
||
}
|
||
}
|
||
|
||
u8 IIC_RecvByte(void) {
|
||
u8 i, dat = 0;
|
||
SDA = 1; // 释放数据线
|
||
for(i=0; i<8; i++) {
|
||
dat <<= 1;
|
||
SCL = 1;
|
||
IIC_Delay();
|
||
if(SDA) dat |= 0x01;
|
||
SCL = 0;
|
||
IIC_Delay();
|
||
}
|
||
return dat;
|
||
}
|
||
|
||
bit IIC_WaitAck(void) {
|
||
SDA = 1; // 主机释放SDA
|
||
IIC_Delay();
|
||
SCL = 1;
|
||
IIC_Delay();
|
||
if(SDA) { // 检测SDA状态
|
||
SCL = 0;
|
||
return 0; // 无ACK
|
||
} else {
|
||
SCL = 0;
|
||
return 1; // 收到ACK
|
||
}
|
||
}
|
||
|
||
void IIC_SendAck(bit ack) {
|
||
SDA = ack ? 0 : 1;
|
||
IIC_Delay();
|
||
SCL = 1;
|
||
IIC_Delay();
|
||
SCL = 0;
|
||
SDA = 1; // 释放SDA
|
||
}
|
||
|
||
/**
|
||
* @brief I²C连续写入多个字节数据
|
||
* @param devAddr : 从机地址(7位地址,左对齐)
|
||
* @param regAddr : 寄存器地址
|
||
* @param pData : 待写入数据缓冲区
|
||
* @param len : 数据长度
|
||
* @retval 写入状态:1-成功,0-失败
|
||
*/
|
||
bit IIC_WriteBytes(u8 devAddr, u8 regAddr, u8 *pData, u8 len) {
|
||
IIC_Start(); // 启动I²C通信[6](@ref)
|
||
|
||
// 发送设备地址(写模式)
|
||
IIC_SendByte(devAddr & 0xFE); // 7位地址+写位(0)
|
||
if (!IIC_WaitAck()) { // 检测从机应答
|
||
IIC_Stop();
|
||
return 0; // 无应答则终止[2](@ref)
|
||
}
|
||
|
||
// 发送寄存器地址
|
||
IIC_SendByte(regAddr);
|
||
if (!IIC_WaitAck()) {
|
||
IIC_Stop();
|
||
return 0; // 寄存器地址无应答
|
||
}
|
||
|
||
// 循环发送数据字节
|
||
while (len--) {
|
||
IIC_SendByte(*pData++); // 发送当前字节
|
||
if (!IIC_WaitAck()) { // 检测数据应答
|
||
IIC_Stop();
|
||
return 0; // 数据写入失败
|
||
}
|
||
}
|
||
|
||
IIC_Stop(); // 结束通信[6](@ref)
|
||
return 1; // 写入成功
|
||
}
|
||
|