Files
JYF_STC15W4K_wireless_charge/Driver/iic.c

214 lines
4.4 KiB
C
Raw Normal View History

2025-03-18 19:34:19 +08:00
#include "iic.h"
// 延时函数1us
2025-03-18 22:14:15 +08:00
void
IIC_Delay (void)
{
// 软件延时
// _nop_();_nop_();_nop_();_nop_();_nop_();// 30个nop约1us@30MHz
// _nop_();_nop_();_nop_();..............
DelayUs (1);
2025-03-18 19:34:19 +08:00
}
2025-03-18 22:14:15 +08:00
void
IIC_Init (void)
{
// 配置P2.6和P2.7为开漏模式
P2M1 |= 0xC0; // 1100 0000
P2M0 |= 0xC0; // 开漏模式
SDA = 1;
SCL = 1;
2025-03-18 19:34:19 +08:00
}
2025-03-18 22:14:15 +08:00
void
IIC_Start (void)
{
SDA = 1;
SCL = 1;
IIC_Delay ();
SDA = 0;
IIC_Delay ();
SCL = 0;
2025-03-18 19:34:19 +08:00
}
2025-03-18 22:14:15 +08:00
void
IIC_Stop (void)
{
SDA = 0;
SCL = 1;
IIC_Delay ();
SDA = 1;
IIC_Delay ();
2025-03-18 19:34:19 +08:00
}
2025-03-18 22:14:15 +08:00
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;
2025-03-18 19:34:19 +08:00
}
}
2025-03-18 22:14:15 +08:00
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 ();
2025-03-18 19:34:19 +08:00
}
2025-03-18 22:14:15 +08:00
return dat;
2025-03-18 19:34:19 +08:00
}
2025-03-18 22:14:15 +08:00
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
2025-03-18 19:34:19 +08:00
}
}
/**
* @brief IIC协议中的确认信号
*
* SDA线SCL线ACKNACK
* IIC通信中ACK请求SDA线来响应
*
* @param ack bit类型的变量ack为1时发送ACKack为0时发送NACK
*/
void IIC_SendAck (bit ack)
2025-03-18 22:14:15 +08:00
{
// 根据ack参数决定SDA线的电平1发送ACK0发送NACK
2025-03-18 22:14:15 +08:00
SDA = ack ? 0 : 1;
IIC_Delay(); // 等待一段时间,确保电平稳定
SCL = 1; // 拉高SCL线允许数据传输
IIC_Delay(); // 再次等待,确保时钟脉冲宽度
SCL = 0; // 拉低SCL线结束当前时钟周期
SDA = 1; // 释放SDA线准备下一次通信
2025-03-18 19:34:19 +08:00
}
/**
2025-03-18 22:14:15 +08:00
* @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)
2025-03-18 19:34:19 +08:00
}
2025-03-18 22:14:15 +08:00
// 发送寄存器地址
IIC_SendByte (regAddr);
if (!IIC_WaitAck ())
{
IIC_Stop ();
return 0; // 寄存器地址无应答
2025-03-18 19:34:19 +08:00
}
2025-03-18 22:14:15 +08:00
// 循环发送数据字节
while (len--)
{
IIC_SendByte (*pData++); // 发送当前字节
if (!IIC_WaitAck ())
{ // 检测数据应答
IIC_Stop ();
return 0; // 数据写入失败
2025-03-18 19:34:19 +08:00
}
}
2025-03-18 22:14:15 +08:00
IIC_Stop (); // 结束通信[6](@ref)
return 1; // 写入成功
2025-03-18 19:34:19 +08:00
}
2025-03-18 22:14:15 +08:00
/**
* @brief I²C连续读取多个字节数据
* @param devAddr : 7
* @param regAddr :
* @param pData :
* @param len :
* @retval 1-0-
*/
bit
IIC_ReadBytes (u8 devAddr, u8 regAddr, u8 *pData, u8 len)
{
IIC_Start (); // 启动I²C通信
// 发送设备地址(写模式)
IIC_SendByte (devAddr & 0xFE); // 7位地址+写位(0)
if (!IIC_WaitAck ())
{ // 检测从机应答
IIC_Stop ();
return 0; // 无应答则终止
}
// 发送寄存器地址
IIC_SendByte (regAddr);
if (!IIC_WaitAck ())
{
IIC_Stop ();
return 0; // 寄存器地址无应答
}
// 重新启动I²C通信重复启动
IIC_Start ();
// 发送设备地址(读模式)
IIC_SendByte (devAddr | 0x01); // 7位地址+读位(1)
if (!IIC_WaitAck ())
{ // 检测从机应答
IIC_Stop ();
return 0; // 无应答则终止
}
// 循环读取数据字节
while (len--)
{
*pData++ = IIC_RecvByte (); // 接收当前字节
if (len > 0)
{
IIC_SendAck (1); // 发送ACK
}
else
{
IIC_SendAck (0); // 发送NACK
}
}
IIC_Stop (); // 结束通信
return 1; // 读取成功
}