CH32V407 I2C 扫描代码

这里提供一个 CH32V407 I2C 设备扫描代码,可以用于调试I2C 设备。使用默认的 PB6-SCL / PB7-SDA 两个引脚。

/*
 *@Note
 7-bit address mode, master/slave mode, transceiver routine:
 I2C1_SCL(PB6)\I2C1_SDA(PB7).
 */

#include "debug.h"

#define I2C_TIMEOUT     0xFFFF

/*********************************************************************
 * @fn      IIC_Init
 *
 * @brief   Initializes the IIC peripheral.
 *
 * @return  none
 */
void IIC_Init(u32 bound)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    I2C_InitTypeDef  I2C_InitTSturcture = {0};

    RCC_PB2PeriphClockCmd(RCC_PB2Periph_GPIOB | RCC_PB2Periph_AFIO, ENABLE);
    RCC_PB1PeriphClockCmd(RCC_PB1Periph_I2C1, ENABLE);

    /* 不使用重映射,I2C1走PB6/PB7 */
    GPIO_PinRemapConfig(GPIO_Remap_I2C1, DISABLE);

    GPIO_SetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7);

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

    I2C_Cmd(I2C1, ENABLE);

    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_High;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_High;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/* 等待某个事件,带超时 */
static int I2C_WaitEvent(I2C_TypeDef *I2Cx, uint32_t event)
{
    uint32_t timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(I2Cx, event))
    {
        if(--timeout == 0)
            return 0;
    }
    return 1;
}

/* 扫描单个地址是否存在
 * addr: 7-bit地址
 * 返回: 1=存在, 0=不存在
 */
int I2C_CheckDevice(uint8_t addr)
{
    uint32_t timeout;

    /* 等待总线空闲 */
    timeout = I2C_TIMEOUT;
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY))
    {
        if(--timeout == 0)
            return 0;
    }

    /* 产生START */
    I2C_GenerateSTART(I2C1, ENABLE);
    if(!I2C_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
        goto fail;

    /* 发送7位地址,写方向 */
    I2C_Send7bitAddress(I2C1, addr << 1, I2C_Direction_Transmitter);

    timeout = I2C_TIMEOUT;
    while(1)
    {
        /* ADDR: 收到ACK */
        if(I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR))
        {
            /* 清ADDR标志 */
            (void)I2C1->STAR1;
            (void)I2C1->STAR2;

            I2C_GenerateSTOP(I2C1, ENABLE);
            return 1;
        }

        /* AF: 无应答 */
        if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF))
        {
            I2C_ClearFlag(I2C1, I2C_FLAG_AF);
            goto fail;
        }

        if(--timeout == 0)
            goto fail;
    }

fail:
    I2C_GenerateSTOP(I2C1, ENABLE);
    return 0;
}

/* 扫描I2C设备 */
void I2C_ScanBus(void)
{
    uint8_t addr;
    uint8_t found = 0;

    printf("I2C bus scanning...\r\n");

    for(addr = 0x08; addr <= 0x77; addr++)
    {
        if(I2C_CheckDevice(addr))
        {
            printf("Found device at 0x%02X\r\n", addr);
            found++;
        }
        Delay_Ms(2);
    }

    if(found == 0)
        printf("No I2C device found.\r\n");
    else
        printf("Scan done, total %d device(s).\r\n", found);
}


/*********************************************************************
 * @fn      main
 *
 * @brief   Main program.
 *
 * @return  none
 */
int main(void)
{
    SystemCoreClockUpdate();
    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n", SystemClock);
    printf("SystemCoreClk:%d\r\n", SystemCoreClock);
    printf("ChipID:%08x\r\n", DBGMCU_GetCHIPID());

    printf("IIC Host mode\r\n");
    IIC_Init(100000);

    while(1)
    {
        I2C_ScanBus();
        printf("Rescan after 2 seconds...\r\n\r\n");
        Delay_Ms(2000);
    }

}

运行结果

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注