这里提供一个 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);
}
}
运行结果
