CH347T SPI的阻塞问题

使用

CH347StreamSPI4函数与SPI从机通信时 偶尔会出现函数不返回阻塞导致进程卡死的现象。
此时只有拔掉CH347的USB口才能解决卡死问题(函数可直接返回错误)


程序已经在CH347OpenDevice后设置了超时
CH347SetTimeout(mDevIndex,500,500);


以下是源码:

#include "ch347.h"
#include "CH347DLL.H"

#include <QDebug>
#include "QsLog.h"
#include "mytime.h"
//pins 0-7  isRisingEdge 是否为上升沿触发
bool Ch347::gpioSetIRQCallback(uint8_t pins,bool isRisingEdge,mPCH347_INT_ROUTINE call)
{
    uint8_t Int0TripMode=0;
    if(isRisingEdge)
    {
        Int0TripMode=1;
    }
    // 设定GPIO中断服务程序
    bool isSetIrq=CH347SetIntRoutine(mDevIndex,           // 指定设备序号
                                     pins,          // 中断0 GPIO引脚号,大于7:不启用此中断源; 为0-7对应gpio0-7
                                     Int0TripMode,      // 中断0类型: 00:下降沿触发; 01:上升沿触发; 02:双边沿触发; 03:保留;
                                     9,          // 中断1 GPIO引脚号,大于7则不启用此中断源,为0-7对应gpio0-7
                                     0,      // 中断1类型: 00:下降沿触发; 01:上升沿触发; 02:双边沿触发; 03:保留;
                                     call);// 指定中断服务程序,为NULL则取消中断服务,否则在中断时调用该程序
    return isSetIrq;
}

Ch347::Ch347(int mode)
{
    mMode=mode;
    QLOG_DEBUG()<<"mMode="<<mMode;
    int count=enumDevice();
    QLOG_DEBUG()<<"设备数量:"<<count;
    if(count<=0)
    {
        QLOG_ERROR()<<"枚举失败";
    }

    for (auto it = qAsConst(mDevInfoMap).begin(); it != qAsConst(mDevInfoMap).end(); ++it)
    {
        QString str(it.value().FuncDescStr);
        int key=it.key();
        QLOG_DEBUG()<<"枚举设备 index:"<<key<<"信息:"<<str;
    }
    QLOG_DEBUG()<<"CH347 构造完成";
}

Ch347::~Ch347()
{
    closeDev();
}

//枚举设备
int Ch347::enumDevice()
{
    ULONG i,DevCnt = 0;

    mDevIsOpened = (CH347OpenDevice(mDevIndex) != INVALID_HANDLE_VALUE);
    QLOG_DEBUG()<<"devOpen:"<<mDevIsOpened;
    if(mDevIsOpened==false)
    {
        QLOG_ERROR()<<"打开CH347设备出错";
    }

    CH347SetTimeout(mDevIndex,500,500);

    mDeviceInforS DevInfor;
    for(i=0;i<16;i++)
    {
        if(CH347Uart_Open(i) != INVALID_HANDLE_VALUE)
        {
            CH347Uart_GetDeviceInfor(i,&DevInfor);
            mDevInfoMap[DevCnt]=DevInfor;
            DevCnt++;
        }
        CH347Uart_Close(i);
    }
    return DevCnt;
}

void Ch347::closeDev(void)
{
    if(mDevIsOpened)
    {
        QLOG_DEBUG()<<"关闭CH347设备";
        CH347CloseDevice(mDevIndex);
        mDevIsOpened=false;
    }
}


bool Ch347::SPITest()
{
    mSpiCfgS readCfg = {0};
    bool rec=CH347SPI_GetCfg(0,&readCfg);


    return rec;
}




bool Ch347::SPIOpen()
{
    bool RetVal = FALSE;
    mSpiCfgS SpiCfg = {0};
    UCHAR SpiDatabits = 0;	// 设置的数据位 默认0

    SpiCfg.iMode = (UCHAR)1;
    SpiCfg.iClock = (UCHAR)5;
    SpiCfg.iByteOrder = (UCHAR)1;
    SpiCfg.iSpiWriteReadInterval =0;
    SpiCfg.iSpiOutDefaultData = 0xFF;

    SpiCfg.iChipSelect = 0;
    SpiCfg.iChipSelect |= 0x80;


    SpiCfg.CS1Polarity = (UCHAR)0;
    SpiCfg.CS2Polarity = (UCHAR)0;



    SpiCfg.iIsAutoDeativeCS = 0;
    SpiCfg.iActiveDelay = 0;
    SpiCfg.iDelayDeactive =0;

    // 设置SPI 数据位
    //SpiDatabits = (UCHAR)0;//SendDlgItemMessage(SpiI2cGpioDebugHwnd,IDC_SpiCfg_Databits,CB_GETCURSEL,0,0);
    RetVal = CH347SPI_SetDataBits(mDevIndex, SpiDatabits);

    RetVal = CH347SPI_Init(mDevIndex,&SpiCfg);
    QLOG_DEBUG()<<"CH347SPI_Init "<<RetVal;
    return RetVal;
}

bool Ch347::gpioGet(uint8_t pins)
{
    bool RetVal;
    uint8_t iDir = 0,iData = 0;

    RetVal = CH347GPIO_Get(mDevIndex,&iDir,&iData);
    if(RetVal)
    {
        mPinsDir=iDir;
        mPinsVol=iData;
        //显示方向
        uint8_t Dir = (iDir&(1<<pins))?BST_CHECKED:BST_UNCHECKED;
        //电平值
        uint8_t Sel = (iData&(1<<pins))?BST_CHECKED:BST_UNCHECKED;

        bool vol=(bool)Sel;
        return vol;
    }
    return false;
}

bool Ch347::gpioSet(uint8_t pins,bool isHigh,bool isEnable)
{
    if(pins>7)
    {
        return false;
    }
    uint8_t enable=(uint8_t)isEnable;
    uint8_t dir=1;
    uint8_t data=(uint8_t)isHigh;
    mPinsEnable|=(enable<<pins);
    mPinsDir|=(dir<<pins);
    mPinsVol|=(data<<pins);
    bool rec=CH347GPIO_Set(mDevIndex,// 指定设备序号
                      mPinsEnable,// 数据有效标志:对应位0-7,对应GPIO0-7.
                      mPinsDir,// 设置I/O方向,某位清0则对应引脚为输入,某位置1则对应引脚为输出.GPIO0-7对应位0-7.
                      mPinsVol);  // 输出数据,如果I/O方向为输出,那么某位清0时对应引脚输出低电平,某位置1时对应引脚输出高电平
    return rec;
}


bool Ch347::SPIWrite(Bytes& bytes)
{
    uint8_t buf[1024*3]={0};
    int len=bytes.length();
    memcpy(buf,bytes.toBuffer(),len);

    QLOG_DEBUG()<<"SPI 写入:"<<bytes.toString();
    UCHAR ChipSelect=0x80;

    //事实上单独的SPI写或读函数是可以直接被 CH347SPI_WriteRead 函数替代使用的。
    //之所以提供单独的 CH347SPI_Read 和 CH347SPI_Write 函数
    //是考虑到实际应用有需要单向操作的场景,此类函数使用会更直观些
    bool rec=CH347SPI_Write(mDevIndex,ChipSelect,len,512,buf);
    if(rec==false)
    {
        QLOG_ERROR()<<"SPI写失败";
    }
    return rec;
}

bool Ch347::SPIWriteRead(Bytes& bytes)
{

    Mytime::delayMs(10);
    uint8_t buf[1024*3]={0};
    int len=bytes.length();
    memcpy(buf,bytes.toBuffer(),len);

    QLOG_DEBUG()<<"SPI 写入:"<<bytes.toString();
    UCHAR ChipSelect=0x80;
    //CH347StreamSPI4其API为适应此前调用方式,功能与CH347SPI_WriteRead一致
    bool rec=CH347StreamSPI4(mDevIndex,ChipSelect,len,buf);
    memcpy(bytes.toBuffer(),buf,len);
    QLOG_DEBUG()<<"SPI 读出:"<<bytes.toString();
    if(rec==false)
    {
        QLOG_ERROR()<<"SPI写失败";
    }
    return rec;
}


bool Ch347::IICOpen()
{
    mDevIsOpened = (CH347OpenDevice(mDevIndex) != INVALID_HANDLE_VALUE);
    QLOG_DEBUG()<<"devOpen:"<<mDevIsOpened;
    if(mDevIsOpened==false)
    {
        return false;
    }

    bool retVal = CH347I2C_Set(mDevIndex, mIICSpeedMode);
    QLOG_DEBUG()<<"CH347I2C Set clock:"<<retVal;

    retVal = CH347I2C_SetStretch(mDevIndex, false);
    QLOG_DEBUG()<<"CH347 I2C set stetching:"<<retVal;
    uint32_t I2CDelayMs = 100;
    if (I2CDelayMs > 0)
    {
        retVal = CH347I2C_SetDelaymS(mDevIndex, I2CDelayMs);
        QLOG_DEBUG()<<"CH347InitI2C"<<retVal;
    }
    return retVal;
}

bool Ch347::IICReadWrite(uint8_t* outBuffer,int& outLen,uint8_t* inBuffer,int& inLen)
{
    bool RetVal = CH347StreamI2C(mDevIndex,outLen,outBuffer,inLen,inBuffer);
    QLOG_DEBUG()<<"read write iic:"<<RetVal;
    if(RetVal)
    {
        QLOG_DEBUG()<<"inlen="<<inLen;
    }
    return RetVal;
}


卡死后的页面、LOG日志、设备管理器


58ade386d460b8c1d4c6332a7d0f21a.png


b221589cdab8145f1e74383e3b9df33.pngf79865353a0774d1264e3a1c202fe04.png


您好,在通信异常时如不动硬件重新开关软件是否可以恢复?如开关不能恢复,重新上电或插拔USB可恢复,则因为USB信号传输不稳定产生了异常的可能性较高。

需检查PCB设计,USB使用端子以及线缆情况。CH347是高速USB2.0转接芯片,因此USB的设计和线缆需要遵循协议规范。


您好,按您说的尝试了,强制关闭软件->重启软件,可以正常通信,无需重启硬件。这似乎不是硬件问题


只有登录才能回复,可以选择微信账号登录