Ch32V307 I2C 扫描程序

Ch32V307 使用 I2C2 进行扫描的代码,使用 I2C2 ,对应引脚 PB10 为 SCL , PB11 为 SDA。串口输出波特率 6000 000bps。

#include “ch32v30x.h”
#include “debug.h”

/* I2C 引脚定义 (可根据实际硬件修改) */
#define I2C_SCL_PIN GPIO_Pin_10
#define I2C_SDA_PIN GPIO_Pin_11
#define I2C_PORT GPIOB
#define I2C_CLK RCC_APB2Periph_GPIOB

/* I2C 实例定义 */
#define I2C_INSTANCE I2C2
#define I2C_CLK_SRC RCC_APB1Periph_I2C2

/* I2C GPIO 初始化 */
void I2C_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(I2C_CLK, ENABLE);

GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 开漏复用输出
GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}

/* I2C 模块初始化 */
void I2C_Master_Init(void)
{
I2C_InitTypeDef I2C_InitStructure;

RCC_APB1PeriphClockCmd(I2C_CLK_SRC, ENABLE);

I2C_DeInit(I2C_INSTANCE);

I2C_InitStructure.I2C_ClockSpeed = 100000; // 100kHz 标准模式
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x00; // 主机模式不需要自身地址
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

I2C_Init(I2C_INSTANCE, &I2C_InitStructure);
I2C_Cmd(I2C_INSTANCE, ENABLE);
}

/* 检测单个 I2C 地址是否存在设备 */
// 返回 0: 设备存在 (ACK), 1: 无设备 (NACK) 或错误
uint8_t I2C_Check_Device(uint8_t address)
{
I2C_GenerateSTART(I2C_INSTANCE, ENABLE);

// 等待起始条件发送完成
while(!I2C_CheckEvent(I2C_INSTANCE, I2C_EVENT_MASTER_MODE_SELECT));

// 发送地址 (写方向, 最后一位为0)
I2C_Send7bitAddress(I2C_INSTANCE, address << 1, I2C_Direction_Transmitter);

// 等待地址发送完成或接收到 NACK
// 注意:CH32V307 库函数可能需要根据具体状态标志判断
// 这里使用简单的超时机制和状态检查

uint32_t timeout = 10000;
while(timeout–)
{
if(I2C_GetFlagStatus(I2C_INSTANCE, I2C_FLAG_ADDR))
{
// 地址发送成功,收到 ACK
I2C_ClearFlag(I2C_INSTANCE, I2C_FLAG_ADDR);
I2C_GenerateSTOP(I2C_INSTANCE, ENABLE);
return 0; // 设备存在
}

if(I2C_GetFlagStatus(I2C_INSTANCE, I2C_FLAG_AF))
{
// 收到 NACK
I2C_ClearFlag(I2C_INSTANCE, I2C_FLAG_AF);
I2C_GenerateSTOP(I2C_INSTANCE, ENABLE);
return 1; // 无设备
}
}

// 超时错误
I2C_GenerateSTOP(I2C_INSTANCE, ENABLE);
return 1;
}

/* 扫描总线上的所有设备 */
void I2C_Scan_Bus(void)
{
uint8_t address;
uint8_t found_count = 0;

printf(“\r\n========================================\r\n”);
printf(” CH32V307 I2C Scanner Start\r\n”);
printf(“========================================\r\n”);
printf(“Scanning I2C bus…\r\n”);

for(address = 1; address < 127; address++)
{
// 跳过保留地址 (通常 0x00 是通用呼叫,0x78-0x7F 是保留)
// 但为了全面扫描,我们扫描 1-127,具体保留地址视情况而定

if(I2C_Check_Device(address) == 0)
{
printf(“Found device at address: 0x%02X (7-bit)\r\n”, address);
printf(” : 0x%02X (8-bit Write)\r\n”, address << 1);
printf(” : 0x%02X (8-bit Read)\r\n”, (address << 1) | 1);
found_count++;
}
// 短暂延时,避免总线过于繁忙
Delay_Ms(5);
}

if(found_count == 0)
{
printf(“No I2C devices found.\r\n”);
}
else
{
printf(“Total devices found: %d\r\n”, found_count);
}
printf(“========================================\r\n\r\n”);
}

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

I2C_GPIO_Init();
I2C_Master_Init();

while(1)
{
I2C_Scan_Bus();
Delay_Ms(5000); // 每5秒扫描一次
}

}
运行结果:

发表回复

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