debug version

This commit is contained in:
2025-09-26 09:02:37 +08:00
parent 233576fd9a
commit fcf10601b9
6 changed files with 574 additions and 7 deletions

View File

@@ -27,6 +27,14 @@
/******************************************************************************/
#define MCU_CODE 23u
#define FW_VERSION_MAJOR 0
#define FW_VERSION_MINOR 0
#define FW_VERSION_PATCH 3
/******************************************************************************/
/* Dynamic USART Configuration Structure */
typedef struct {
uint32_t rcu_usart;

View File

@@ -107,15 +107,76 @@ i2c_result_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data
*/
i2c_result_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data);
/* Generic read/write functions with configurable length */
/*!
\brief read 16-bit data from I2C device
\param[in] slave_addr: 7-bit slave address
\brief write data to I2C device with configurable length
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: register address
\param[out] data: pointer to 2-byte data buffer
\retval i2c_result_t
\param[in] data: pointer to data buffer
\param[in] length: number of bytes to write (1-255)
\param[out] none
\retval i2c_result_t: operation result
*/
i2c_result_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data);
i2c_result_t i2c_write(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length);
/*!
\brief read data from I2C device with configurable length
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: register address
\param[out] data: pointer to data buffer
\param[in] length: number of bytes to read (1-255)
\retval i2c_result_t: operation result
*/
i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length);
/* Convenience functions for common operations */
/*!
\brief write single byte to I2C device
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: register address
\param[in] data: data byte to write
\retval i2c_result_t: operation result
*/
i2c_result_t i2c_write_8bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data);
/*!
\brief read single byte from I2C device
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: register address
\param[out] data: pointer to data byte
\retval i2c_result_t: operation result
*/
i2c_result_t i2c_read_8bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data);
/*!
\brief write 32-bit data to I2C device
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: register address
\param[in] data: pointer to 4-byte data array
\retval i2c_result_t: operation result
*/
i2c_result_t i2c_write_32bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[4]);
/*!
\brief read 32-bit data from I2C device
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: register address
\param[out] data: pointer to 4-byte data buffer
\retval i2c_result_t: operation result
*/
i2c_result_t i2c_read_32bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data);
/*!
\brief read display panel parameters (multi-byte)
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: register address
\param[out] data: pointer to data buffer
\param[in] length: number of bytes to read (1-13)
\retval i2c_result_t: operation result
*/
i2c_result_t i2c_read_display_params(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length);
#ifdef DEBUG_VERBOSE
/*!
\brief get status string for debugging
\param[in] status: i2c_result_t value
@@ -123,5 +184,6 @@ i2c_result_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data
\retval const char* status string
*/
const char* i2c_get_status_string(i2c_result_t status);
#endif
#endif //I2C_H

View File

@@ -306,6 +306,7 @@ void handle_command(const uint8_t *frame, uint8_t len) {
case 2u: // M2: disable sensor report
set_eddy_sensor_report_status(false);
send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok));
return;
case 3u:
@@ -314,12 +315,26 @@ void handle_command(const uint8_t *frame, uint8_t len) {
case 4u:
set_temp_sensor_report_status(false);
send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok));
return;
// case 201u: // M201命令
// send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok));
// return;
case 999u: //M999: 输出固件版本号vMCU_CODE.FW_VERSION_MAJOR.FW_VERSION_MINOR.FW_VERSION_PATCH
char version_str[16];
int n = snprintf(version_str, sizeof(version_str), "v%u.%u.%u.%u", MCU_CODE, FW_VERSION_MAJOR, FW_VERSION_MINOR, FW_VERSION_PATCH);
send_response(RESP_TYPE_OK, (uint8_t *)version_str, (uint8_t)n);
// send_response(RESP_TYPE_OK, (uint8_t *)"v23.0.0.3", 9);
return;
case 9999u:
// M9999: 重启系统
__disable_irq(); // 关闭全局中断GD32E230 CMSIS标准函数
nvic_system_reset(); // 系统复位GD32E230标准库函数
break;
default:
// 其它无参数命令在此扩展示例M100处理逻辑该如何待定
// send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok));

481
Src/i2c.c
View File

@@ -649,6 +649,487 @@ i2c_result_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data
return I2C_RESULT_TIMEOUT;
}
/*!
\brief write data to I2C device with configurable length
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: register address
\param[in] data: pointer to data buffer
\param[in] length: number of bytes to write (1-255)
\param[out] none
\retval i2c_result_t: operation result
*/
i2c_result_t i2c_write(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length) {
i2c_state_t state = I2C_STATE_START;
uint16_t timeout = 0;
uint8_t retry_count = 0;
uint8_t data_index = 0;
/* parameter validation */
if (data == NULL || slave_addr > 0x7F || length == 0) {
return I2C_RESULT_INVALID_PARAM;
}
while (retry_count < I2C_MAX_RETRY) {
switch (state) {
case I2C_STATE_START:
timeout = 0;
data_index = 0;
/* wait for bus to be idle */
while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
i2c_start_on_bus(I2C0);
timeout = 0;
state = I2C_STATE_SEND_ADDRESS;
break;
case I2C_STATE_SEND_ADDRESS:
/* wait for start condition to be sent. SBSEND flag */
while((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
/* send slave address */
i2c_master_addressing(I2C0, slave_addr << 1, I2C_TRANSMITTER);
timeout = 0;
state = I2C_STATE_CLEAR_ADDRESS;
break;
case I2C_STATE_CLEAR_ADDRESS:
/* wait for address to be acknowledged.ADDSEND set means i2c slave sends ACK */
while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (!i2c_flag_get(I2C0, I2C_FLAG_AERR)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
} else if (i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) {
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
timeout = 0;
state = I2C_STATE_TRANSMIT_REG;
break;
} else {
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
timeout = 0;
#ifdef DEBUG_VERBOSE
printf("IIC write failed for Error Slave Address. \n");
#endif
return I2C_RESULT_NACK;
}
case I2C_STATE_TRANSMIT_REG:
/* wait until the transmit data buffer is empty */
while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
/* send register address */
i2c_data_transmit(I2C0, reg_addr);
timeout = 0;
state = I2C_STATE_TRANSMIT_DATA;
break;
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++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
/* send data byte */
i2c_data_transmit(I2C0, data[data_index]);
data_index++;
/* check for errors */
if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) {
i2c_stop_on_bus(I2C0);
return I2C_RESULT_NACK;
} else if (i2c_flag_get(I2C0, I2C_FLAG_BERR) || i2c_flag_get(I2C0, I2C_FLAG_LOSTARB)) {
i2c_stop_on_bus(I2C0);
return I2C_RESULT_ERROR;
}
/* check if all data has been sent */
if (data_index >= length) {
/* wait until BTC bit is set for last byte */
timeout = 0;
while (!i2c_flag_get(I2C0, I2C_FLAG_BTC) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
state = I2C_STATE_STOP;
}
timeout = 0;
break;
case I2C_STATE_STOP:
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C0);
timeout = 0;
while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
/* success */
return I2C_RESULT_SUCCESS;
case I2C_STATE_ERROR:
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C0);
timeout = 0;
while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
i2c_flag_clear(I2C0, I2C_FLAG_BERR);
i2c_flag_clear(I2C0, I2C_FLAG_LOSTARB);
retry_count++;
if (retry_count >= I2C_MAX_RETRY) {
#ifdef DEBUG_VERBOSE
printf("IIC write failed after %d retries\n", I2C_MAX_RETRY);
#endif
return I2C_RESULT_ERROR;
}
/* reset state machine for retry */
state = I2C_STATE_START;
timeout = 0;
/* small delay before retry */
delay_10us(10);
break;
default:
state = I2C_STATE_START;
break;
}
}
return I2C_RESULT_TIMEOUT;
}
/*!
\brief read data from I2C device with configurable length
\param[in] slave_addr: slave device address (7-bit)
\param[in] reg_addr: register address
\param[out] data: pointer to data buffer
\param[in] length: number of bytes to read (1-255)
\retval i2c_result_t: operation result
*/
i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length) {
i2c_state_t state = I2C_STATE_START;
uint16_t timeout = 0;
uint8_t retry_count = 0;
bool write_phase = true;
uint8_t data_index = 0;
/* parameter validation */
if (data == NULL || slave_addr > 0x7F || length == 0) {
return I2C_RESULT_INVALID_PARAM;
}
/* enable acknowledge */
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
while (retry_count < (uint8_t)I2C_MAX_RETRY) {
switch (state) {
case I2C_STATE_START:
timeout = 0;
data_index = 0;
/* wait for bus to be idle */
while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
/* send start condition */
i2c_start_on_bus(I2C0);
state = I2C_STATE_SEND_ADDRESS;
timeout = 0;
break;
case I2C_STATE_SEND_ADDRESS:
/* wait for start condition to be sent */
while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
/* send slave address */
if (write_phase) {
/* write phase: send address with write bit */
i2c_master_addressing(I2C0, (slave_addr << 1), I2C_TRANSMITTER);
} else {
/* read phase: send address with read bit */
i2c_master_addressing(I2C0, (slave_addr << 1) | 0x01, I2C_RECEIVER);
}
state = I2C_STATE_CLEAR_ADDRESS;
timeout = 0;
break;
case I2C_STATE_CLEAR_ADDRESS:
/* wait for address to be acknowledged */
while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
if (write_phase) {
/* clear address flag (write phase) */
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
state = I2C_STATE_TRANSMIT_DATA;
} else {
/* read phase setup based on length */
if (length == 1) {
/* single byte read: disable ACK before clearing ADDR */
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
/* send STOP immediately after clearing ADDR for single byte */
i2c_stop_on_bus(I2C0);
} else if (length == 2) {
/* two bytes read: set POS=NEXT and disable ACK before clearing ADDR */
i2c_ackpos_config(I2C0, I2C_ACKPOS_NEXT);
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
} else {
/* multi-byte read: clear ADDR with ACK enabled */
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
}
state = I2C_STATE_RECEIVE_DATA;
}
timeout = 0;
break;
case I2C_STATE_TRANSMIT_DATA:
/* wait for transmit buffer to be empty */
while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
/* send register address */
i2c_data_transmit(I2C0, reg_addr);
state = I2C_STATE_RESTART;
timeout = 0;
break;
case I2C_STATE_RESTART:
/* wait for byte transfer complete */
while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
/* generate repeated start condition */
i2c_start_on_bus(I2C0);
/* wait for repeated start condition to be sent */
timeout = 0;
while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
/* send slave address with read bit */
i2c_master_addressing(I2C0, (slave_addr << 1), I2C_RECEIVER);
/* switch to read phase */
write_phase = false;
state = I2C_STATE_CLEAR_ADDRESS;
timeout = 0;
break;
case I2C_STATE_RECEIVE_DATA:
if (length == 1) {
/* single byte read */
while ((!i2c_flag_get(I2C0, I2C_FLAG_RBNE)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
data[0] = i2c_data_receive(I2C0);
state = I2C_STATE_STOP;
} else if (length == 2) {
/* two bytes read */
while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
/* send STOP before reading the last two bytes */
i2c_stop_on_bus(I2C0);
/* read the two bytes back-to-back */
data[0] = i2c_data_receive(I2C0);
data[1] = i2c_data_receive(I2C0);
state = I2C_STATE_STOP;
} else {
/* multi-byte read (length > 2) */
while (data_index < length) {
/* wait for RBNE (receive buffer not empty) */
while ((!i2c_flag_get(I2C0, I2C_FLAG_RBNE)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
/* special handling for last 3 bytes */
if (data_index == length - 3) {
/* wait for BTF (byte transfer finished) before reading N-2 */
while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
/* disable ACK for last 2 bytes */
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
}
/* read data byte */
data[data_index] = i2c_data_receive(I2C0);
data_index++;
/* send STOP after reading N-1 byte */
if (data_index == length - 1) {
i2c_stop_on_bus(I2C0);
}
timeout = 0;
}
state = I2C_STATE_STOP;
}
break;
case I2C_STATE_STOP:
/* wait for stop condition to complete */
while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout >= I2C_TIME_OUT) {
state = I2C_STATE_ERROR;
break;
}
/* reset ACK configuration for next operation */
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
i2c_ackpos_config(I2C0, I2C_ACKPOS_CURRENT);
/* success */
return I2C_RESULT_SUCCESS;
case I2C_STATE_ERROR:
/* send stop condition to release bus */
i2c_stop_on_bus(I2C0);
/* reset ACK configuration */
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
i2c_ackpos_config(I2C0, I2C_ACKPOS_CURRENT);
retry_count++;
if (retry_count >= I2C_MAX_RETRY) {
#ifdef DEBUG_VERBOSE
printf("I2C read failed after %d retries\n", I2C_MAX_RETRY);
#endif
return I2C_RESULT_ERROR;
}
/* reset state machine for retry */
state = I2C_STATE_START;
write_phase = true;
timeout = 0;
/* small delay before retry */
delay_10us(10);
break;
default:
state = I2C_STATE_START;
break;
}
}
return I2C_RESULT_TIMEOUT;
}
/* convenience functions for common operations */
i2c_result_t i2c_write_8bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data) {
return i2c_write(slave_addr, reg_addr, &data, 1);
}
i2c_result_t i2c_read_8bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) {
return i2c_read(slave_addr, reg_addr, data, 1);
}
i2c_result_t i2c_write_32bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[4]) {
return i2c_write(slave_addr, reg_addr, data, 4);
}
i2c_result_t i2c_read_32bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) {
return i2c_read(slave_addr, reg_addr, data, 4);
}
/* 显示面板专用函数 - 支持读取显示界面参数 */
i2c_result_t i2c_read_display_params(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length) {
/* 针对显示面板的多字节读取支持13字节的完整参数读取 */
if (length > 13) {
return I2C_RESULT_INVALID_PARAM;
}
return i2c_read(slave_addr, reg_addr, data, length);
}
#ifdef DEBUG_VERBOSE
/*!
\brief get status string for debugging

View File

@@ -60,7 +60,7 @@ int main(void)
// led_init();
printf("Flash size: %d Kbytes\n", get_flash_size());
// printf("Flash size: %d Kbytes\n", get_flash_size());
#ifdef DEBUG_VERBOSE
char hello_world[] = {"Hello World!\r\n"};

View File

@@ -86,7 +86,8 @@ tmp112a_status_t tmp112a_read_temperature(tmp112a_result_t *result) {
}
void tmp112a_get_raw_temperature_value(uint8_t *value) {
i2c_read_16bits(TMP112A_ADDR, TMP112A_TEMP_REG, value);
// i2c_read_16bits(TMP112A_ADDR, TMP112A_TEMP_REG, value);
i2c_read(TMP112A_ADDR, TMP112A_TEMP_REG, value, 2);
return;
}