fixing IIC

This commit is contained in:
2025-08-15 18:51:56 +08:00
parent dd7549d62b
commit 8adabcd08d
4 changed files with 154 additions and 70 deletions

147
Src/i2c.c
View File

@@ -156,6 +156,7 @@ i2c_result_t i2c_bus_reset(void) {
return I2C_RECOVERY_OK;
}
#ifdef DEBUG_VERBOSE
/**
* @brief 扫描I2C总线查找连接的设备
*
@@ -262,17 +263,24 @@ void i2c_scan(void) {
while (usart_flag_get(I2C_DEBUG_UART, USART_FLAG_TC) == RESET) {}
}
}
#endif
uint8_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2]) {
uint8_t state = I2C_START;
i2c_result_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2]) {
uint8_t state = I2C_STATE_START;
uint16_t timeout = 0;
uint8_t i2c_timeout_flag = 0;
/* parameter validation */
if (data == NULL || slave_addr > 0x7F) {
return I2C_RESULT_INVALID_PARAM;
}
/* enable acknowledge */
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
while (!(i2c_timeout_flag)) {
switch (state) {
case I2C_START:
case I2C_STATE_START:
/* i2c master sends start signal only when the bus is idle */
while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) {
timeout++;
@@ -280,16 +288,16 @@ uint8_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2])
if (timeout < I2C_TIME_OUT) {
i2c_start_on_bus(I2C0);
timeout = 0;
state = I2C_SEND_ADDRESS;
state = I2C_STATE_SEND_ADDRESS;
} else {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
#ifdef DEBUG_VERBOES
printf("i2c bus is busy in WRITE BYTE!\n");
#endif
}
break;
case I2C_SEND_ADDRESS:
case I2C_STATE_SEND_ADDRESS:
/* i2c master sends START signal successfully */
while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
@@ -297,16 +305,16 @@ uint8_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2])
if (timeout < I2C_TIME_OUT) {
i2c_master_addressing(I2C0, slave_addr << 1, I2C_TRANSMITTER);
timeout = 0;
state = I2C_CLEAR_ADDRESS_FLAG;
state = I2C_STATE_CLEAR_ADDRESS;
} else {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
#ifdef DEBUG_VERBOES
printf("i2c master sends start signal timeout in WRITE BYTE!\n");
#endif
}
break;
case I2C_CLEAR_ADDRESS_FLAG:
case I2C_STATE_CLEAR_ADDRESS:
/* address flag set means i2c slave sends ACK */
while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
@@ -314,16 +322,16 @@ uint8_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2])
if (timeout < I2C_TIME_OUT) {
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
timeout = 0;
state = I2C_TRANSMIT_DATA;
state = I2C_STATE_TRANSMIT_DATA;
} else {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
#ifdef DEBUG_VERBOES
printf("i2c master clears address flag timeout in WRITE BYTE!\n");
#endif
}
break;
case I2C_TRANSMIT_DATA:
case I2C_STATE_TRANSMIT_DATA:
/* wait until the transmit data buffer is empty */
while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) {
timeout++;
@@ -334,7 +342,7 @@ uint8_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2])
timeout = 0;
} else {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
#ifdef DEBUG_VERBOES
printf("i2c master sends data timeout in WRITE BYTE!\n");
#endif
@@ -350,7 +358,7 @@ uint8_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2])
timeout = 0;
} else {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
#ifdef DEBUG_VERBOES
printf("i2c master sends MSB data timeout in WRITE BYTE!\n");
#endif
@@ -364,10 +372,10 @@ uint8_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2])
/* send register LSB value */
i2c_data_transmit(I2C0, data[1]);
timeout = 0;
state = I2C_STOP;
state = I2C_STATE_STOP;
} else {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
#ifdef DEBUG_VERBOES
printf("i2c master sends LSB data timeout in WRITE BYTE!\n");
#endif
@@ -378,17 +386,17 @@ uint8_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2])
timeout++;
}
if (timeout < I2C_TIME_OUT) {
state = I2C_STOP;
state = I2C_STATE_STOP;
timeout = 0;
} else {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
#ifdef DEBUG_VERBOES
printf("i2c master sends data timeout in WRITE BYTE!\n");
#endif
}
break;
case I2C_STOP:
case I2C_STATE_STOP:
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
@@ -397,18 +405,18 @@ uint8_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2])
}
if (timeout < I2C_TIME_OUT) {
timeout = 0;
state = I2C_END;
state = I2C_STATE_END;
i2c_timeout_flag = I2C_OK;
} else {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
#ifdef DEBUG_VERBOES
printf("i2c master sends stop signal timeout in WRITE BYTE!\n");
#endif
}
break;
default:
state = I2C_START;
state = I2C_STATE_START;
i2c_timeout_flag = I2C_OK;
timeout = 0;
#ifdef DEBUG_VERBOES
@@ -417,14 +425,19 @@ uint8_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2])
break;
}
}
return I2C_END;
return I2C_RESULT_SUCCESS;
}
uint8_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) {
uint8_t state = I2C_START;
uint8_t read_cycle = 0;
i2c_result_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) {
// 参数检查:防止空指针和非法地址
if (data == NULL || slave_addr > 0x7F) {
return I2C_RESULT_INVALID_PARAM;
}
i2c_state_t state = I2C_STATE_START;
bool read_cycle = false;
bool i2c_timeout_flag = false;
uint16_t timeout = 0;
uint8_t i2c_timeout_flag = 0;
uint8_t number_of_byte = 2;
/* enable acknowledge */
@@ -432,7 +445,7 @@ uint8_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) {
while (!(i2c_timeout_flag)) {
switch (state) {
case I2C_START:
case I2C_STATE_START:
if (RESET == read_cycle) {
/* i2c master sends start signal only when the bus is idle */
while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) {
@@ -444,7 +457,7 @@ uint8_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) {
} else {
// i2c_bus_reset();
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
#ifdef DEBUG_VERBOES
printf("i2c bus is busy in READ!\n");
#endif
@@ -453,9 +466,9 @@ uint8_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) {
/* send the start signal */
i2c_start_on_bus(I2C0);
timeout = 0;
state = I2C_SEND_ADDRESS;
state = I2C_STATE_SEND_ADDRESS;
break;
case I2C_SEND_ADDRESS:
case I2C_STATE_SEND_ADDRESS:
/* i2c master sends START signal successfully */
while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
@@ -463,45 +476,56 @@ uint8_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) {
if (timeout < I2C_TIME_OUT) {
if (RESET == read_cycle) {
i2c_master_addressing(I2C0, slave_addr << 1, I2C_TRANSMITTER);
state = I2C_CLEAR_ADDRESS_FLAG;
state = I2C_STATE_CLEAR_ADDRESS;
} else {
i2c_master_addressing(I2C0, slave_addr << 1, I2C_RECEIVER);
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
state = I2C_CLEAR_ADDRESS_FLAG;
state = I2C_STATE_CLEAR_ADDRESS;
}
timeout = 0;
} else {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
read_cycle = RESET;
#ifdef DEBUG_VERBOES
printf("i2c master sends start signal timeout in READ!\n");
#endif
}
break;
case I2C_CLEAR_ADDRESS_FLAG:
case I2C_STATE_CLEAR_ADDRESS:
/* address flag set means i2c slave sends ACK */
while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
/* Check for NACK before clearing address flag */
if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) {
/* NACK received - slave did not acknowledge address */
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
i2c_stop_on_bus(I2C0);
#ifdef DEBUG_VERBOES
printf("i2c NACK received for address 0x%02X in read!\n", slave_addr);
#endif
return I2C_RESULT_NACK;
}
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
if ((SET == read_cycle) && (1 == number_of_byte)) {
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C0);
}
timeout = 0;
state = I2C_TRANSMIT_DATA;
state = I2C_STATE_TRANSMIT_DATA;
} else {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
read_cycle = RESET;
#ifdef DEBUG_VERBOES
printf("i2c master clears address flag timeout in READ!\n");
#endif
}
break;
case I2C_TRANSMIT_DATA:
case I2C_STATE_TRANSMIT_DATA:
if (RESET == read_cycle) {
/* wait until the transmit data buffer is empty */
while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) {
@@ -513,7 +537,7 @@ uint8_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) {
timeout = 0;
} else {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
read_cycle = RESET;
#ifdef DEBUG_VERBOES
printf("i2c master wait data buffer is empty timeout in READ!\n");
@@ -525,11 +549,11 @@ uint8_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) {
}
if (timeout < I2C_TIME_OUT) {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
read_cycle = SET;
} else {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
read_cycle = RESET;
#ifdef DEBUG_VERBOES
printf("i2c master sends register address timeout in READ!\n");
@@ -556,7 +580,7 @@ uint8_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) {
}
if (timeout > I2C_TIME_OUT) {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
read_cycle = 0;
#ifdef DEBUG_VERBOES
printf("i2c master sends data timeout in READ!\n");
@@ -564,21 +588,21 @@ uint8_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) {
}
}
timeout = 0;
state = I2C_STOP;
state = I2C_STATE_STOP;
}
break;
case I2C_STOP:
case I2C_STATE_STOP:
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
timeout = 0;
state = I2C_END;
state = I2C_STATE_END;
i2c_timeout_flag = I2C_OK;
} else {
timeout = 0;
state = I2C_START;
state = I2C_STATE_START;
read_cycle = 0;
#ifdef DEBUG_VERBOES
printf("i2c master sends stop signal timeout in READ!\n");
@@ -586,7 +610,7 @@ uint8_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) {
}
break;
default:
state = I2C_START;
state = I2C_STATE_START;
read_cycle = 0;
i2c_timeout_flag = I2C_OK;
timeout = 0;
@@ -596,5 +620,32 @@ uint8_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) {
break;
}
}
return I2C_END;
return I2C_RESULT_SUCCESS;
}
#ifdef DEBUG_VERBOSE
/*!
\brief get status string for debugging
\param[in] status: i2c_status_t value
\param[out] none
\retval const char* status string
*/
const char* i2c_get_status_string(i2c_result_t status) {
switch (status) {
case I2C_RESULT_SUCCESS:
return "SUCCESS";
case I2C_RESULT_TIMEOUT:
return "TIMEOUT";
case I2C_RESULT_NACK:
return "NACK";
case I2C_RESULT_BUS_BUSY:
return "BUS_BUSY";
case I2C_RESULT_ERROR:
return "ERROR";
case I2C_RESULT_INVALID_PARAM:
return "INVALID_PARAM";
default:
return "UNKNOWN";
}
}
#endif

View File

@@ -81,10 +81,58 @@ int main(void)
i2c_bus_reset();
#endif
i2c_scan();
ldc1612_iic_get_sensor_infomation();
// i2c_scan();
uint8_t ldc_data[2] = {0};
i2c_result_t i2c_result = i2c_read_16bits(LDC1612_ADDR, READ_MANUFACTURER_ID, ldc_data);
// const char* i2c_string = i2c_get_status_string(i2c_result);
// const char* msg1 = "I2C Status: ";
// for (uint8_t i = 0; msg1[i] != '\0'; i++) {
// while (usart_flag_get(RS485_PHY, USART_FLAG_TBE) == RESET) {}
// usart_data_transmit(RS485_PHY, msg1[i]);
// }
// // 发送i2c_string内容
// for (uint8_t i = 0; i2c_string[i] != '\0'; i++) {
// while (usart_flag_get(RS485_PHY, USART_FLAG_TBE) == RESET) {}
// usart_data_transmit(RS485_PHY, i2c_string[i]);
// }
// // 发送换行符
// const char* newline1 = "\r\n";
// for (uint8_t i = 0; newline1[i] != '\0'; i++) {
// while (usart_flag_get(RS485_PHY, USART_FLAG_TBE) == RESET) {}
// usart_data_transmit(RS485_PHY, newline1[i]);
// }
// 第二句:发送 "LDC1612 Manufacturer ID: 0x" + 十六进制数值 + "\r\n"
const char* msg2 = "LDC1612 Manufacturer ID: 0x";
for (uint8_t i = 0; msg2[i] != '\0'; i++) {
while (usart_flag_get(RS485_PHY, USART_FLAG_TBE) == RESET) {}
usart_data_transmit(RS485_PHY, msg2[i]);
}
// 发送十六进制数值
uint16_t manufacturer_id = (ldc_data[0] << 8) | ldc_data[1];
uint8_t hex_chars[] = "0123456789ABCDEF";
for (int8_t i = 3; i >= 0; i--) {
uint8_t nibble = (manufacturer_id >> (i * 4)) & 0x0F;
while (usart_flag_get(RS485_PHY, USART_FLAG_TBE) == RESET) {}
usart_data_transmit(RS485_PHY, hex_chars[nibble]);
}
// 发送换行符
const char* newline2 = "\r\n";
for (uint8_t i = 0; newline2[i] != '\0'; i++) {
while (usart_flag_get(RS485_PHY, USART_FLAG_TBE) == RESET) {}
usart_data_transmit(RS485_PHY, newline2[i]);
}
// 等待所有数据发送完成
while (usart_flag_get(RS485_PHY, USART_FLAG_TC) == RESET) {}
while(1){
command_process();