diff --git a/CMakeLists.txt b/CMakeLists.txt index f228a1d..e951606 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,9 @@ set(TARGET_C_SRC ${CMAKE_SOURCE_DIR}/src/systick.c ${CMAKE_SOURCE_DIR}/src/ultrasonic_driver.c ${CMAKE_SOURCE_DIR}/src/mlx90614.c - ${CMAKE_SOURCE_DIR}/src/RS485.c + ${CMAKE_SOURCE_DIR}/src/rs485.c + ${CMAKE_SOURCE_DIR}/src/i2c.c + ${CMAKE_SOURCE_DIR}/src/led.c ) add_executable(xlsw_3dp_ultrasonic_300K ${TARGET_C_SRC}) diff --git a/inc/RS485.h b/inc/RS485.h deleted file mode 100644 index a484aae..0000000 --- a/inc/RS485.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// Created by dell on 24-11-29. -// - -#ifndef RS485_H -#define RS485_H - -#include "gd32e23x_it.h" -#include -#include - -#define RX_BUFFER_SIZE 64 - -void process_command(char *cmd); - -#endif //RS485_H diff --git a/inc/i2c.h b/inc/i2c.h new file mode 100644 index 0000000..13caca9 --- /dev/null +++ b/inc/i2c.h @@ -0,0 +1,61 @@ +// +// Created by dell on 24-12-25. +// + +#ifndef I2C_H +#define I2C_H + +#include "gd32e23x_it.h" +#include "gd32e23x.h" +#include "systick.h" +#include "main.h" +#include +#include +#include +#include +#include + +/******************************************************************************/ + +#define I2C_SPEED 20000 +#define RCU_GPIO_I2C RCU_GPIOF +#define RCU_I2C RCU_I2C0 +#define I2C_PHY I2C0 +#define I2C_SCL_PORT GPIOF +#define I2C_SCL_PIN GPIO_PIN_1 +#define I2C_SDA_PORT GPIOF +#define I2C_SDA_PIN GPIO_PIN_0 +#define I2C_GPIO_AF GPIO_AF_1 + +/******************************************************************************/ + +#define I2C_TIME_OUT (uint16_t)(10000) +#define I2C_OK 1 +#define I2C_FAIL 0 +#define I2C_END 1 + +/******************************************************************************/ + +typedef enum { + I2C_START = 0, + I2C_SEND_ADDRESS, + I2C_CLEAR_ADDRESS_FLAG, + I2C_TRANSMIT_DATA, + I2C_STOP +} i2c_process_enum; + +/******************************************************************************/ + +void i2c_gpio_config(void); + +void i2c_config(void); + +void i2c_bus_reset(void); + +void i2c_scan(void); + +uint8_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2]); + +uint8_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data); + +#endif //I2C_H \ No newline at end of file diff --git a/inc/led.h b/inc/led.h new file mode 100644 index 0000000..9fc87ce --- /dev/null +++ b/inc/led.h @@ -0,0 +1,30 @@ +// +// Created by dell on 24-12-25. +// + +#ifndef LED_H +#define LED_H + +#include "gd32e23x_it.h" +#include "gd32e23x.h" +#include "systick.h" +#include +#include +#include +#include +#include + +/******************************************************************************/ + +#define LED_PORT GPIOA +#define LED_PIN GPIO_PIN_9 +#define LED_RCU RCU_GPIOA +#define LED_TIMER_RCU RCU_TIMER5 +#define LED_TIMER TIMER5 +#define LED_IRQ TIMER5_IRQn + +/******************************************************************************/ + +void led_config(void); + +#endif //LED_H diff --git a/inc/mlx90614.h b/inc/mlx90614.h index 4230eb0..17ae0ec 100644 --- a/inc/mlx90614.h +++ b/inc/mlx90614.h @@ -6,27 +6,19 @@ #define MLX90614_H #include "gd32e23x.h" +#include "i2c.h" +#include "gd32e23x.h" +#include "systick.h" +#include -#define I2C_SPEED 100000 -#define IR_I2C I2C0 -#define RCU_IR_GPIO RCU_GPIOF -#define RCU_I2C RCU_I2C0 -#define I2C_SCL_PORT GPIOF -#define I2C_SCL_PIN GPIO_PIN_1 -#define I2C_SDA_PORT GPIOF -#define I2C_SDA_PIN GPIO_PIN_0 -#define I2C_GPIO_AF GPIO_AF_1 +/******************************************************************************/ -#define I2C_TIME_OUT (uint16_t)(5000) +#define MLX90614_ADDR (0x5A << 1) +#define MLX90614_OBJ_TEMP_REG 0x07 +#define MLX90614_AMB_TEMP_REG 0x06 -#define SLAVE_ADDR (0x5A << 1) -#define REG_ADDR_OBJ_TEMP 0x07 -#define REG_ADDR_AMB_TEMP 0x06 +/******************************************************************************/ -/* function declarations */ -/* this function configures I2C Peripheral & GPIO AF for I2C */ -void MLX90614_I2CConfig(void); -/* this function reads object temperature */ -int MLX90614_GetObjectTemperature(void); +uint16_t mlx90614_get_objrct_temperature(void); #endif //MLX90614_H diff --git a/inc/rs485.h b/inc/rs485.h new file mode 100644 index 0000000..f714eb3 --- /dev/null +++ b/inc/rs485.h @@ -0,0 +1,59 @@ +// +// Created by dell on 24-11-29. +// + +#ifndef RS485_H +#define RS485_H + +#include "gd32e23x_it.h" +#include "gd32e23x.h" +#include "systick.h" +#include +#include +#include +#include +#include + +/******************************************************************************/ + +#define RS485_RCU RCU_USART0 +#define RS485_GPIO_RCU RCU_GPIOA +#define RS485_GPIO_PORT GPIOA +#define RS485_TX_PIN GPIO_PIN_2 +#define RS485_RX_PIN GPIO_PIN_3 +#define RS485_PHY USART0 +#define RS485_BAUDRATE 115200U +#define RS485_EN_PIN GPIO_PIN_4 + +/******************************************************************************/ + +#define RX_BUFFER_SIZE 32 + +#define US_IR_PACKAGE_HEADER 0xD5 +#define US_IR_BOARD_TYPE 0x04 +#define US_IR_PACKAGE_LENGTH 0x02 + +/******************************************************************************/ + +typedef enum +{ + VALIDATION_SUCCESS = 0, + VALIDATION_CRC_ERROR = 1, + VALIDATION_HEADER_ERROR = 2, + VALIDATION_TYPE_ERROR = 4, + VALIDATION_LENGTH_ERROR = 8 +} validation_result_t; + +/******************************************************************************/ + +void rs485_config(void); +void process_command(uint8_t* cmd, size_t length); +uint8_t calculate_crc(uint8_t data[], uint8_t data_length); +validation_result_t validate_package_crc(uint8_t* data, uint8_t data_length); +validation_result_t validate_package_header(uint8_t* data); +validation_result_t validate_package_type(uint8_t* data); +validation_result_t validate_data_length(uint8_t* data); +void ultrasonic_distance_value_report(void); +void mlx90614_tempture_value_report(void); + +#endif //RS485_H diff --git a/inc/ultrasonic_driver.h b/inc/ultrasonic_driver.h index 2a57dbc..6f757da 100644 --- a/inc/ultrasonic_driver.h +++ b/inc/ultrasonic_driver.h @@ -6,6 +6,7 @@ #define ULTRASONIC_DRIVER_H #include "gd32e23x.h" +#include "i2c.h" #define POWER_SUPPLY_12V // #define POWER_SUPPLY_24V @@ -25,23 +26,6 @@ #define ULTRASONIC_CYCLES 0x05U #define ULTRASONIC_TRAN_US 498 // (ms) -#define LED_PORT GPIOA -#define LED_PIN GPIO_PIN_9 -#define LED_RCU RCU_GPIOA -#define LED_TIMER_RCU RCU_TIMER5 -#define LED_TIMER TIMER5 -#define LED_IRQ TIMER5_IRQn - -#define USART_RCU RCU_USART0 -#define USART_GPIO_RCU RCU_GPIOA -#define USART_GPIO_PORT GPIOA -#define USART_TX_PIN GPIO_PIN_2 -#define USART_RX_PIN GPIO_PIN_3 -#define USART0_PHY USART0 -#define USART_BAUDRATE 115200U - -#define USART_EN_PIN GPIO_PIN_4 - #define US_TRAN_GPIO_RCU RCU_GPIOB #define US_TRAN_GPIO_PORT GPIOB #define US_TRAN_PIN GPIO_PIN_1 @@ -65,15 +49,12 @@ #define US_ECHO_TIMER TIMER16 #define US_ECHO_CH TIMER_CH_0 -void led_config(void); -void usart_config(void); -void UltraSonic_GPIO_Config(void); -void UltraSonic_Transmit_Config(void); -void UltraSonic_PwmOut_Cycles(const uint8_t cycles); -void UltraSonic_Transmit_Delay(const uint16_t micro_second); -void UltraSonic_ReceExti_Config(void); -void UltraSonic_EchoTimer_Config(void); -void UltraSonic_Receive_Config(void); -uint16_t UltraSonic_CalcDistance(uint32_t us_value); +void ultrasonic_gpio_config(void); +void ultrasonic_pwm_out_cycles(const uint8_t cycles); +void ultrasonic_transmit_delay(const uint16_t micro_second); +void ultrasonic_rece_exti_Config(void); +void ultrasonic_echo_timer_config(void); +void ultrasonic_receive_config(void); +uint16_t ultrasonic_calc_distance(uint32_t us_value); #endif //ULTRASONIC_DRIVER_H diff --git a/src/RS485.c b/src/RS485.c deleted file mode 100644 index 993e5a2..0000000 --- a/src/RS485.c +++ /dev/null @@ -1,35 +0,0 @@ -// -// Created by dell on 24-11-29. -// - -#include "RS485.h" -#include "gd32e23x.h" -#include "systick.h" -#include -#include - -#define MAX_CMD_SIZE 16 -#define BUFSIZE 8 - -extern uint16_t g_distance_uint16; -extern int g_temperature_int; - -void process_command(char *cmd) { - if (strncmp(cmd, "M1", 2) == 0) { - // printf("M1 -=-=- OK!\r\n"); - printf("Distance: %d\r\n", g_distance_uint16); - } else if (strncmp(cmd, "M2", 2) == 0) { - // printf("M2 -=-=- OK!\r\n"); - printf("Temperature: %d\r\n", g_temperature_int); -// } else if (strncmp(cmd, "M3", 2) == 0) { -// char *param_str = cmd + 2; // Skip "M3" -// int param = atoi(param_str + 1); // Skip "S" and convert to integer -// if (param >= 0 && param <= 100) { -// printf("M3 with parameter %d -=-=- OK!\r\n", param); -// } else { -// printf("Invalid parameter for M3 command!\r\n"); -// } - } else { - printf("Invalid Command!\r\n"); - } -} \ No newline at end of file diff --git a/src/gd32e23x_it.c b/src/gd32e23x_it.c index d02df1c..7d55f7b 100644 --- a/src/gd32e23x_it.c +++ b/src/gd32e23x_it.c @@ -38,6 +38,7 @@ OF SUCH DAMAGE. #include "systick.h" #include "ultrasonic_driver.h" #include "rs485.h" +#include "led.h" __IO uint32_t g_capture_value; @@ -164,21 +165,25 @@ void EXTI0_1_IRQHandler(void) { } void USART0_IRQHandler(void) { - if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) - { + static uint8_t rx_index = 0; + static uint8_t rx_buffer[RX_BUFFER_SIZE]; + + if (RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) { usart_interrupt_flag_clear(USART0, USART_INT_FLAG_RBNE); - uint8_t received_data = (uint8_t)usart_data_receive(USART0); + uint8_t received_data = (uint8_t) usart_data_receive(USART0); // 将接收到的数据存储到缓冲区 - if(rx_index < RX_BUFFER_SIZE - 1) { + if (rx_index < RX_BUFFER_SIZE - 1) { rx_buffer[rx_index++] = received_data; } + } - // 检查是否接收到换行符,表示指令结束 - if(received_data == '\n') { - rx_buffer[rx_index] = '\0'; // 添加字符串结束符 - process_command(rx_buffer); // 处理指令 - rx_index = 0; // 重置缓冲区索引 - } + if (RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE)) { + usart_interrupt_flag_clear(USART0, USART_INT_FLAG_IDLE); + + process_command(rx_buffer, rx_index); // 处理指令 + + rx_index = 0; // 重置缓冲区索引 + return; } } \ No newline at end of file diff --git a/src/i2c.c b/src/i2c.c new file mode 100644 index 0000000..36e9bd1 --- /dev/null +++ b/src/i2c.c @@ -0,0 +1,473 @@ +// +// Created by dell on 24-12-25. +// + +#include "i2c.h" +/*! + \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 none +*/ +void i2c_config(void) { + /* enable I2C clock */ + rcu_periph_clock_enable(RCU_I2C); + /* configure I2C clock */ + i2c_clock_config(I2C_PHY, I2C_SPEED, I2C_DTCY_2); + /* configure I2C address */ + i2c_mode_addr_config(I2C_PHY, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0xA0); + /* enable I2CX */ + i2c_enable(I2C_PHY); + /* enable acknowledge */ + i2c_ack_config(I2C_PHY, I2C_ACK_ENABLE); +} + +/*! + \brief reset I2C bus + \param[in] none + \param[out] none + \retval none +*/ +void i2c_bus_reset(void) { + i2c_deinit(I2C_PHY); + /* 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 */ + 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 */ + 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"); + + for (address = 1; address < 127; address++) { + timeout = 0; + + // 生成起始条件 + while (i2c_flag_get(I2C_PHY, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) + timeout++; + if (timeout >= I2C_TIME_OUT) { + continue; // 超时,跳过该地址 + } + i2c_start_on_bus(I2C_PHY); + timeout = 0; + + // 等待起始条件发送完成 + while (!i2c_flag_get(I2C_PHY, I2C_FLAG_SBSEND) && (timeout < I2C_TIME_OUT)) + timeout++; + if (timeout >= I2C_TIME_OUT) { + continue; // 超时,跳过该地址 + } + i2c_master_addressing(I2C_PHY, (address << 1), I2C_TRANSMITTER); + timeout = 0; + + // 等待地址发送完成 + while (!i2c_flag_get(I2C_PHY, I2C_FLAG_ADDSEND) && (timeout < I2C_TIME_OUT)) + timeout++; + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C_PHY, I2C_FLAG_ADDSEND); + printf("Found device at 0x%02X\r\n", address); + found_devices++; + } + + // 生成停止条件 + i2c_stop_on_bus(I2C_PHY); + + timeout = 0; + + while (i2c_flag_get(I2C_PHY, I2C_FLAG_STPDET) && (timeout < I2C_TIME_OUT)) + timeout++; + } + + if (found_devices == 0) { + printf("No I2C devices found.\r\n"); + } else { + printf("Total %d I2C devices found.\r\n", found_devices); + } +} + +uint8_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2]) { + uint8_t state = I2C_START; + uint16_t timeout = 0; + uint8_t i2c_timeout_flag = 0; + + /* enable acknowledge */ + i2c_ack_config(I2C_PHY, I2C_ACK_ENABLE); + while (!(i2c_timeout_flag)) { + switch (state) { + case I2C_START: + /* i2c master sends start signal only when the bus is idle */ + while (i2c_flag_get(I2C_PHY, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_start_on_bus(I2C_PHY); + timeout = 0; + state = I2C_SEND_ADDRESS; + } else { + timeout = 0; + state = I2C_START; +#ifdef DEBUG_VERBOES + printf("i2c bus is busy in WRITE BYTE!\n"); +#endif + } + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while ((!i2c_flag_get(I2C_PHY, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_master_addressing(I2C_PHY, slave_addr, I2C_TRANSMITTER); + timeout = 0; + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + timeout = 0; + state = I2C_START; +#ifdef DEBUG_VERBOES + printf("i2c master sends start signal timeout in WRITE BYTE!\n"); +#endif + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while ((!i2c_flag_get(I2C_PHY, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C_PHY, I2C_FLAG_ADDSEND); + timeout = 0; + state = I2C_TRANSMIT_DATA; + } else { + timeout = 0; + state = I2C_START; +#ifdef DEBUG_VERBOES + printf("i2c master clears address flag timeout in WRITE BYTE!\n"); +#endif + } + break; + case I2C_TRANSMIT_DATA: + /* wait until the transmit data buffer is empty */ + while ((!i2c_flag_get(I2C_PHY, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + /* send IIC register address */ + i2c_data_transmit(I2C_PHY, reg_addr); + timeout = 0; + } else { + timeout = 0; + state = I2C_START; +#ifdef DEBUG_VERBOES + printf("i2c master sends data timeout in WRITE BYTE!\n"); +#endif + } + + /* wait until BTC bit is set */ + while ((!i2c_flag_get(I2C_PHY, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + /* send register MSB value */ + i2c_data_transmit(I2C_PHY, data[0]); + timeout = 0; + } else { + timeout = 0; + state = I2C_START; +#ifdef DEBUG_VERBOES + printf("i2c master sends MSB data timeout in WRITE BYTE!\n"); +#endif + } + + /* wait until BTC bit is set */ + while ((!i2c_flag_get(I2C_PHY, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + /* send register LSB value */ + i2c_data_transmit(I2C_PHY, data[1]); + timeout = 0; + state = I2C_STOP; + } else { + timeout = 0; + state = I2C_START; +#ifdef DEBUG_VERBOES + printf("i2c master sends LSB data timeout in WRITE BYTE!\n"); +#endif + } + + /* wait until BTC bit is set */ + while ((!i2c_flag_get(I2C_PHY, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + state = I2C_STOP; + timeout = 0; + } else { + timeout = 0; + state = I2C_START; +#ifdef DEBUG_VERBOES + printf("i2c master sends data timeout in WRITE BYTE!\n"); +#endif + } + break; + case I2C_STOP: + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(I2C_PHY); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C_PHY) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + i2c_timeout_flag = I2C_OK; + } else { + timeout = 0; + state = I2C_START; +#ifdef DEBUG_VERBOES + printf("i2c master sends stop signal timeout in WRITE BYTE!\n"); +#endif + } + break; + default: + state = I2C_START; + i2c_timeout_flag = I2C_OK; + timeout = 0; +#ifdef DEBUG_VERBOES + printf("i2c master sends start signal in WRITE BYTE.\n"); +#endif + break; + } + } + return I2C_END; +} + +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; + uint16_t timeout = 0; + uint8_t i2c_timeout_flag = 0; + uint8_t number_of_byte = 2; + + /* enable acknowledge */ + i2c_ack_config(I2C_PHY, I2C_ACK_ENABLE); + + while (!(i2c_timeout_flag)) { + switch (state) { + case I2C_START: + if (RESET == read_cycle) { + /* i2c master sends start signal only when the bus is idle */ + while (i2c_flag_get(I2C_PHY, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + /* whether to send ACK or not for the next byte */ + i2c_ackpos_config(I2C_PHY, I2C_ACKPOS_NEXT); + } else { + // i2c_bus_reset(); + timeout = 0; + state = I2C_START; +#ifdef DEBUG_VERBOES + printf("i2c bus is busy in READ!\n"); +#endif + } + } + /* send the start signal */ + i2c_start_on_bus(I2C_PHY); + timeout = 0; + state = I2C_SEND_ADDRESS; + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while ((!i2c_flag_get(I2C_PHY, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + if (RESET == read_cycle) { + i2c_master_addressing(I2C_PHY, slave_addr, I2C_TRANSMITTER); + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + i2c_master_addressing(I2C_PHY, slave_addr, I2C_RECEIVER); + i2c_ack_config(I2C_PHY, I2C_ACK_DISABLE); + state = I2C_CLEAR_ADDRESS_FLAG; + } + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + read_cycle = RESET; +#ifdef DEBUG_VERBOES + printf("i2c master sends start signal timeout in READ!\n"); +#endif + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while ((!i2c_flag_get(I2C_PHY, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C_PHY, I2C_FLAG_ADDSEND); + if ((SET == read_cycle) && (1 == number_of_byte)) { + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(I2C_PHY); + } + timeout = 0; + state = I2C_TRANSMIT_DATA; + } else { + timeout = 0; + state = I2C_START; + read_cycle = RESET; +#ifdef DEBUG_VERBOES + printf("i2c master clears address flag timeout in READ!\n"); +#endif + } + break; + case I2C_TRANSMIT_DATA: + if (RESET == read_cycle) { + /* wait until the transmit data buffer is empty */ + while ((!i2c_flag_get(I2C_PHY, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + /* send the EEPROM's internal address to write to : only one byte address */ + i2c_data_transmit(I2C_PHY, reg_addr); + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + read_cycle = RESET; +#ifdef DEBUG_VERBOES + printf("i2c master wait data buffer is empty timeout in READ!\n"); +#endif + } + /* wait until BTC bit is set */ + while ((!i2c_flag_get(I2C_PHY, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_START; + read_cycle = SET; + } else { + timeout = 0; + state = I2C_START; + read_cycle = RESET; +#ifdef DEBUG_VERBOES + printf("i2c master sends register address timeout in READ!\n"); +#endif + } + } else { + while (number_of_byte) { + timeout++; + if (2 == number_of_byte) { + /* wait until BTC bit is set */ + while (!i2c_flag_get(I2C_PHY, I2C_FLAG_BTC)); + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(I2C_PHY); + } + /* wait until RBNE bit is set */ + if (i2c_flag_get(I2C_PHY, I2C_FLAG_RBNE)) { + /* read a byte from the EEPROM */ + *data = i2c_data_receive(I2C_PHY); + /* point to the next location where the byte read will be saved */ + data++; + /* decrement the read bytes counter */ + number_of_byte--; + timeout = 0; + } + if (timeout > I2C_TIME_OUT) { + timeout = 0; + state = I2C_START; + read_cycle = 0; +#ifdef DEBUG_VERBOES + printf("i2c master sends data timeout in READ!\n"); +#endif + } + } + timeout = 0; + state = I2C_STOP; + } + break; + case I2C_STOP: + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C_PHY) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + i2c_timeout_flag = I2C_OK; + } else { + timeout = 0; + state = I2C_START; + read_cycle = 0; +#ifdef DEBUG_VERBOES + printf("i2c master sends stop signal timeout in READ!\n"); +#endif + } + break; + default: + state = I2C_START; + read_cycle = 0; + i2c_timeout_flag = I2C_OK; + timeout = 0; +#ifdef DEBUG_VERBOES + printf("i2c master sends start signal in READ.\n"); +#endif + break; + } + } + return I2C_END; +} diff --git a/src/led.c b/src/led.c new file mode 100644 index 0000000..5e4fbaa --- /dev/null +++ b/src/led.c @@ -0,0 +1,32 @@ +// +// Created by dell on 24-12-25. +// + +#include "led.h" + +void led_config(void) { + rcu_periph_clock_enable(LED_RCU); + + gpio_mode_set(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_PIN); + gpio_output_options_set(LED_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED_PIN); + gpio_bit_write(LED_PORT, LED_PIN, SET); + + rcu_periph_clock_enable(LED_TIMER_RCU); + timer_deinit(LED_TIMER); + + timer_parameter_struct timer_initpara; + timer_struct_para_init(&timer_initpara); + timer_initpara.prescaler = 799; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = 999; + timer_initpara.clockdivision = TIMER_CKDIV_DIV1; + timer_init(LED_TIMER, &timer_initpara); + + timer_auto_reload_shadow_enable(LED_TIMER); + timer_interrupt_enable(LED_TIMER, TIMER_INT_UP); + + timer_enable(LED_TIMER); + + nvic_irq_enable(LED_IRQ, 2); +} diff --git a/src/main.c b/src/main.c index 64bd640..170272b 100644 --- a/src/main.c +++ b/src/main.c @@ -9,13 +9,16 @@ #include "gd32e23x.h" #include "systick.h" #include "gd32e23x_libopt.h" - #include "ultrasonic_driver.h" #include "mlx90614.h" +#include "i2c.h" +#include "led.h" +#include "rs485.h" extern uint32_t g_capture_value; + uint16_t g_distance_uint16; -int g_temperature_int; +uint16_t g_temperature_uint16; /*! \brief main function @@ -27,38 +30,36 @@ int main(void) { /* configure systick */ systick_config(); - /* configure ultrasonic board hardware */ - UltraSonic_Transmit_Config(); - UltraSonic_Receive_Config(); - MLX90614_I2CConfig(); + + i2c_gpio_config(); + i2c_config(); + + led_config(); + + rs485_config(); + + + /* configure ultrasonic board hardware */ + ultrasonic_gpio_config(); + ultrasonic_receive_config(); /* ---------- debug start ---------- */ /* ---------- debug end ---------- */ - // printf("\r\n"); - // printf("XLSW-3DP-UltraSonic Analog 300K! V0.1.14\r\n"); - // printf("\r\n"); - // - // delay_ms(2000); - while (1) { delay_ms(ULTRASONIC_TRAN_US); - UltraSonic_PwmOut_Cycles(ULTRASONIC_CYCLES); + ultrasonic_pwm_out_cycles(ULTRASONIC_CYCLES); delay_ms(2); // printf("cap_val:%ld\t", g_capture_value); if (g_capture_value <= CAPTURE_VALUE_MAX) { - g_distance_uint16 = UltraSonic_CalcDistance(g_capture_value); + g_distance_uint16 = ultrasonic_calc_distance(g_capture_value); } else { g_distance_uint16 = 0x0000; } - // const char* result = (g_capture_value <= CAPTURE_VALUE_MAX) ? "Distance: %d\t" : "Over Range\t"; - // printf(result, distance_uint16); - - // printf("Temp:%d\n", MLX90614_GetObjectTemperature()); - g_temperature_int = MLX90614_GetObjectTemperature(); + g_temperature_uint16 = mlx90614_get_objrct_temperature(); } } diff --git a/src/mlx90614.c b/src/mlx90614.c index d8c5b4d..982abe5 100644 --- a/src/mlx90614.c +++ b/src/mlx90614.c @@ -3,9 +3,6 @@ // #include "mlx90614.h" -#include "gd32e23x.h" -#include "systick.h" -#include /** * @brief This function configure the I2C peripheral & GPIO @@ -13,24 +10,41 @@ * @param[out] none * @retval None */ -void MLX90614_I2CConfig(void) { - rcu_periph_clock_enable(RCU_IR_GPIO); - rcu_periph_clock_enable(RCU_I2C); +// void MLX90614_I2CConfig(void) { +// rcu_periph_clock_enable(RCU_IR_GPIO); +// rcu_periph_clock_enable(RCU_I2C); +// +// 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_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); +// +// i2c_clock_config(IR_I2C, I2C_SPEED, I2C_DTCY_2); +// +// i2c_mode_addr_config(IR_I2C, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, SLAVE_ADDR); +// i2c_enable(IR_I2C); +// i2c_ack_config(IR_I2C, I2C_ACK_ENABLE); +// } - gpio_af_set(I2C_SCL_PORT, I2C_GPIO_AF, I2C_SCL_PIN); - gpio_af_set(I2C_SDA_PORT, I2C_GPIO_AF, I2C_SDA_PIN); +uint16_t mlx90614_get_objrct_temperature(void) { + uint8_t data[2] = {0}; + uint16_t tempRaw = 0; - 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); + i2c_read_16bits(MLX90614_ADDR, MLX90614_OBJ_TEMP_REG, data); - 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); + tempRaw = ((uint16_t) (data[1] << 8) | data[0]) * 2 - 27315 + 4000; + // (Data[1] << 8) | data[0] * 0.02 -273.15 为避免浮点运算,直接放大100倍 + // 4000是为了避免负数 - i2c_clock_config(IR_I2C, I2C_SPEED, I2C_DTCY_2); + if (tempRaw > 12500) { + tempRaw = 12500; + } - i2c_mode_addr_config(IR_I2C, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, SLAVE_ADDR); - i2c_enable(IR_I2C); - i2c_ack_config(IR_I2C, I2C_ACK_ENABLE); + return tempRaw; } /** @@ -39,125 +53,125 @@ void MLX90614_I2CConfig(void) { * @param[out] temp_raw: object temperature * @retval None */ -int MLX90614_GetObjectTemperature(void) { - uint8_t data[3] = {0}; - int temp_raw = 0; - uint16_t timeout = 0; - - i2c_ack_config(IR_I2C, I2C_ACK_ENABLE); - - while (i2c_flag_get(IR_I2C, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) //判断IIC总线是否忙,发送起始信号 - timeout++; - if (timeout < I2C_TIME_OUT) { - i2c_start_on_bus(IR_I2C); - timeout = 0; - } else { - printf("err\r\n"); - return -4100; // 超时返回错误 - } - - while (!i2c_flag_get(IR_I2C, I2C_FLAG_SBSEND) && (timeout < I2C_TIME_OUT)) //判断起始位是否发送,设置sensor地址并设置为写 - timeout++; - if (timeout < I2C_TIME_OUT) { - i2c_master_addressing(IR_I2C, SLAVE_ADDR, I2C_TRANSMITTER); - timeout = 0; - } else { - return -4100; // 超时返回错误 - } - - while (!i2c_flag_get(IR_I2C, I2C_FLAG_ADDSEND) && (timeout < I2C_TIME_OUT)) - timeout++; - if (timeout < I2C_TIME_OUT) { - i2c_flag_clear(IR_I2C, I2C_FLAG_ADDSEND); - timeout = 0; - } else { - return -4100; // 超时返回错误 - } - - while (!i2c_flag_get(IR_I2C, I2C_FLAG_TBE) && (timeout < I2C_TIME_OUT)) //判断地址是否发送完成,然后发送寄存器地址 - timeout++; - if (timeout < I2C_TIME_OUT) { - i2c_data_transmit(IR_I2C, REG_ADDR_OBJ_TEMP); - timeout = 0; - // i2c_start_on_bus(IR_I2C); - } else { - return -4100; // 超时返回错误 - } - - while (i2c_flag_get(IR_I2C, I2C_FLAG_BTC) && (timeout < I2C_TIME_OUT)) //判断发送缓冲器是否为空,为空后(发送完毕)重新发送开始信号 - timeout++; - if (timeout < I2C_TIME_OUT) { - i2c_start_on_bus(IR_I2C); - timeout = 0; - } else { - return -4100; // 超时返回错误 - } - - while (!i2c_flag_get(IR_I2C, I2C_FLAG_SBSEND) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - i2c_master_addressing(IR_I2C, SLAVE_ADDR, I2C_RECEIVER); - timeout = 0; - } else { - return -4100; // 超时返回错误 - } - - while (!i2c_flag_get(IR_I2C, I2C_FLAG_ADDSEND) && (timeout < I2C_TIME_OUT)) - timeout++; - if (timeout < I2C_TIME_OUT) { - i2c_flag_clear(IR_I2C, I2C_FLAG_ADDSEND); - timeout = 0; - } else { - return -4100; // 超时返回错误 - } - - // 读取第一个字节的数据 - while (!i2c_flag_get(IR_I2C, I2C_FLAG_RBNE) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - data[0] = i2c_data_receive(IR_I2C); - timeout = 0; - } else { - return -4100; // 超时返回错误 - } - - // 读取第二个字节的数据 - while (!i2c_flag_get(IR_I2C, I2C_FLAG_RBNE) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - data[1] = i2c_data_receive(IR_I2C); - timeout = 0; - } else { - return -4100; // 超时返回错误 - } - - i2c_ack_config(IR_I2C, I2C_ACK_DISABLE); // 关闭发送ACK,它会在下一个字节完成后发送NAK - - // 读取第三个字节的数据 - while (!i2c_flag_get(IR_I2C, I2C_FLAG_RBNE) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - data[2] = i2c_data_receive(IR_I2C); - timeout = 0; - } else { - return -4100; // 超时返回错误 - } - - i2c_stop_on_bus(IR_I2C); - - temp_raw = ((uint16_t) (data[1] << 8) | data[0]) * 2 - 27315; - // (Data[1] << 8) | data[0] * 0.02 -273.15 为避免浮点运算,直接放大100倍 - - if (temp_raw > 8500) { - temp_raw = 8500; - } - if (temp_raw < -4000) { - temp_raw = -4000; - } - - return temp_raw; -} +// int MLX90614_GetObjectTemperature(void) { +// uint8_t data[3] = {0}; +// int temp_raw = 0; +// uint16_t timeout = 0; +// +// i2c_ack_config(IR_I2C, I2C_ACK_ENABLE); +// +// while (i2c_flag_get(IR_I2C, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) //判断IIC总线是否忙,发送起始信号 +// timeout++; +// if (timeout < I2C_TIME_OUT) { +// i2c_start_on_bus(IR_I2C); +// timeout = 0; +// } else { +// printf("err\r\n"); +// return -4100; // 超时返回错误 +// } +// +// while (!i2c_flag_get(IR_I2C, I2C_FLAG_SBSEND) && (timeout < I2C_TIME_OUT)) //判断起始位是否发送,设置sensor地址并设置为写 +// timeout++; +// if (timeout < I2C_TIME_OUT) { +// i2c_master_addressing(IR_I2C, SLAVE_ADDR, I2C_TRANSMITTER); +// timeout = 0; +// } else { +// return -4100; // 超时返回错误 +// } +// +// while (!i2c_flag_get(IR_I2C, I2C_FLAG_ADDSEND) && (timeout < I2C_TIME_OUT)) +// timeout++; +// if (timeout < I2C_TIME_OUT) { +// i2c_flag_clear(IR_I2C, I2C_FLAG_ADDSEND); +// timeout = 0; +// } else { +// return -4100; // 超时返回错误 +// } +// +// while (!i2c_flag_get(IR_I2C, I2C_FLAG_TBE) && (timeout < I2C_TIME_OUT)) //判断地址是否发送完成,然后发送寄存器地址 +// timeout++; +// if (timeout < I2C_TIME_OUT) { +// i2c_data_transmit(IR_I2C, REG_ADDR_OBJ_TEMP); +// timeout = 0; +// // i2c_start_on_bus(IR_I2C); +// } else { +// return -4100; // 超时返回错误 +// } +// +// while (i2c_flag_get(IR_I2C, I2C_FLAG_BTC) && (timeout < I2C_TIME_OUT)) //判断发送缓冲器是否为空,为空后(发送完毕)重新发送开始信号 +// timeout++; +// if (timeout < I2C_TIME_OUT) { +// i2c_start_on_bus(IR_I2C); +// timeout = 0; +// } else { +// return -4100; // 超时返回错误 +// } +// +// while (!i2c_flag_get(IR_I2C, I2C_FLAG_SBSEND) && (timeout < I2C_TIME_OUT)) { +// timeout++; +// } +// if (timeout < I2C_TIME_OUT) { +// i2c_master_addressing(IR_I2C, SLAVE_ADDR, I2C_RECEIVER); +// timeout = 0; +// } else { +// return -4100; // 超时返回错误 +// } +// +// while (!i2c_flag_get(IR_I2C, I2C_FLAG_ADDSEND) && (timeout < I2C_TIME_OUT)) +// timeout++; +// if (timeout < I2C_TIME_OUT) { +// i2c_flag_clear(IR_I2C, I2C_FLAG_ADDSEND); +// timeout = 0; +// } else { +// return -4100; // 超时返回错误 +// } +// +// // 读取第一个字节的数据 +// while (!i2c_flag_get(IR_I2C, I2C_FLAG_RBNE) && (timeout < I2C_TIME_OUT)) { +// timeout++; +// } +// if (timeout < I2C_TIME_OUT) { +// data[0] = i2c_data_receive(IR_I2C); +// timeout = 0; +// } else { +// return -4100; // 超时返回错误 +// } +// +// // 读取第二个字节的数据 +// while (!i2c_flag_get(IR_I2C, I2C_FLAG_RBNE) && (timeout < I2C_TIME_OUT)) { +// timeout++; +// } +// if (timeout < I2C_TIME_OUT) { +// data[1] = i2c_data_receive(IR_I2C); +// timeout = 0; +// } else { +// return -4100; // 超时返回错误 +// } +// +// i2c_ack_config(IR_I2C, I2C_ACK_DISABLE); // 关闭发送ACK,它会在下一个字节完成后发送NAK +// +// // 读取第三个字节的数据 +// while (!i2c_flag_get(IR_I2C, I2C_FLAG_RBNE) && (timeout < I2C_TIME_OUT)) { +// timeout++; +// } +// if (timeout < I2C_TIME_OUT) { +// data[2] = i2c_data_receive(IR_I2C); +// timeout = 0; +// } else { +// return -4100; // 超时返回错误 +// } +// +// i2c_stop_on_bus(IR_I2C); +// +// temp_raw = ((uint16_t) (data[1] << 8) | data[0]) * 2 - 27315; +// // (Data[1] << 8) | data[0] * 0.02 -273.15 为避免浮点运算,直接放大100倍 +// +// if (temp_raw > 8500) { +// temp_raw = 8500; +// } +// if (temp_raw < -4000) { +// temp_raw = -4000; +// } +// +// return temp_raw; +// } diff --git a/src/rs485.c b/src/rs485.c new file mode 100644 index 0000000..0b42b84 --- /dev/null +++ b/src/rs485.c @@ -0,0 +1,145 @@ +// +// Created by dell on 24-11-29. +// + +#include "RS485.h" + +extern uint16_t g_distance_uint16; +extern uint16_t g_temperature_uint16; + +uint8_t package_header[3] = {0xB5, 0xF0, 0x02}; +uint8_t package_data[2] = {0}; + +void rs485_config(void) { + rcu_periph_clock_enable(RS485_GPIO_RCU); + rcu_periph_clock_enable(RS485_RCU); + + gpio_af_set(RS485_GPIO_PORT, GPIO_AF_1, GPIO_PIN_2 | GPIO_PIN_3); + + /* configure USART Tx&Rx as alternate function push-pull */ + gpio_mode_set(RS485_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, RS485_TX_PIN | RS485_RX_PIN); + gpio_output_options_set(RS485_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, RS485_TX_PIN | RS485_RX_PIN); + + /* configure RS485 EN Pin */ + gpio_mode_set(RS485_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, RS485_EN_PIN); + gpio_output_options_set(RS485_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, RS485_EN_PIN); + gpio_bit_write(RS485_GPIO_PORT, RS485_EN_PIN, SET); + + /* USART configure */ + usart_deinit(RS485_PHY); + usart_baudrate_set(RS485_PHY, RS485_BAUDRATE); + usart_receive_config(RS485_PHY, USART_RECEIVE_ENABLE); + usart_transmit_config(RS485_PHY, USART_TRANSMIT_ENABLE); + + usart_enable(RS485_PHY); + + nvic_irq_enable(USART0_IRQn, 0); + usart_interrupt_enable(RS485_PHY, USART_INT_RBNE); + usart_interrupt_enable(RS485_PHY, USART_INT_IDLE); +} + +void process_command(uint8_t *cmd, size_t length) { + char combined_str[3]; + validation_result_t validate = VALIDATION_SUCCESS; + + validate = (validate_package_header(cmd) | + validate_package_type(cmd) | + validate_data_length(cmd) | + validate_package_crc(cmd, length)); + + switch (validate) { + case VALIDATION_SUCCESS: + sprintf(combined_str, "%c%c", cmd[3], cmd[4]); + if (strcmp(combined_str, "M1") == 0) { + ultrasonic_distance_value_report(); + } else if (strcmp(combined_str, "M2") == 0) { + mlx90614_tempture_value_report(); + } else { + printf("%c%c%c%c%c%c%c", 0xB5, 0xF0, 0x03, 0x65, 0x72, 0x72, 0x3C); + return; + } + break; + case VALIDATION_CRC_ERROR: + printf("%c%c%c%c%c%c%c", 0xB5, 0xF0, 0x03, 0x65, 0x72, 0x72, 0x3F); + break; + case VALIDATION_HEADER_ERROR: + printf("%c%c%c%c%c%c%c", 0xB5, 0xF3, 0x03, 0x65, 0x72, 0x72, 0x3F); + break; + case VALIDATION_TYPE_ERROR: + printf("%c%c%c%c%c%c%c", 0xB5, 0xF4, 0x03, 0x65, 0x72, 0x72, 0x3F); + break; + case VALIDATION_LENGTH_ERROR: + printf("%c%c%c%c%c%c%c", 0xB5, 0xF2, 0x03, 0x65, 0x72, 0x72, 0x3F); + break; + default: + break; + } +} + +uint8_t calculate_crc(uint8_t data[], uint8_t data_length) { + uint8_t crc = 0; + + for (uint8_t i = 1; i < data_length - 1; i++) { + crc += data[i]; + } + + return (uint8_t) (crc & 0xFF); +} + +validation_result_t validate_package_crc(uint8_t *data, uint8_t data_length) { + if (data[data_length - 1] == calculate_crc(data, data_length) && data_length == 3 + data[2] + 1) { + return VALIDATION_SUCCESS; + } else { + return VALIDATION_CRC_ERROR; + } +} + +validation_result_t validate_package_header(uint8_t *data) { + if (data[0] == US_IR_PACKAGE_HEADER) { + return VALIDATION_SUCCESS; + } else { + return VALIDATION_HEADER_ERROR; + } +} + +validation_result_t validate_package_type(uint8_t *data) { + if (data[1] == US_IR_BOARD_TYPE) { + return VALIDATION_SUCCESS; + } else { + return VALIDATION_TYPE_ERROR; + } +} + +validation_result_t validate_data_length(uint8_t *data) { + if (data[2] == US_IR_PACKAGE_LENGTH) { + return VALIDATION_SUCCESS; + } else { + return VALIDATION_LENGTH_ERROR; + } +} + +void ultrasonic_distance_value_report(void) { + package_data[0] = (g_distance_uint16 >> 8) & 0xFF; + package_data[1] = g_distance_uint16 & 0xFF; + + uint8_t combined_data[5]; + memcpy(combined_data, package_header, 3); + memcpy(combined_data + 3, package_data, 2); + + printf("%c%c%c", package_header[0], package_header[1], package_header[2]); + printf("%c%c", package_data[0], package_data[1]); + printf("%c", calculate_crc(combined_data, 5)); +} + +void mlx90614_tempture_value_report(void) { + package_data[0] = (g_temperature_uint16 >> 8) & 0xFF; + package_data[1] = g_temperature_uint16 & 0xFF; + + uint8_t combined_data[7]; + memcpy(combined_data, package_header, 3); + memcpy(combined_data + 3, package_data, 2); + + printf("%c%c%c", package_header[0], package_header[1], package_header[2]); + printf("%c%c", package_data[0], package_data[1]); + printf("%c", calculate_crc(combined_data, 5)); +} diff --git a/src/ultrasonic_driver.c b/src/ultrasonic_driver.c index 3172129..1cf9e66 100644 --- a/src/ultrasonic_driver.c +++ b/src/ultrasonic_driver.c @@ -6,63 +6,7 @@ #include "gd32e23x.h" #include "systick.h" -void led_config(void) -{ - rcu_periph_clock_enable(LED_RCU); - - gpio_mode_set(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_PIN); - gpio_output_options_set(LED_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED_PIN); - gpio_bit_write(LED_PORT, LED_PIN, SET); - - rcu_periph_clock_enable(LED_TIMER_RCU); - timer_deinit(LED_TIMER); - - timer_parameter_struct timer_initpara; - timer_struct_para_init(&timer_initpara); - timer_initpara.prescaler = 7199; - timer_initpara.alignedmode = TIMER_COUNTER_EDGE; - timer_initpara.counterdirection = TIMER_COUNTER_UP; - timer_initpara.period = 999; - timer_initpara.clockdivision = TIMER_CKDIV_DIV1; - timer_init(LED_TIMER, &timer_initpara); - - timer_auto_reload_shadow_enable(LED_TIMER); - timer_interrupt_enable(LED_TIMER, TIMER_INT_UP); - - timer_enable(LED_TIMER); - - nvic_irq_enable(LED_IRQ, 0); -} - -void usart_config(void) -{ - rcu_periph_clock_enable(USART_GPIO_RCU); - rcu_periph_clock_enable(USART_RCU); - - gpio_af_set(USART_GPIO_PORT, GPIO_AF_1, GPIO_PIN_2 | GPIO_PIN_3); - - /* configure USART Tx&Rx as alternate function push-pull */ - gpio_mode_set(USART_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART_TX_PIN | USART_RX_PIN); - gpio_output_options_set(USART_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, USART_TX_PIN | USART_RX_PIN); - - /* configure RS485 EN Pin */ - gpio_mode_set(USART_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, USART_EN_PIN); - gpio_output_options_set(USART_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, USART_EN_PIN); - gpio_bit_write(USART_GPIO_PORT, USART_EN_PIN, SET); - - /* USART configure */ - usart_deinit(USART0_PHY); - usart_baudrate_set(USART0_PHY, USART_BAUDRATE); - usart_receive_config(USART0_PHY, USART_RECEIVE_ENABLE); - usart_transmit_config(USART0_PHY, USART_TRANSMIT_ENABLE); - - usart_enable(USART0_PHY); - - nvic_irq_enable(USART0_IRQn, 0); - usart_interrupt_enable(USART0_PHY, USART_INT_RBNE); -} - -void UltraSonic_GPIO_Config(void) +void ultrasonic_gpio_config(void) { rcu_periph_clock_enable(US_TRAN_GPIO_RCU); @@ -100,14 +44,7 @@ void UltraSonic_GPIO_Config(void) timer_interrupt_enable(US_TRAN_TIMER, TIMER_INT_UP); } -void UltraSonic_Transmit_Config(void) -{ - led_config(); - usart_config(); - UltraSonic_GPIO_Config(); -} - -void UltraSonic_PwmOut_Cycles(const uint8_t cycles) +void ultrasonic_pwm_out_cycles(const uint8_t cycles) { uint8_t current_cycle = 0; @@ -131,7 +68,7 @@ void UltraSonic_PwmOut_Cycles(const uint8_t cycles) // } } -void UltraSonic_Transmit_Delay(const uint16_t micro_second) +void ultrasonic_transmit_delay(const uint16_t micro_second) { rcu_periph_clock_enable(US_TRAN_DELAY_RCU); timer_deinit(US_TRAN_DELAY_TIMER); @@ -151,7 +88,7 @@ void UltraSonic_Transmit_Delay(const uint16_t micro_second) nvic_irq_enable(TIMER15_IRQn, 1U); } -void UltraSonic_ReceExti_Config(void) +void ultrasonic_rece_exti_Config(void) { rcu_periph_clock_enable(US_FB_GPIO_RCU); rcu_periph_clock_enable(US_FB_EXTI_RCU); @@ -166,7 +103,7 @@ void UltraSonic_ReceExti_Config(void) // exti_interrupt_enable(EXTI_0); } -void UltraSonic_EchoTimer_Config(void) +void ultrasonic_echo_timer_config(void) { rcu_periph_clock_enable(US_ECHO_RCU); timer_deinit(US_ECHO_TIMER); @@ -190,14 +127,14 @@ void UltraSonic_EchoTimer_Config(void) timer_input_capture_config(US_ECHO_TIMER, US_ECHO_CH, &timer_icinitpara); } -void UltraSonic_Receive_Config(void) +void ultrasonic_receive_config(void) { - UltraSonic_Transmit_Delay(TIME_CORRECTION_US); - UltraSonic_ReceExti_Config(); - UltraSonic_EchoTimer_Config(); + ultrasonic_transmit_delay(TIME_CORRECTION_US); + ultrasonic_rece_exti_Config(); + ultrasonic_echo_timer_config(); } -uint16_t UltraSonic_CalcDistance(uint32_t us_value) +uint16_t ultrasonic_calc_distance(uint32_t us_value) { uint16_t distace = (TIME_CORRECTION_US + us_value) * 17; /*