//延时函数
static void I2c_Delay(uint8_t count)
{
uint8_t i;
for(i = 0;i < count;i++);
}
//读取SDA脚位状态
static uint8_t I2c_SDAStatus(void)
{
uint8_t SDA_Status;
SDA_Status = PB06_GETVALUE();
return SDA_Status?1:0;
}
//设置SDA脚为输出
void SDA_OutMode(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
GPIO_InitStructure.Pins = GPIO_PIN_6;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.IT = GPIO_IT_NONE;
GPIO_Init(CW_GPIOB,&GPIO_InitStructure);
}
//设置SDA脚为输入
void SDA_inputMode(uint8_t InputMode)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
GPIO_InitStructure.Pins = GPIO_PIN_6;
if(InputMode == 0)
{
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; //无下拉,只能输出低电平作ACK(2004特殊I2C协议,主机即作写数据又作ACK,最后一字节非ACK)
}
else
{
GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
}
GPIO_InitStructure.IT = GPIO_IT_NONE;
GPIO_Init(CW_GPIOB,&GPIO_InitStructure);
}
//I2C开始信号
void I2c_Start(void)
{
SDA_OutLow;
I2c_Delay(30);
SCL_OutLow;
I2c_Delay(30);
}
//I2C停止信号
void I2c_Stop(void)
{
SCL_OutLow;
I2c_Delay(30);
SDA_OutLow;
I2c_Delay(30);
SCL_OutHigh;
I2c_Delay(30);
SDA_OutHigh;
}
//等待(从机)应答
uint8_t I2c_WaitAck(uint8_t AckFlag)
{
uint8_t AckNack = 1;
if(AckFlag) //2004特殊I2C协议,主机即作写数据又作ACK,最后一字节非ACK
{
SDA_inputMode(0); //输入下拉,模拟假应答;主机写主机应答/非应答,从机2004识别
SDA_OutLow;
}
else
{
SDA_inputMode(0); //输入下拉,模拟假应答;主机写主机应答/非应答,从机2004识别
SDA_OutHigh;
}
I2c_Delay(12);
SCL_OutHigh;
I2c_Delay(30);
SCL_OutLow;
I2c_Delay(10);
SDA_OutMode();
I2c_Delay(5);
return AckNack;
}
//发送ACK
void I2c_SendAck(void)
{
SDA_OutLow;
I2c_Delay(30);
SCL_OutHigh;
I2c_Delay(30);
SCL_OutLow;
I2c_Delay(30);
}
//发送NACK
void I2c_SendNack(void)
{
SDA_OutHigh;
I2c_Delay(30);
SCL_OutHigh;
I2c_Delay(30);
SCL_OutLow;
I2c_Delay(30);
}
//写一个字节
void I2c_WriteByte(uint8_t Byte)
{
uint8_t i;
for(i = 0;i < 8;i++)
{
I2c_Delay(26);
I2c_Delay(6);
if(Byte&0x80)
{
SDA_OutHigh;
}
else
{
SDA_OutLow;
}
I2c_Delay(30);
SCL_OutHigh;
I2c_Delay(30);
SCL_OutLow;
Byte <<= 1;
}
SCL_OutLow;
I2c_Delay(5);
}
//读一个字节
uint8_t I2c_ReadByte(void)
{
uint8_t i,byte;
SDA_inputMode(0);
I2c_Delay(5);
for(i = 0;i < 8;i++)
{
byte <<= 1;
I2c_Delay(26);
if(I2c_SDAStatus())
{
byte |= 0x01;
}
I2c_Delay(26);
SCL_OutHigh;
I2c_Delay(26);
SCL_OutLow;
}
SDA_OutMode();
return byte;
}
//连续写多个字节
void I2c_WriteNbyte(uint8_t I2C_Addr,uint8_t* data,uint8_t len)
{
uint8_t j = 0;
I2c_Start();
I2c_WriteByte(I2C_Addr);
I2c_WaitAck(1);
for(j = 0;j < len;j++)
{
I2c_WriteByte(data[j]);
if(j < (len-1))
{
I2c_WaitAck(1); //2004特殊I2C协议,主机写,还得主机应答
}
else
{
I2c_WaitAck(0); //最后一个字节NACK
}
}
I2c_Stop();
}
//读取多个字节
void I2c_ReadNbyte(uint8_t I2C_Addr,uint8_t* buf,uint8_t len)
{
uint8_t j;
// I2C_Addr <<= 1;
I2c_Start();
I2c_WriteByte(I2C_Addr|0x01);
if(!I2c_WaitAck(1))
{
I2c_Stop();
return;
}
for(j = 0;j < len;j++)
{
buf[j] = I2c_ReadByte();
if(j != (len-1))
{
I2c_SendAck();
}
else
{
I2c_SendNack();
}
}
I2c_Delay(26);
I2c_Stop();
}
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_50707044/article/details/141259267
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_50707044/article/details/141259766
|