ch32v307 I2C读取卡死

使用ch32v307的i2c会一直卡在while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));这里。

参考ch32v203使用IIC,一直卡在I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED这步骤 - 沁恒微电子社区 (wch.cn)里的方式也没有解决。


I2C初始化代码为:

void i2c1_init(u32 bound, u16 address)
{
    GPIO_InitTypeDef GPIO_InitStructure={0};
    I2C_InitTypeDef I2C_InitTSturcture={0};

    //RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE );
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO, ENABLE );
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE );

    I2C_DeInit(I2C1);
    GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOB, &GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOB, &GPIO_InitStructure );

    I2C_InitTSturcture.I2C_ClockSpeed = bound;
    I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;
    I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_2;//I2C_DutyCycle_16_9;//
    I2C_InitTSturcture.I2C_OwnAddress1 = address;
    I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable;
    I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_Init( I2C1, &I2C_InitTSturcture );

    I2C_Cmd( I2C1, ENABLE );

    I2C_AcknowledgeConfig( I2C1, ENABLE );
}


i2c1_init(100000, CH32_I2C_ADDR);


读取代码为:

uint8_t I2C_RegRead(I2C_TypeDef* I2Cx, uint8_t deviceAddr, uint8_t data)
{
    uint8_t value;
    if (NULL == I2Cx) return -1;

    printf("[lbc_info] %04d %s 1\r\n", __LINE__, __func__);

    while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY) != RESET);
    I2C_GenerateSTART(I2Cx, ENABLE);

    printf("[lbc_info] %04d %s 2\r\n", __LINE__, __func__);

    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
    I2C_Send7bitAddress(I2Cx,  deviceAddr, I2C_Direction_Transmitter);

    printf("[lbc_info] %04d %s 3\r\n", __LINE__, __func__);
    Delay_Ms(10);

    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    printf("[lbc_info] %04d %s 4\r\n", __LINE__, __func__);

    I2C_SendData(I2Cx, data);
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    printf("[lbc_info] %04d %s 5\r\n", __LINE__, __func__);

    I2C_GenerateSTART(I2Cx, ENABLE);

    printf("[lbc_info] %04d %s 6\r\n", __LINE__, __func__);

    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
    I2C_Send7bitAddress(I2Cx, deviceAddr, I2C_Direction_Receiver);

    printf("[lbc_info] %04d %s 7\r\n", __LINE__, __func__);

    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
    printf("[lbc_info] %04d %s 8\r\n", __LINE__, __func__);
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) ==  RESET );
    printf("[lbc_info] %04d %s 9\r\n", __LINE__, __func__);
    I2C_AcknowledgeConfig(I2Cx, DISABLE);

    value = I2C_ReceiveData(I2Cx);
    I2C_GenerateSTOP(I2Cx, ENABLE);

    return value;
}


uint16_t tmp116_read_id(void)
{
    uint16_t temp;

    temp = I2C_RegRead(I2C1, TMP116_R_ADDR, TMP116_DEVICE_ID_ADDR);
    printf("[lbc_info] tmp116 device id:0x%X.\r\n", temp);

    return temp;
}


问题已解决,非ch32造成。


i2c连续读取两个字节需要怎么处理,尝试了两种方式均会导致卡死

uint16_t I2C_RegRead16(I2C_TypeDef* I2Cx, uint8_t deviceAddr, uint8_t data)
{
    uint16_t value = 0;
    if (NULL == I2Cx) return 0;

    printf("[lbc_info] %s %d 1\r\n", __func__, __LINE__);

    while( I2C_GetFlagStatus( I2Cx, I2C_FLAG_BUSY ) != RESET );
    I2C_GenerateSTART(I2Cx, ENABLE);

    printf("[lbc_info] %s %d 2\r\n", __func__, __LINE__);

    while( !I2C_CheckEvent( I2Cx, I2C_EVENT_MASTER_MODE_SELECT ) );
    I2C_Send7bitAddress( I2Cx, deviceAddr, I2C_Direction_Transmitter );

    printf("[lbc_info] %s %d 3\r\n", __func__, __LINE__);

    while( !I2C_CheckEvent( I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );

    printf("[lbc_info] %s %d 4\r\n", __func__, __LINE__);

    I2C_SendData(I2Cx, data);                                                   //SEND REG
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));            //SEND REG

    printf("[lbc_info] %s %d 5\r\n", __func__, __LINE__);

    I2C_GenerateSTART(I2Cx, ENABLE);                                            //REPEATED START
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));                 //REPEATED START

    printf("[lbc_info] %s %d 6\r\n", __func__, __LINE__);

    I2C_Send7bitAddress(I2Cx, deviceAddr, I2C_Direction_Receiver);              //SEND ADDR R
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));      //SEND ADDR R

    printf("[lbc_info] %s %d 7\r\n", __func__, __LINE__);

#if 0
    I2C_AcknowledgeConfig(I2Cx, DISABLE);                                   //ACK=0

    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); /* EV7 */     //WAIT READ
    value = (uint16_t)I2C_ReceiveData(I2Cx) << 8;                               //READ DATA

    printf("[lbc_info] %s %d 8\r\n", __func__, __LINE__);

    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); /* EV7 */     //WAIT READ
    value |= (uint16_t)I2C_ReceiveData(I2Cx);                                   //READ DATA

    printf("[lbc_info] %s %d 9\r\n", __func__, __LINE__);

    I2C_GenerateSTOP(I2Cx, ENABLE);                                             //STOP
#endif
#if 1
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); /* EV7 */     //WAIT READ
    value = (uint16_t)I2C_ReceiveData(I2Cx) << 8;                               //READ DATA

    printf("[lbc_info] %s %d 8\r\n", __func__, __LINE__);

    I2C_AcknowledgeConfig(I2Cx, DISABLE);                                   //ACK=0
    I2C_GenerateSTOP(I2Cx, ENABLE);                                             //STOP

    printf("[lbc_info] %s %d 9\r\n", __func__, __LINE__);

    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); /* EV7 */     //WAIT READ
    value |= (uint16_t)I2C_ReceiveData(I2Cx);                                   //READ DATA
#endif

    return value;
}



您好,可以参考一下EVT IIC读写EEPROM例程中读取多个数据的写法,读写的过程中不建议加这么多打印。后续若有问题,可邮箱(lzs@wch.cn)沟通。


可以试下这个封装过的I2C库:https://github.com/WuxiProject-offical/CH32X035-HelperLibrary/tree/main/I2C/Master

这个库是适配X035系列的,但应该可以稍微改下或者参考这个状态机的实现方法。


楼上推荐的库做的不错。

健壮的I2C是要有超时机制,避免总线锁死的。这很重要,不是调试的时候OK就没问题的。


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