generated from hulk/gd32e23x_template_cmake_vscode
debug version
This commit is contained in:
@@ -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 */
|
/* Dynamic USART Configuration Structure */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t rcu_usart;
|
uint32_t rcu_usart;
|
||||||
|
72
Inc/i2c.h
72
Inc/i2c.h
@@ -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);
|
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
|
\brief write data to I2C device with configurable length
|
||||||
\param[in] slave_addr: 7-bit slave address
|
\param[in] slave_addr: slave device address (7-bit)
|
||||||
\param[in] reg_addr: register address
|
\param[in] reg_addr: register address
|
||||||
\param[out] data: pointer to 2-byte data buffer
|
\param[in] data: pointer to data buffer
|
||||||
\retval i2c_result_t
|
\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
|
\brief get status string for debugging
|
||||||
\param[in] status: i2c_result_t value
|
\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
|
\retval const char* status string
|
||||||
*/
|
*/
|
||||||
const char* i2c_get_status_string(i2c_result_t status);
|
const char* i2c_get_status_string(i2c_result_t status);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif //I2C_H
|
#endif //I2C_H
|
||||||
|
@@ -306,6 +306,7 @@ void handle_command(const uint8_t *frame, uint8_t len) {
|
|||||||
|
|
||||||
case 2u: // M2: disable sensor report
|
case 2u: // M2: disable sensor report
|
||||||
set_eddy_sensor_report_status(false);
|
set_eddy_sensor_report_status(false);
|
||||||
|
send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 3u:
|
case 3u:
|
||||||
@@ -314,12 +315,26 @@ void handle_command(const uint8_t *frame, uint8_t len) {
|
|||||||
|
|
||||||
case 4u:
|
case 4u:
|
||||||
set_temp_sensor_report_status(false);
|
set_temp_sensor_report_status(false);
|
||||||
|
send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// case 201u: // M201命令
|
// case 201u: // M201命令
|
||||||
// send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok));
|
// send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok));
|
||||||
// return;
|
// 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:
|
default:
|
||||||
// 其它无参数命令在此扩展(示例:M100)处理逻辑该如何待定
|
// 其它无参数命令在此扩展(示例:M100)处理逻辑该如何待定
|
||||||
// send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok));
|
// send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok));
|
||||||
|
481
Src/i2c.c
481
Src/i2c.c
@@ -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;
|
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
|
#ifdef DEBUG_VERBOSE
|
||||||
/*!
|
/*!
|
||||||
\brief get status string for debugging
|
\brief get status string for debugging
|
||||||
|
@@ -60,7 +60,7 @@ int main(void)
|
|||||||
|
|
||||||
// led_init();
|
// led_init();
|
||||||
|
|
||||||
printf("Flash size: %d Kbytes\n", get_flash_size());
|
// printf("Flash size: %d Kbytes\n", get_flash_size());
|
||||||
|
|
||||||
#ifdef DEBUG_VERBOSE
|
#ifdef DEBUG_VERBOSE
|
||||||
char hello_world[] = {"Hello World!\r\n"};
|
char hello_world[] = {"Hello World!\r\n"};
|
||||||
|
@@ -86,7 +86,8 @@ tmp112a_status_t tmp112a_read_temperature(tmp112a_result_t *result) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void tmp112a_get_raw_temperature_value(uint8_t *value) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user