generated from hulk/gd32e23x_template_cmake_vscode
Compare commits
2 Commits
88f79f7eb0
...
dd7549d62b
Author | SHA1 | Date | |
---|---|---|---|
dd7549d62b | |||
90486c6609 |
12
Inc/i2c.h
12
Inc/i2c.h
@@ -39,7 +39,10 @@ typedef enum {
|
||||
I2C_RESULT_NACK, /* No acknowledge received */
|
||||
I2C_RESULT_BUS_BUSY, /* Bus is busy */
|
||||
I2C_RESULT_ERROR, /* General error */
|
||||
I2C_RESULT_INVALID_PARAM /* Invalid parameter */
|
||||
I2C_RESULT_INVALID_PARAM, /* Invalid parameter */
|
||||
I2C_RECOVERY_OK,
|
||||
I2C_RECOVERY_SDA_STUCK_LOW,
|
||||
I2C_RECOVERY_SCL_STUCK_LOW
|
||||
} i2c_result_t;
|
||||
|
||||
/* I2C state machine enumeration */
|
||||
@@ -69,24 +72,21 @@ typedef enum {
|
||||
|
||||
|
||||
/* Function declarations */
|
||||
|
||||
// TODO I2C Result
|
||||
/*!
|
||||
\brief configure the I2C interface
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval i2c_result_t
|
||||
*/
|
||||
void i2c_config(void);
|
||||
i2c_result_t i2c_config(void);
|
||||
|
||||
// TODO I2C Result
|
||||
/*!
|
||||
\brief reset I2C bus with proper recovery
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval i2c_result_t
|
||||
*/
|
||||
void i2c_bus_reset(void);
|
||||
i2c_result_t i2c_bus_reset(void);
|
||||
|
||||
/*!
|
||||
\brief scan I2C bus for devices
|
||||
|
176
Src/i2c.c
176
Src/i2c.c
@@ -31,7 +31,7 @@ void i2c_gpio_config(void) {
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_config(void) {
|
||||
i2c_result_t i2c_config(void) {
|
||||
/* configure I2C GPIO */
|
||||
i2c_gpio_config();
|
||||
/* enable I2C clock */
|
||||
@@ -44,6 +44,27 @@ void i2c_config(void) {
|
||||
i2c_enable(I2C0);
|
||||
/* enable acknowledge */
|
||||
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
|
||||
|
||||
return I2C_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/* wait for SCL to go high, return true if successful, false if timeout */
|
||||
static bool i2c_wait_scl_high(uint16_t max_wait_time) {
|
||||
while (max_wait_time--) {
|
||||
if (gpio_input_bit_get(I2C_SCL_PORT, I2C_SCL_PIN)) {
|
||||
return true;
|
||||
}
|
||||
delay_10us(1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* generate one manual SCL pulse; return true if SCL observed high (no stuck/overstretch) */
|
||||
static bool i2c_generate_scl_pulse(void) {
|
||||
GPIO_BC(I2C_SCL_PORT) = I2C_SCL_PIN; /* drive SCL low */
|
||||
delay_10us(1);
|
||||
GPIO_BOP(I2C_SCL_PORT) = I2C_SCL_PIN; /* release SCL (open-drain -> high via pull-up) */
|
||||
return i2c_wait_scl_high(200); /* wait up to ~2ms for clock stretching release */
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -52,31 +73,87 @@ void i2c_config(void) {
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_bus_reset(void) {
|
||||
i2c_result_t i2c_bus_reset(void) {
|
||||
/* 1. Disable & deinit peripheral so pins can be fully controlled */
|
||||
i2c_disable(I2C0);
|
||||
i2c_deinit(I2C0);
|
||||
/* configure SDA/SCL for GPIO */
|
||||
GPIO_BC(I2C_SCL_PORT) |= I2C_SCL_PIN;
|
||||
GPIO_BC(I2C_SDA_PORT) |= I2C_SDA_PIN;
|
||||
gpio_output_options_set(I2C_SCL_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, I2C_SCL_PIN);
|
||||
gpio_output_options_set(I2C_SDA_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, I2C_SDA_PIN);
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP();
|
||||
GPIO_BOP(I2C_SCL_PORT) |= I2C_SCL_PIN;
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP();
|
||||
GPIO_BOP(I2C_SDA_PORT) |= I2C_SDA_PIN;
|
||||
/* connect I2C_SCL_PIN to I2C_SCL */
|
||||
/* connect I2C_SDA_PIN to I2C_SDA */
|
||||
|
||||
#ifdef DEBUG_VERBOSE
|
||||
printf("I2C bus reset\r\n");
|
||||
#endif
|
||||
|
||||
/* 2. Configure SCL/SDA as GPIO open-drain outputs with pull-up and release them */
|
||||
gpio_mode_set(I2C_SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, I2C_SCL_PIN);
|
||||
gpio_mode_set(I2C_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, I2C_SDA_PIN);
|
||||
gpio_output_options_set(I2C_SCL_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SCL_PIN);
|
||||
gpio_output_options_set(I2C_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SDA_PIN);
|
||||
/* configure the I2CX interface */
|
||||
gpio_bit_set(I2C_SCL_PORT, I2C_SCL_PIN); /* release SCL */
|
||||
gpio_bit_set(I2C_SDA_PORT, I2C_SDA_PIN); /* release SDA */
|
||||
|
||||
#ifdef DEBUG_VERBOSE
|
||||
printf("I2C bus reset: SCL = %d, SDA = %d\r\n", gpio_input_bit_get(I2C_SCL_PORT, I2C_SCL_PIN), gpio_input_bit_get(I2C_SDA_PORT, I2C_SDA_PIN));
|
||||
#endif
|
||||
|
||||
/* 3. Double sample to confirm bus state */
|
||||
delay_10us(1);
|
||||
bool scl_value1 = gpio_input_bit_get(I2C_SCL_PORT, I2C_SCL_PIN);
|
||||
bool sda_value1 = gpio_input_bit_get(I2C_SDA_PORT, I2C_SDA_PIN);
|
||||
delay_10us(1);
|
||||
bool scl_value2 = gpio_input_bit_get(I2C_SCL_PORT, I2C_SCL_PIN);
|
||||
bool sda_value2 = gpio_input_bit_get(I2C_SDA_PORT, I2C_SDA_PIN);
|
||||
|
||||
/* 4. If SCL low -> stuck (cannot proceed) */
|
||||
if (!scl_value2) {
|
||||
#ifdef DEBUG_VERBOSE
|
||||
printf("I2C bus reset: SCL stuck low\r\n");
|
||||
#endif
|
||||
return I2C_RECOVERY_SCL_STUCK_LOW;
|
||||
}
|
||||
|
||||
/* 5. Fast path: bus idle */
|
||||
if (scl_value1 && sda_value1 && scl_value2 && sda_value2) {
|
||||
i2c_config();
|
||||
#ifdef DEBUG_VERBOSE
|
||||
printf("I2C bus reset: bus idle\r\n");
|
||||
#endif
|
||||
return I2C_RECOVERY_OK;
|
||||
}
|
||||
|
||||
/* 6. SDA low: attempt to free by generating up to I2C_RECOVERY_CLOCKS pulses */
|
||||
if (scl_value2 && !sda_value2) {
|
||||
bool sda_released = false;
|
||||
#ifdef DEBUG_VERBOSE
|
||||
printf("I2C bus reset: SCL will try to free SDA\r\n");
|
||||
#endif
|
||||
for (uint8_t i = 0; i < I2C_RECOVERY_CLOCKS && !sda_released; i++) {
|
||||
if (!i2c_generate_scl_pulse()) {
|
||||
return I2C_RECOVERY_SCL_STUCK_LOW; /* SCL failed to go high */
|
||||
}
|
||||
if (gpio_input_bit_get(I2C_SDA_PORT, I2C_SDA_PIN)) {
|
||||
sda_released = true;
|
||||
}
|
||||
}
|
||||
if (!sda_released) {
|
||||
return I2C_RECOVERY_SDA_STUCK_LOW;
|
||||
}
|
||||
/* 7. Generate a STOP condition to leave bus in idle state */
|
||||
#ifdef DEBUG_VERBOSE
|
||||
printf("I2C bus reset: generating STOP condition\r\n");
|
||||
#endif
|
||||
gpio_bit_reset(I2C_SDA_PORT, I2C_SDA_PIN); /* SDA low */
|
||||
delay_10us(1);
|
||||
gpio_bit_set(I2C_SCL_PORT, I2C_SCL_PIN); /* ensure SCL high */
|
||||
delay_10us(1);
|
||||
gpio_bit_set(I2C_SDA_PORT, I2C_SDA_PIN); /* SDA rising while SCL high -> STOP */
|
||||
delay_10us(1);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VERBOSE
|
||||
printf("I2C bus reset: bus recovered\r\n");
|
||||
#endif
|
||||
/* 8. Reconfigure & enable peripheral */
|
||||
i2c_config();
|
||||
return I2C_RECOVERY_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,7 +168,13 @@ void i2c_scan(void) {
|
||||
uint8_t address;
|
||||
int found_devices = 0;
|
||||
|
||||
printf("Scanning I2C bus...\r\n");
|
||||
// printf("Scanning I2C bus...\r\n");
|
||||
const char* msg1 = "Scanning I2C bus...\r\n";
|
||||
for (uint8_t i = 0; msg1[i] != '\0'; i++) {
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, msg1[i]);
|
||||
}
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TC) == RESET) {}
|
||||
|
||||
for (address = 1; address < 127; address++) {
|
||||
timeout = 0;
|
||||
@@ -119,7 +202,24 @@ void i2c_scan(void) {
|
||||
timeout++;
|
||||
if (timeout < I2C_TIME_OUT) {
|
||||
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
|
||||
printf("Found device at 0x%02X\r\n", address);
|
||||
// printf("Found device at 0x%02X\r\n", address);
|
||||
const char* msg2_prefix = "Found device at 0x";
|
||||
for (uint8_t i = 0; msg2_prefix[i] != '\0'; i++) {
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, msg2_prefix[i]);
|
||||
}
|
||||
// 发送地址的十六进制表示
|
||||
uint8_t hex_chars[] = "0123456789ABCDEF";
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, hex_chars[(address >> 4) & 0x0F]);
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, hex_chars[address & 0x0F]);
|
||||
const char* msg2_suffix = "\r\n";
|
||||
for (uint8_t i = 0; msg2_suffix[i] != '\0'; i++) {
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, msg2_suffix[i]);
|
||||
}
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TC) == RESET) {}
|
||||
found_devices++;
|
||||
}
|
||||
|
||||
@@ -133,9 +233,33 @@ void i2c_scan(void) {
|
||||
}
|
||||
|
||||
if (found_devices == 0) {
|
||||
printf("No I2C devices found.\r\n");
|
||||
// printf("No I2C devices found.\r\n");
|
||||
const char* msg3 = "No I2C devices found.\r\n";
|
||||
for (uint8_t i = 0; msg3[i] != '\0'; i++) {
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, msg3[i]);
|
||||
}
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TC) == RESET) {}
|
||||
} else {
|
||||
printf("Total %d I2C devices found.\r\n", found_devices);
|
||||
// printf("Total %d I2C devices found.\r\n", found_devices);
|
||||
const char* msg4_prefix = "Total ";
|
||||
for (uint8_t i = 0; msg4_prefix[i] != '\0'; i++) {
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, msg4_prefix[i]);
|
||||
}
|
||||
// 发送设备数量
|
||||
if (found_devices >= 10) {
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, '0' + (found_devices / 10));
|
||||
}
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, '0' + (found_devices % 10));
|
||||
const char* msg4_suffix = " I2C devices found.\r\n";
|
||||
for (uint8_t i = 0; msg4_suffix[i] != '\0'; i++) {
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, msg4_suffix[i]);
|
||||
}
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TC) == RESET) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
25
Src/main.c
25
Src/main.c
@@ -60,7 +60,7 @@ int main(void)
|
||||
led_init();
|
||||
|
||||
#ifdef DEBUG_VERBOSE
|
||||
char hello_world[] = {"Hello World!"};
|
||||
char hello_world[] = {"Hello World!\r\n"};
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(hello_world); i++)
|
||||
{
|
||||
@@ -69,30 +69,23 @@ int main(void)
|
||||
}
|
||||
|
||||
while (usart_flag_get(RS485_PHY, USART_FLAG_TC) == RESET) {}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
i2c_config();
|
||||
|
||||
i2c_scan();
|
||||
|
||||
// i2c_bus_reset();
|
||||
|
||||
// uint8_t sensor_data[2] = {0};
|
||||
|
||||
// i2c_read_16bits(0x2B, 0x7E, sensor_data);
|
||||
|
||||
// printf("Sensor Data: 0x%02X 0x%02X\r\n", sensor_data[0], sensor_data[1]);
|
||||
|
||||
// i2c_bus_reset();
|
||||
|
||||
ldc1612_iic_get_sensor_infomation();
|
||||
|
||||
#ifdef DEBUG_VERBOSE
|
||||
i2c_scan();
|
||||
|
||||
i2c_bus_reset();
|
||||
#endif
|
||||
|
||||
i2c_scan();
|
||||
ldc1612_iic_get_sensor_infomation();
|
||||
|
||||
|
||||
|
||||
while(1){
|
||||
command_process();
|
||||
delay_ms(100);
|
||||
|
209
i2c_wait.c
209
i2c_wait.c
@@ -8,215 +8,6 @@
|
||||
/* Private variables */
|
||||
static uint8_t i2c_retry_count = 0;
|
||||
|
||||
/*!
|
||||
\brief configure the GPIO ports
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_gpio_config(void) {
|
||||
/* enable IIC GPIO clock */
|
||||
rcu_periph_clock_enable(RCU_GPIO_I2C);
|
||||
|
||||
/* connect I2C_SCL_PIN to I2C_SCL */
|
||||
gpio_af_set(I2C_SCL_PORT, I2C_GPIO_AF, I2C_SCL_PIN);
|
||||
/* connect I2C_SDA_PIN to I2C_SDA */
|
||||
gpio_af_set(I2C_SDA_PORT, I2C_GPIO_AF, I2C_SDA_PIN);
|
||||
/* configure GPIO pins of I2C */
|
||||
gpio_mode_set(I2C_SCL_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SCL_PIN);
|
||||
gpio_output_options_set(I2C_SCL_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SCL_PIN);
|
||||
gpio_mode_set(I2C_SDA_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SDA_PIN);
|
||||
gpio_output_options_set(I2C_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SDA_PIN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the I2CX interface
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval i2c_status_t
|
||||
*/
|
||||
i2c_status_t i2c_config(void) {
|
||||
/* configure I2C GPIO */
|
||||
i2c_gpio_config();
|
||||
|
||||
/* enable I2C clock */
|
||||
rcu_periph_clock_enable(RCU_I2C);
|
||||
|
||||
/* configure I2C clock */
|
||||
i2c_clock_config(I2C0, I2C_SPEED, I2C_DTCY_2);
|
||||
|
||||
/* configure I2C address - use 0x00 as master doesn't need specific address */
|
||||
i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, I2C_MASTER_ADDRESS);
|
||||
|
||||
/* enable I2CX */
|
||||
i2c_enable(I2C0);
|
||||
|
||||
/* enable acknowledge */
|
||||
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
|
||||
|
||||
/* reset retry counter */
|
||||
i2c_retry_count = 0;
|
||||
|
||||
return I2C_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset I2C bus with proper 9-clock recovery
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval i2c_status_t
|
||||
*/
|
||||
i2c_status_t i2c_bus_reset(void) {
|
||||
uint8_t i;
|
||||
|
||||
/* disable I2C peripheral */
|
||||
i2c_disable(I2C0);
|
||||
i2c_deinit(I2C0);
|
||||
|
||||
/* configure SDA/SCL as GPIO output for manual control */
|
||||
gpio_mode_set(I2C_SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, I2C_SCL_PIN);
|
||||
gpio_mode_set(I2C_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, I2C_SDA_PIN);
|
||||
gpio_output_options_set(I2C_SCL_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SCL_PIN);
|
||||
gpio_output_options_set(I2C_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SDA_PIN);
|
||||
|
||||
/* ensure both lines are high initially */
|
||||
gpio_bit_set(I2C_SCL_PORT, I2C_SCL_PIN);
|
||||
gpio_bit_set(I2C_SDA_PORT, I2C_SDA_PIN);
|
||||
delay_10us(I2C_DELAY_10US);
|
||||
|
||||
/* generate 9 clock pulses to release any stuck slave */
|
||||
for (i = 0; i < I2C_RECOVERY_CLOCKS; i++) {
|
||||
gpio_bit_reset(I2C_SCL_PORT, I2C_SCL_PIN);
|
||||
delay_10us(I2C_DELAY_10US);
|
||||
gpio_bit_set(I2C_SCL_PORT, I2C_SCL_PIN);
|
||||
delay_10us(I2C_DELAY_10US);
|
||||
}
|
||||
|
||||
/* generate stop condition */
|
||||
gpio_bit_reset(I2C_SDA_PORT, I2C_SDA_PIN);
|
||||
delay_10us(I2C_DELAY_10US);
|
||||
gpio_bit_set(I2C_SCL_PORT, I2C_SCL_PIN);
|
||||
delay_10us(I2C_DELAY_10US);
|
||||
gpio_bit_set(I2C_SDA_PORT, I2C_SDA_PIN);
|
||||
delay_10us(I2C_DELAY_10US);
|
||||
|
||||
/* reconfigure as I2C pins */
|
||||
gpio_af_set(I2C_SCL_PORT, I2C_GPIO_AF, I2C_SCL_PIN);
|
||||
gpio_af_set(I2C_SDA_PORT, I2C_GPIO_AF, I2C_SDA_PIN);
|
||||
gpio_mode_set(I2C_SCL_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SCL_PIN);
|
||||
gpio_mode_set(I2C_SDA_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SDA_PIN);
|
||||
|
||||
/* reconfigure the I2CX interface */
|
||||
return i2c_config();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 扫描I2C总线,查找连接的设备
|
||||
*
|
||||
* 该函数会扫描I2C总线上的所有地址(1到126),并尝试与每个地址进行通信。
|
||||
* 如果在某个地址上发现了设备,则会打印出该设备的地址。
|
||||
* 最后会打印出找到的设备总数。
|
||||
*/
|
||||
void i2c_scan(void) {
|
||||
uint32_t timeout;
|
||||
uint8_t address;
|
||||
int found_devices = 0;
|
||||
|
||||
// printf("Scanning I2C bus...\r\n");
|
||||
const char* msg1 = "Scanning I2C bus...\r\n";
|
||||
for (uint8_t i = 0; msg1[i] != '\0'; i++) {
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, msg1[i]);
|
||||
}
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TC) == RESET) {}
|
||||
|
||||
for (address = 1; address < 127; address++) {
|
||||
timeout = 0;
|
||||
|
||||
// 生成起始条件
|
||||
while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT))
|
||||
timeout++;
|
||||
if (timeout >= I2C_TIME_OUT) {
|
||||
continue; // 超时,跳过该地址
|
||||
}
|
||||
i2c_start_on_bus(I2C0);
|
||||
timeout = 0;
|
||||
|
||||
// 等待起始条件发送完成
|
||||
while (!i2c_flag_get(I2C0, I2C_FLAG_SBSEND) && (timeout < I2C_TIME_OUT))
|
||||
timeout++;
|
||||
if (timeout >= I2C_TIME_OUT) {
|
||||
continue; // 超时,跳过该地址
|
||||
}
|
||||
i2c_master_addressing(I2C0, (address << 1), I2C_TRANSMITTER);
|
||||
timeout = 0;
|
||||
|
||||
// 等待地址发送完成
|
||||
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND) && (timeout < I2C_TIME_OUT))
|
||||
timeout++;
|
||||
if (timeout < I2C_TIME_OUT) {
|
||||
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
|
||||
// printf("Found device at 0x%02X\r\n", address);
|
||||
const char* msg2_prefix = "Found device at 0x";
|
||||
for (uint8_t i = 0; msg2_prefix[i] != '\0'; i++) {
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, msg2_prefix[i]);
|
||||
}
|
||||
// 发送地址的十六进制表示
|
||||
uint8_t hex_chars[] = "0123456789ABCDEF";
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, hex_chars[(address >> 4) & 0x0F]);
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, hex_chars[address & 0x0F]);
|
||||
const char* msg2_suffix = "\r\n";
|
||||
for (uint8_t i = 0; msg2_suffix[i] != '\0'; i++) {
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, msg2_suffix[i]);
|
||||
}
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TC) == RESET) {}
|
||||
found_devices++;
|
||||
}
|
||||
|
||||
// 生成停止条件
|
||||
i2c_stop_on_bus(I2C0);
|
||||
|
||||
timeout = 0;
|
||||
|
||||
while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT))
|
||||
timeout++;
|
||||
}
|
||||
|
||||
if (found_devices == 0) {
|
||||
// printf("No I2C devices found.\r\n");
|
||||
const char* msg3 = "No I2C devices found.\r\n";
|
||||
for (uint8_t i = 0; msg3[i] != '\0'; i++) {
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, msg3[i]);
|
||||
}
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TC) == RESET) {}
|
||||
} else {
|
||||
// printf("Total %d I2C devices found.\r\n", found_devices);
|
||||
const char* msg4_prefix = "Total ";
|
||||
for (uint8_t i = 0; msg4_prefix[i] != '\0'; i++) {
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, msg4_prefix[i]);
|
||||
}
|
||||
// 发送设备数量
|
||||
if (found_devices >= 10) {
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, '0' + (found_devices / 10));
|
||||
}
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, '0' + (found_devices % 10));
|
||||
const char* msg4_suffix = " I2C devices found.\r\n";
|
||||
for (uint8_t i = 0; msg4_suffix[i] != '\0'; i++) {
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TBE) == RESET) {}
|
||||
usart_data_transmit(I2C_DEBUG_UART, msg4_suffix[i]);
|
||||
}
|
||||
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TC) == RESET) {}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief write 16-bit data to I2C device with improved state machine
|
||||
\param[in] slave_addr: 7-bit slave address
|
||||
|
Reference in New Issue
Block a user