CH341(CH347)搜索I2C从机地址的方法

CH341搜索I2C从机,必须自行发送手动搭建临时I2C时序指令。而CH347搜索I2C从机,一个原生函数搞定

一、 CH341搜索I2C从机,必须自行发送手动搭建临时I2C时序指令

纯C的写法是:

c 复制代码
//发送START  
IIC_IssueStart(iIndex);  
//通知iIndex主机发送从机地址device_addr,其bit7..bit1是7bit的从机地址且bit0=0,返回从机是否正确响应ack=0  
Status = IIC_OutByteCheckAck(iIndex, device_addr);  
//发送STOP      
IIC_IssueStop(iIndex);  
//判断Status是否等于1,=1表示找到了device_addr这个从机,=0表示没有找到  
if (0==Status) {//没有找到USBHandle下I2CSlaveAddress对应的从I2C设备   
    return -1;  
}  

其中,

c 复制代码
uint8_t CMD_I2C_STREAM  = 0xAA;  // I2C流命令包开头    
uint8_t CMD_I2C_STM_STA = 0x74; // 产生起始位    
uint8_t CMD_I2C_STM_STO = 0x75; // 产生停止位    
uint8_t CMD_I2C_STM_OUT = 0x80; // 输出数据    
uint8_t CMD_I2C_STM_END = 0x00; // 命令包提前结束    
  
bool CH341Device::IIC_IssueStart()    
{    
    uint8_t mBuffer[3] = {0};    
    mBuffer[0] = CMD_I2C_STREAM;    
    mBuffer[1] = CMD_I2C_STM_STA;    
    mBuffer[2] = CMD_I2C_STM_END;    
    
    ULONG writeLen = 3;    
    return CH341WriteData(m_deviceIndex, mBuffer, &writeLen);    
}    
    
bool CH341Device::IIC_IssueStop()    
{    
    uint8_t mBuffer[3] = {0};    
    mBuffer[0] = CMD_I2C_STREAM;    
    mBuffer[1] = CMD_I2C_STM_STO;    
    mBuffer[2] = CMD_I2C_STM_END;    
    
    ULONG writeLen = 3;    
    return CH341WriteData(    
        static_cast<ULONG>(m_deviceIndex),    
        reinterpret_cast<PUCHAR>(mBuffer),    
        &writeLen    
        );    
}    
    
bool CH341Device::IIC_OutByteCheckAck1(uint8_t slaveAddr)    
{    
    uint8_t mBuffer[4] = {0};    
    mBuffer[0] = CMD_I2C_STREAM;    
    mBuffer[1] = CMD_I2C_STM_OUT;    
    mBuffer[2] = slaveAddr;    
    mBuffer[3] = CMD_I2C_STM_END;    
    
    ULONG iWriteLength = 4;    
    ULONG iReadLength = 1;    
    ULONG readLen = 0;    
    uint8_t readBuffer[32] = {0};    
    
    BOOL ret = CH341WriteRead(    
        static_cast<ULONG>(m_deviceIndex),    
        iWriteLength,    
        reinterpret_cast<PUCHAR>(mBuffer),    
        32,    
        iReadLength,    
        &readLen,    
        reinterpret_cast<PUCHAR>(readBuffer)    
        );    
    
    if (ret && readLen > 0) {    
        return (readBuffer[readLen - 1] & 0x80) == 0;    
    }    
    return false;    
}   

二、 CH347搜索I2C从机,一个原生函数搞定

C原型函数头:

c 复制代码
// 处理I2C数据流,速度约56K字节,返回主机端获取到的ACK数量  
BOOL    WINAPI  CH347StreamI2C_RetACK(    
    ULONG  iIndex,         // 指定设备序号  
    ULONG  iWriteLength,  // 准备写出的数据字节数  
    PVOID  iWriteBuffer,  // 指向一个缓冲区,放置准备写出的数据,首字节通常是I2C设备地址及读写方向位  
    ULONG  iReadLength,   // 准备读取的数据字节数  
    PVOID  oReadBuffer,   // 指向一个缓冲区,返回后是读入的数据  
    PULONG rAckCount);    // 指向读写返回的ACK值  

一样的,我们可以调用该函数,通知iIndex主机发送1Byte数据即从机地址device_addr,其bit7...bit1是7bit的从机地址且bit0=0,运行完了应该有rAckCount==1,且返回值是执行完该函数(但实测无论从机是否有正确响应ack=1,这个返回值总是1)。

C#代码,先封装一个方法ConfirmSlaveAdd_CH347():

csharp 复制代码
private int ConfirmSlaveAdd_CH347(uint CH347Index, byte I2CSlaveAdd)  
{   
    byte[] wrBuf = new byte[] { I2CSlaveAdd, 0x00 };  
    byte[] rdBuf = new byte[1];  
    // iWriteLen=1,iReadLen=0;发送 Start + 从机写地址,然后Stop  
    uint ackCnt;  
  
    int apiOk = DLLProxy.CH347StreamI2C_RetACK(  
        (uint)CH347Index,  
        (uint)1,  
        wrBuf,  
        (uint)0,  
        rdBuf,  
        out ackCnt  
    );  
    if ((1 == apiOk) && (ackCnt == 1))//发送从机地址成功,且返回1次有效的ack=0  
        return 0;  //已搜到目标从机地址  
    else  
        return -1; //未搜到目标从机地址  
}  

然后在某按键的Click事件的回调函数中调用ConfirmSlaveAdd_CH347():

csharp 复制代码
int streamOk = ConfirmSlaveAdd_CH347(CH347Index, I2CSlaveAdd);  
if (0 != streamOk){ //没搜到  
    Debug.WriteLine($"CH347StreamI2C调用失败,设备索引={CH347Index},从机地址={I2CSlaveAdd}");  
    return;  
}  
else{               //搜到了  
Debug.WriteLine($"找到有效I2C地址:0x{I2CSlaveAdd:X2}");  
}  
相关推荐
橘好き5 天前
将7针的SPI OLED做I2C使用
oled·spi·i2c
susplus8 天前
【ARM 裸机开发 (IMX6ULL-mini)】I2C协议详解
嵌入式·arm·i2c
嵌入式分享18 天前
I2C 信号怎么测?从万用表到示波器的完整排查流程
i2c
潘潘的嵌入式日记22 天前
I²C 主机读到的 U16 偶尔跳变?先修复多字节快照发布
嵌入式·并发·数据一致性·i2c·快照
WWJA王文举25 天前
从设备地址到寄存器地址:I²C驱动完整流程详解
嵌入式开发·rtos·通信协议·i2c
程序员老舅2 个月前
啃透 I2C 驱动开发,才算入门嵌入式 Linux 内核驱动
数据结构·驱动开发·b树·内核·嵌入式·嵌入式开发·i2c
ItJavawfc3 个月前
Linux驱动-IIC完善FT5X06设备节点和驱动
i2c·驱动-完善i2c 设备树·i2c-完善驱动
阿拉斯攀登3 个月前
I2C 设备驱动开发
linux·驱动开发·嵌入式硬件·嵌入式·linux驱动·i2c·字符设备驱动
ALINX技术博客4 个月前
【黑金云课堂】FPGA技术教程FPGA基础:I2C 总线通信技术
fpga开发·i2c