SmartOS/Device/I2C.h

162 lines
3.8 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef _I2C_H_
#define _I2C_H_
#include "Device\Port.h"
//SCL 开漏复用输出
//SDA 开漏复用输出
// I2C外设
class I2C
{
public:
int Speed; // 速度
int Retry; // 等待重试次数默认200
int Error; // 错误次数
ushort Address; // 设备地址。7位或10位
byte SubWidth; // 子地址占字节数
bool Opened; // 是否已经打开
I2C();
virtual ~I2C();
virtual void SetPin(Pin scl, Pin sda) = 0;
virtual void GetPin(Pin* scl = nullptr, Pin* sda = nullptr) = 0;
virtual bool Open(); // 打开设备
virtual void Close(); // 关闭设备
virtual void Start() = 0; // 开始会话
virtual void Stop() = 0; // 停止会话
virtual void WriteByte(byte dat) = 0; // 写入单个字节
virtual byte ReadByte() = 0; // 读取单个字节
virtual void Ack(bool ack) = 0; // 发送Ack/Nak
virtual bool WaitAck(bool ack) = 0; // 等待Ack/Nak
// 新会话向指定地址写入
bool Write(int addr, const Buffer& bs);
bool Write(int addr, byte data);
// 新会话从指定地址读取
virtual uint Read(int addr, Buffer& bs);
virtual byte Read(int addr);
virtual ushort Read2(int addr);
virtual uint Read4(int addr);
protected:
virtual bool OnOpen() = 0; // 打开设备
virtual void OnClose() = 0; // 外部设备
virtual bool SendAddress(int addr, bool tx);
virtual bool SendSubAddr(int addr);
};
// I2C会话类。初始化时打开超出作用域析构时关闭
class I2CScope
{
private:
I2C* _iic;
public:
I2CScope(I2C* iic)
{
_iic = iic;
_iic->Start();
}
~I2CScope()
{
_iic->Stop();
}
};
// 硬件I2C
class HardI2C : public I2C
{
private:
void Init(byte index, uint speedHz);
public:
// 使用端口和最大速度初始化,因为需要分频,实际速度小于等于该速度
//HardI2C(I2C_TypeDef* iic = I2C1, uint speedHz = 100000);
HardI2C(byte index, uint speedHz = 100000);
virtual ~HardI2C();
virtual void SetPin(Pin scl, Pin sda);
virtual void GetPin(Pin* scl = nullptr, Pin* sda = nullptr);
virtual void Start();
virtual void Stop();
virtual void WriteByte(byte dat);
virtual byte ReadByte();
virtual void Ack(bool ack);
virtual bool WaitAck(bool ack);
//virtual bool Write(int addr, byte* buf, uint len); // 新会话向指定地址写入多个字节
//virtual uint Read(int addr, byte* buf, uint len); // 新会话从指定地址读取多个字节
private:
byte _index;
void* _IIC;
uint _Event;
AlternatePort SCL;
AlternatePort SDA;
virtual bool SendAddress(int addr, bool tx = true);
void OnInit();
virtual bool OnOpen();
virtual void OnClose();
};
// 软件模拟I2C
class SoftI2C : public I2C
{
public:
bool HasSecAddress; // 设备是否有子地址
// 使用端口和最大速度初始化,因为需要分频,实际速度小于等于该速度
SoftI2C(uint speedHz = 100000);
virtual ~SoftI2C();
virtual void SetPin(Pin scl, Pin sda);
virtual void GetPin(Pin* scl = nullptr, Pin* sda = nullptr);
virtual void Start();
virtual void Stop();
virtual void WriteByte(byte dat);
virtual byte ReadByte();
virtual void Ack(bool ack);
virtual bool WaitAck(bool ack);
private:
int _delay; // 根据速度匹配的延时
OutputPort SCL; // 时钟。开漏输出
OutputPort SDA; // 数据。开漏输出,直接具备读写功能
virtual bool OnOpen();
virtual void OnClose();
void Delay();
};
/*
开发历史
2015-10-03
I2C的核心SCL为高时SDA不许改变开始停止除外。
SCL为高时SDA下降沿表示开始SDA上升沿表示停止。
发送数据后拉高SCL等待接收方通过SDA发过来的ACK确认。
读取数据时如果数据提供方来不及提供数据可拉低SCL。
感谢夏宇@10068953
*/
#endif