测试最后一次是否需要Ack/Nak

This commit is contained in:
大石头 2017-04-07 13:17:51 +08:00
parent 8ff176ec09
commit 168203cf1a
4 changed files with 45 additions and 42 deletions

View File

@ -58,7 +58,7 @@ bool I2C::SendAddress(int addr, bool tx)
ushort d = (tx || SubWidth > 0) ? Address : (Address | 0x01);
//debug_printf("I2C::SendAddr %02X \r\n", d);
WriteByte((byte)d);
if (!WaitAck())
if (!WaitAck(true))
{
debug_printf("I2C::SendAddr %02X 可能设备未连接,或地址不对\r\n", d);
return false;
@ -83,7 +83,7 @@ bool I2C::SendAddress(int addr, bool tx)
{
Start();
WriteByte((byte)d);
rs = WaitAck();
rs = WaitAck(true);
}
if (!rs)
{
@ -105,7 +105,7 @@ bool I2C::SendSubAddr(int addr)
for (int k = SubWidth - 1; k >= 0; k--)
{
WriteByte(addr >> (k << 3));
if (!WaitAck()) return false;
if (!WaitAck(true)) return false;
}
}
@ -130,9 +130,9 @@ WEAK bool I2C::Write(int addr, const Buffer& bs)
{
WriteByte(bs[i]);
// 最后一次不要等待Ack
//if (i < len - 1 && !WaitAck()) return false;
if (!WaitAck(i < len - 1)) return false;
// EEPROM上最后一次也要等Ack否则错乱
if (!WaitAck()) return false;
//if (!WaitAck()) return false;
}
return true;
@ -239,6 +239,9 @@ void HardI2C::GetPin(Pin* scl, Pin* sda)
if (sda) *sda = SDA._Pin;
}
/******************************** SoftI2C ********************************/
// 3种速率可选择 标准模式100kbps、快速模式400kbps、最高速率3.4Mbps
SoftI2C::SoftI2C(uint speedHz) : I2C()
{
Speed = speedHz;
@ -308,7 +311,7 @@ void SoftI2C::OnClose()
SDA.Close();
}
void SoftI2C::Delay(int us)
void SoftI2C::Delay()
{
//Sys.Delay(us);
@ -337,10 +340,10 @@ void SoftI2C::Start()
// 下降沿
SDA = true;
Delay(1);
Delay();
SDA = false;
Delay(1);
Delay();
SCL = false;
}
@ -355,25 +358,25 @@ void SoftI2C::Stop()
// 在SCL高电平期间SDA产生上升沿
SCL = false;
SDA = false;
Delay(1);
Delay();
SCL = true;
Delay(1);
Delay();
SDA = true;
}
// 等待Ack
bool SoftI2C::WaitAck(int retry)
bool SoftI2C::WaitAck(bool ack)
{
if (!retry) retry = Retry;
int retry = Retry;
// SDA 线上的数据必须在时钟的高电平周期保持稳定
SDA = true;
SDA = ack;
SCL = true;
Delay(1);
Delay();
// 等待SDA低电平
while (SDA.ReadInput())
while (SDA.ReadInput() == ack)
{
if (retry-- <= 0)
{
@ -383,7 +386,7 @@ bool SoftI2C::WaitAck(int retry)
}
SCL = false;
Delay(1);
Delay();
return true;
}
@ -397,8 +400,8 @@ bool SoftI2C::WaitAck(int retry)
I2C 线
0 ACKA1 NACKA
LSB SDA 线SDA
LSB SDA 线SDA
*/
void SoftI2C::Ack(bool ack)
{
@ -406,14 +409,14 @@ void SoftI2C::Ack(bool ack)
SCL = false;
SDA = !ack;
Delay(1);
Delay();
SCL = true;
Delay(1);
Delay();
SCL = false;
SDA = true;
Delay(1);
Delay();
}
void SoftI2C::WriteByte(byte dat)
@ -423,13 +426,13 @@ void SoftI2C::WriteByte(byte dat)
for (byte mask = 0x80; mask > 0; mask >>= 1)
{
SDA = (dat & mask) > 0;
Delay(1);
Delay();
// 置时钟线为高,通知被控器开始接收数据位
SCL = true;
Delay(1);
Delay();
SCL = false;
Delay(1);
Delay();
}
}
@ -447,12 +450,12 @@ byte SoftI2C::ReadByte()
while (!SCL.ReadInput())
{
if (retry-- <= 0) break;
Delay(1);
Delay();
}
if (SDA.ReadInput()) rs |= mask; //读数据位
SCL = false; // 置时钟线为低,准备接收数据位
Delay(1);
Delay();
}
return rs;

View File

@ -33,8 +33,8 @@ public:
virtual void WriteByte(byte dat) = 0; // 写入单个字节
virtual byte ReadByte() = 0; // 读取单个字节
virtual void Ack(bool ack) = 0;
virtual bool WaitAck(int retry = 0) = 0; // 等待Ack默认0表示采用全局Retry
virtual void Ack(bool ack) = 0; // 发送Ack/Nak
virtual bool WaitAck(bool ack) = 0; // 等待Ack/Nak
// 新会话向指定地址写入
bool Write(int addr, const Buffer& bs);
@ -93,7 +93,7 @@ public:
virtual void WriteByte(byte dat);
virtual byte ReadByte();
virtual void Ack(bool ack);
virtual bool WaitAck(int retry=0); // 等待Ack默认0表示采用全局Retry
virtual bool WaitAck(bool ack);
//virtual bool Write(int addr, byte* buf, uint len); // 新会话向指定地址写入多个字节
//virtual uint Read(int addr, byte* buf, uint len); // 新会话从指定地址读取多个字节
@ -131,8 +131,8 @@ public:
virtual void WriteByte(byte dat);
virtual byte ReadByte();
virtual void Ack(bool ack = true);
virtual bool WaitAck(int retry=0);
virtual void Ack(bool ack);
virtual bool WaitAck(bool ack);
private:
int _delay; // 根据速度匹配的延时
@ -143,7 +143,7 @@ private:
virtual bool OnOpen();
virtual void OnClose();
void Delay(int us);
void Delay();
};
/*

View File

@ -102,7 +102,7 @@ void HardI2C::Start()
I2C_GenerateSTART(iic, ENABLE);
_Event = I2C_EVENT_MASTER_MODE_SELECT;
WaitAck();
WaitAck(true);
}
void HardI2C::Stop()
@ -119,9 +119,9 @@ void HardI2C::Ack(bool ack)
I2C_AcknowledgeConfig((I2C_TypeDef*)_IIC, ack ? ENABLE : DISABLE);
}
bool HardI2C::WaitAck(int retry)
bool HardI2C::WaitAck(bool ack)
{
if(!retry) retry = Retry;
int retry = Retry;
while(!I2C_CheckEvent((I2C_TypeDef*)_IIC, _Event))
{
if(--retry <= 0) return ++Error; // 超时处理
@ -138,7 +138,7 @@ bool HardI2C::SendAddress(int addr, bool tx)
I2C_Send7bitAddress(iic, Address, I2C_Direction_Transmitter);
_Event = I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED;
if(!WaitAck()) return false;
if(!WaitAck(true)) return false;
_Event = I2C_EVENT_MASTER_BYTE_TRANSMITTED;
return I2C::SendSubAddr(addr);
@ -158,7 +158,7 @@ bool HardI2C::SendAddress(int addr, bool tx)
I2C_Send7bitAddress(iic, Address, I2C_Direction_Receiver);
_Event = I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED;
if(!WaitAck()) return false;
if(!WaitAck(true)) return false;
return true;
}

View File

@ -102,7 +102,7 @@ void HardI2C::Start()
I2C_GenerateSTART(iic, ENABLE);
_Event = I2C_EVENT_MASTER_MODE_SELECT;
WaitAck();
WaitAck(true);
}
void HardI2C::Stop()
@ -119,9 +119,9 @@ void HardI2C::Ack(bool ack)
I2C_AcknowledgeConfig((I2C_TypeDef*)_IIC, ack ? ENABLE : DISABLE);
}
bool HardI2C::WaitAck(int retry)
bool HardI2C::WaitAck(bool ack)
{
if(!retry) retry = Retry;
int retry = Retry;
while(!I2C_CheckEvent((I2C_TypeDef*)_IIC, _Event))
{
if(--retry <= 0) return ++Error; // 超时处理
@ -138,7 +138,7 @@ bool HardI2C::SendAddress(int addr, bool tx)
I2C_Send7bitAddress(iic, Address, I2C_Direction_Transmitter);
_Event = I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED;
if(!WaitAck()) return false;
if(!WaitAck(true)) return false;
_Event = I2C_EVENT_MASTER_BYTE_TRANSMITTED;
return I2C::SendSubAddr(addr);
@ -158,7 +158,7 @@ bool HardI2C::SendAddress(int addr, bool tx)
I2C_Send7bitAddress(iic, Address, I2C_Direction_Receiver);
_Event = I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED;
if(!WaitAck()) return false;
if(!WaitAck(true)) return false;
return true;
}