From 0b2416b8f02b5449d0481889f18aaabd86ae29ed Mon Sep 17 00:00:00 2001 From: Lizongdi <1210855344@qq.com> Date: Fri, 17 Apr 2026 10:39:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E5=8E=9F=E5=A7=8B=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Bingoo/base/BHBF_ROBOT.c | 127 ++ Bingoo/base/DLTuc.c | 636 ++++++ Bingoo/base/Handset_Status_Setting.c | 473 +++++ Bingoo/base/bsp_CV.pb.c | 20 + Bingoo/base/bsp_Cmd.pb.c | 12 + Bingoo/base/bsp_DLT_Log.c | 109 ++ Bingoo/base/bsp_EEPROM.c | 570 ++++++ Bingoo/base/bsp_Error.pb.c | 13 + Bingoo/base/bsp_Error_Detect.c | 31 + Bingoo/base/bsp_FDCAN.c | 334 ++++ Bingoo/base/bsp_GPIO.c | 104 + Bingoo/base/bsp_GV.pb.c | 12 + Bingoo/base/bsp_IAP.pb.c | 12 + Bingoo/base/bsp_INTERCALL.c | 41 + Bingoo/base/bsp_IO.pb.c | 12 + Bingoo/base/bsp_IV.pb.c | 12 + Bingoo/base/bsp_MB_host.c | 372 ++++ Bingoo/base/bsp_PID.pb.c | 20 + Bingoo/base/bsp_PV.pb.c | 12 + Bingoo/base/bsp_ReCmd.pb.c | 12 + Bingoo/base/bsp_TCPClient.c | 186 ++ Bingoo/base/bsp_TIMER.c | 71 + Bingoo/base/bsp_UART.c | 553 ++++++ Bingoo/base/bsp_UDP.c | 430 ++++ Bingoo/base/bsp_UpperComputer_Handler.c | 114 ++ Bingoo/base/bsp_client_setting.c | 126 ++ Bingoo/base/bsp_com_helper.c | 191 ++ Bingoo/base/bsp_cpu_flash.c | 499 +++++ Bingoo/base/bsp_decode_command.c | 473 +++++ Bingoo/base/bsp_ground_management.pb.c | 12 + Bingoo/base/bsp_qspi_w25q128.c | 488 +++++ Bingoo/base/bsp_slide_averager.c | 58 + Bingoo/base/bsp_strain_gauge.pb.c | 12 + Bingoo/base/bsp_tempature.c | 81 + Bingoo/base/change_line_control.c | 404 ++++ Bingoo/base/fsm_state.c | 51 + Bingoo/base/fsm_state_control.c | 414 ++++ Bingoo/base/motor.c | 279 +++ Bingoo/base/motors_power_action.c | 35 + Bingoo/base/msp_DAM_Relay.c | 102 + Bingoo/base/msp_MK32.pb.c | 12 + Bingoo/base/msp_MK32_1.c | 118 ++ Bingoo/base/msp_Motor.pb.c | 12 + Bingoo/base/msp_PID.c | 256 +++ Bingoo/base/msp_TL720D.c | 100 + Bingoo/base/msp_TL720D.pb.c | 12 + Bingoo/base/msp_TTMotor_ZQ.c | 426 ++++ Bingoo/base/msp_WH_LTE_7S0.c | 98 + Bingoo/base/msp_ZQ_MotorParameters.pb.c | 20 + Bingoo/base/msp_ground_management.c | 135 ++ Bingoo/base/msp_strain_gauge.c | 137 ++ Bingoo/base/paint_gun_action.c | 102 + Bingoo/base/pb_common.c | 388 ++++ Bingoo/base/pb_decode.c | 1727 +++++++++++++++++ Bingoo/base/pb_encode.c | 1000 ++++++++++ Bingoo/base/robot_move_actions.c | 1074 ++++++++++ Bingoo/base/swing_action.c | 100 + Bingoo/base/tcp_server.c | 251 +++ Bingoo/include/base/BHBF_ROBOT.h | 125 ++ Bingoo/include/base/DLTuc.h | 248 +++ Bingoo/include/base/DLTucConfig.h | 74 + Bingoo/include/base/Handset_Status_Setting.h | 73 + Bingoo/include/base/bsp_CV.pb.h | 125 ++ Bingoo/include/base/bsp_Cmd.pb.h | 80 + Bingoo/include/base/bsp_DLT_Log.h | 16 + Bingoo/include/base/bsp_EEPROM.h | 73 + Bingoo/include/base/bsp_Error.pb.h | 78 + Bingoo/include/base/bsp_Error_Detect.h | 25 + Bingoo/include/base/bsp_FDCAN.h | 84 + Bingoo/include/base/bsp_GPIO.h | 18 + Bingoo/include/base/bsp_GV.pb.h | 167 ++ Bingoo/include/base/bsp_IAP.pb.h | 58 + Bingoo/include/base/bsp_IO.pb.h | 81 + Bingoo/include/base/bsp_IV.pb.h | 147 ++ Bingoo/include/base/bsp_MB_host.h | 52 + Bingoo/include/base/bsp_PID.pb.h | 57 + Bingoo/include/base/bsp_PV.pb.h | 136 ++ Bingoo/include/base/bsp_ReCmd.pb.h | 80 + Bingoo/include/base/bsp_TCPClient.h | 63 + Bingoo/include/base/bsp_TIMER.h | 17 + Bingoo/include/base/bsp_UART.h | 109 ++ Bingoo/include/base/bsp_UDP.h | 23 + .../include/base/bsp_UpperComputer_Handler.h | 27 + Bingoo/include/base/bsp_client_setting.h | 13 + Bingoo/include/base/bsp_com_helper.h | 82 + Bingoo/include/base/bsp_cpu_flash.h | 66 + Bingoo/include/base/bsp_decode_command.h | 39 + .../include/base/bsp_ground_management.pb.h | 82 + Bingoo/include/base/bsp_include.h | 57 + Bingoo/include/base/bsp_mqtt.h | 36 + Bingoo/include/base/bsp_mqtt_pub.h | 26 + Bingoo/include/base/bsp_pb_decode_encode.h | 51 + Bingoo/include/base/bsp_qspi_w25q128.h | 107 + Bingoo/include/base/bsp_slide_averager.h | 14 + Bingoo/include/base/bsp_strain_gauge.pb.h | 61 + Bingoo/include/base/bsp_tempature.h | 19 + Bingoo/include/base/change_line_control.h | 56 + Bingoo/include/base/fsm_state.h | 44 + Bingoo/include/base/fsm_state_control.h | 18 + Bingoo/include/base/motor.h | 21 + Bingoo/include/base/motors.h | 26 + Bingoo/include/base/motors_power_action.h | 31 + Bingoo/include/base/msp_DAM_Relay.h | 15 + Bingoo/include/base/msp_Force_Sensor.h | 13 + Bingoo/include/base/msp_JTBATTERY.h | 15 + Bingoo/include/base/msp_MK32.pb.h | 99 + Bingoo/include/base/msp_MK32_1.h | 18 + Bingoo/include/base/msp_Motor.pb.h | 91 + Bingoo/include/base/msp_PID.h | 20 + Bingoo/include/base/msp_TL720D.h | 24 + Bingoo/include/base/msp_TL720D.pb.h | 72 + Bingoo/include/base/msp_TTMotor_ZQ.h | 105 + Bingoo/include/base/msp_WH_LTE_7S0.h | 21 + .../include/base/msp_ZQ_MotorParameters.pb.h | 129 ++ Bingoo/include/base/msp_ground_management.h | 21 + Bingoo/include/base/msp_strain_gauge.h | 22 + Bingoo/include/base/paint_gun_action.h | 23 + Bingoo/include/base/pb.h | 917 +++++++++ Bingoo/include/base/pb_common.h | 49 + Bingoo/include/base/pb_decode.h | 193 ++ Bingoo/include/base/pb_encode.h | 185 ++ Bingoo/include/base/readme.h | 38 + Bingoo/include/base/robot_move_actions.h | 34 + Bingoo/include/base/swing_action.h | 20 + Bingoo/include/base/tcp_server.h | 49 + Core/Inc/main.h | 49 +- Core/Src/main.c | 225 ++- 127 files changed, 18784 insertions(+), 29 deletions(-) create mode 100644 Bingoo/base/BHBF_ROBOT.c create mode 100644 Bingoo/base/DLTuc.c create mode 100644 Bingoo/base/Handset_Status_Setting.c create mode 100644 Bingoo/base/bsp_CV.pb.c create mode 100644 Bingoo/base/bsp_Cmd.pb.c create mode 100644 Bingoo/base/bsp_DLT_Log.c create mode 100644 Bingoo/base/bsp_EEPROM.c create mode 100644 Bingoo/base/bsp_Error.pb.c create mode 100644 Bingoo/base/bsp_Error_Detect.c create mode 100644 Bingoo/base/bsp_FDCAN.c create mode 100644 Bingoo/base/bsp_GPIO.c create mode 100644 Bingoo/base/bsp_GV.pb.c create mode 100644 Bingoo/base/bsp_IAP.pb.c create mode 100644 Bingoo/base/bsp_INTERCALL.c create mode 100644 Bingoo/base/bsp_IO.pb.c create mode 100644 Bingoo/base/bsp_IV.pb.c create mode 100644 Bingoo/base/bsp_MB_host.c create mode 100644 Bingoo/base/bsp_PID.pb.c create mode 100644 Bingoo/base/bsp_PV.pb.c create mode 100644 Bingoo/base/bsp_ReCmd.pb.c create mode 100644 Bingoo/base/bsp_TCPClient.c create mode 100644 Bingoo/base/bsp_TIMER.c create mode 100644 Bingoo/base/bsp_UART.c create mode 100644 Bingoo/base/bsp_UDP.c create mode 100644 Bingoo/base/bsp_UpperComputer_Handler.c create mode 100644 Bingoo/base/bsp_client_setting.c create mode 100644 Bingoo/base/bsp_com_helper.c create mode 100644 Bingoo/base/bsp_cpu_flash.c create mode 100644 Bingoo/base/bsp_decode_command.c create mode 100644 Bingoo/base/bsp_ground_management.pb.c create mode 100644 Bingoo/base/bsp_qspi_w25q128.c create mode 100644 Bingoo/base/bsp_slide_averager.c create mode 100644 Bingoo/base/bsp_strain_gauge.pb.c create mode 100644 Bingoo/base/bsp_tempature.c create mode 100644 Bingoo/base/change_line_control.c create mode 100644 Bingoo/base/fsm_state.c create mode 100644 Bingoo/base/fsm_state_control.c create mode 100644 Bingoo/base/motor.c create mode 100644 Bingoo/base/motors_power_action.c create mode 100644 Bingoo/base/msp_DAM_Relay.c create mode 100644 Bingoo/base/msp_MK32.pb.c create mode 100644 Bingoo/base/msp_MK32_1.c create mode 100644 Bingoo/base/msp_Motor.pb.c create mode 100644 Bingoo/base/msp_PID.c create mode 100644 Bingoo/base/msp_TL720D.c create mode 100644 Bingoo/base/msp_TL720D.pb.c create mode 100644 Bingoo/base/msp_TTMotor_ZQ.c create mode 100644 Bingoo/base/msp_WH_LTE_7S0.c create mode 100644 Bingoo/base/msp_ZQ_MotorParameters.pb.c create mode 100644 Bingoo/base/msp_ground_management.c create mode 100644 Bingoo/base/msp_strain_gauge.c create mode 100644 Bingoo/base/paint_gun_action.c create mode 100644 Bingoo/base/pb_common.c create mode 100644 Bingoo/base/pb_decode.c create mode 100644 Bingoo/base/pb_encode.c create mode 100644 Bingoo/base/robot_move_actions.c create mode 100644 Bingoo/base/swing_action.c create mode 100644 Bingoo/base/tcp_server.c create mode 100644 Bingoo/include/base/BHBF_ROBOT.h create mode 100644 Bingoo/include/base/DLTuc.h create mode 100644 Bingoo/include/base/DLTucConfig.h create mode 100644 Bingoo/include/base/Handset_Status_Setting.h create mode 100644 Bingoo/include/base/bsp_CV.pb.h create mode 100644 Bingoo/include/base/bsp_Cmd.pb.h create mode 100644 Bingoo/include/base/bsp_DLT_Log.h create mode 100644 Bingoo/include/base/bsp_EEPROM.h create mode 100644 Bingoo/include/base/bsp_Error.pb.h create mode 100644 Bingoo/include/base/bsp_Error_Detect.h create mode 100644 Bingoo/include/base/bsp_FDCAN.h create mode 100644 Bingoo/include/base/bsp_GPIO.h create mode 100644 Bingoo/include/base/bsp_GV.pb.h create mode 100644 Bingoo/include/base/bsp_IAP.pb.h create mode 100644 Bingoo/include/base/bsp_IO.pb.h create mode 100644 Bingoo/include/base/bsp_IV.pb.h create mode 100644 Bingoo/include/base/bsp_MB_host.h create mode 100644 Bingoo/include/base/bsp_PID.pb.h create mode 100644 Bingoo/include/base/bsp_PV.pb.h create mode 100644 Bingoo/include/base/bsp_ReCmd.pb.h create mode 100644 Bingoo/include/base/bsp_TCPClient.h create mode 100644 Bingoo/include/base/bsp_TIMER.h create mode 100644 Bingoo/include/base/bsp_UART.h create mode 100644 Bingoo/include/base/bsp_UDP.h create mode 100644 Bingoo/include/base/bsp_UpperComputer_Handler.h create mode 100644 Bingoo/include/base/bsp_client_setting.h create mode 100644 Bingoo/include/base/bsp_com_helper.h create mode 100644 Bingoo/include/base/bsp_cpu_flash.h create mode 100644 Bingoo/include/base/bsp_decode_command.h create mode 100644 Bingoo/include/base/bsp_ground_management.pb.h create mode 100644 Bingoo/include/base/bsp_include.h create mode 100644 Bingoo/include/base/bsp_mqtt.h create mode 100644 Bingoo/include/base/bsp_mqtt_pub.h create mode 100644 Bingoo/include/base/bsp_pb_decode_encode.h create mode 100644 Bingoo/include/base/bsp_qspi_w25q128.h create mode 100644 Bingoo/include/base/bsp_slide_averager.h create mode 100644 Bingoo/include/base/bsp_strain_gauge.pb.h create mode 100644 Bingoo/include/base/bsp_tempature.h create mode 100644 Bingoo/include/base/change_line_control.h create mode 100644 Bingoo/include/base/fsm_state.h create mode 100644 Bingoo/include/base/fsm_state_control.h create mode 100644 Bingoo/include/base/motor.h create mode 100644 Bingoo/include/base/motors.h create mode 100644 Bingoo/include/base/motors_power_action.h create mode 100644 Bingoo/include/base/msp_DAM_Relay.h create mode 100644 Bingoo/include/base/msp_Force_Sensor.h create mode 100644 Bingoo/include/base/msp_JTBATTERY.h create mode 100644 Bingoo/include/base/msp_MK32.pb.h create mode 100644 Bingoo/include/base/msp_MK32_1.h create mode 100644 Bingoo/include/base/msp_Motor.pb.h create mode 100644 Bingoo/include/base/msp_PID.h create mode 100644 Bingoo/include/base/msp_TL720D.h create mode 100644 Bingoo/include/base/msp_TL720D.pb.h create mode 100644 Bingoo/include/base/msp_TTMotor_ZQ.h create mode 100644 Bingoo/include/base/msp_WH_LTE_7S0.h create mode 100644 Bingoo/include/base/msp_ZQ_MotorParameters.pb.h create mode 100644 Bingoo/include/base/msp_ground_management.h create mode 100644 Bingoo/include/base/msp_strain_gauge.h create mode 100644 Bingoo/include/base/paint_gun_action.h create mode 100644 Bingoo/include/base/pb.h create mode 100644 Bingoo/include/base/pb_common.h create mode 100644 Bingoo/include/base/pb_decode.h create mode 100644 Bingoo/include/base/pb_encode.h create mode 100644 Bingoo/include/base/readme.h create mode 100644 Bingoo/include/base/robot_move_actions.h create mode 100644 Bingoo/include/base/swing_action.h create mode 100644 Bingoo/include/base/tcp_server.h diff --git a/Bingoo/base/BHBF_ROBOT.c b/Bingoo/base/BHBF_ROBOT.c new file mode 100644 index 0000000..9d340ca --- /dev/null +++ b/Bingoo/base/BHBF_ROBOT.c @@ -0,0 +1,127 @@ +/* + * BHBF_ROBOT.c + * + * Created on: Oct 26, 2023 + * Author: shiya + */ +#include "fsm.h" +#include "BHBF_ROBOT.h" +#include + + +#include "bsp_FDCAN.h" + + + + + + +int32_t* SystemTimeMiliSeconds; //似乎未用 +int32_t SystemTimeMiliCount; //2ms加一 + +int32_t* SystemErrorCode; +ErrorData* SystemErrorData; + + + + + +//Declare a CV and initialize CV +CV_struct_define CV = +{ 0 }; + + + + +//Declare a GV and initialize CV +GV_struct_define GV = +{ 0 }; + +PV_struct_define decoded_PV_variable = { 0 }; +PV_struct_define decoded_PV = { 0 }; + + +IV_struct_define IV ={ 0 }; + + + +void SET_BIT_1(int32_t* num,int32_t k) +{ + *num=((*num) | (1 << (k))); +} +void SET_BIT_0(int32_t* num,int32_t k) +{ + *num=((*num) & ~(1 << (k))); +} +int32_t Get_BIT(int32_t* num,int32_t k) +{ + return (*num >> (k)) & 1; +} + + + +void SystemTimer_Intialize() +{ + SystemTimeMiliCount=0; + GF_BSP_Interrupt_Add_CallBack( + DF_BSP_InterCall_TIM8_2ms_PeriodElapsedCallback, GF_Timer_Count); +} + +void GF_Timer_Count() +{ + SystemTimeMiliCount++; +} + + +Sys_timer_handler timer_handler_1; +Sys_timer_handler timer_handler_2; +Sys_timer_handler timer_handler_3; +Sys_timer_handler timer_handler_4; + + + +int sys_timer_1_flag_count[4]; + + + + +bool CompareTimer(int32_t DelayMiliSeconds,Sys_timer_handler * timer_handler) +{ + if(timer_handler->start_timer==1) + { + timer_handler->sys_current_timer_count=DelayMiliSeconds/2+SystemTimeMiliCount; + timer_handler->start_timer=0; + } + if(timer_handler->sys_current_timer_count<=SystemTimeMiliCount) + { + return true; + }else + { + return false; + } + +} +bool CompareTimer_Delay(int32_t Delay) +{ + + + int32_t tickstart = SystemTimeMiliCount; + int32_t wait = Delay; + + /* Add a freq to guarantee minimum wait */ + if (wait < HAL_MAX_DELAY) + { + int32_t wait = Delay; + while ((SystemTimeMiliCount - tickstart) < wait/2) + { + } + } + +} +/*m/min--->0.1m/min 其实就是×10*/ +int32_t speed_M_min_toE01_M_min(int32_t speedm_min) +{ + return speedm_min*10; +} + + diff --git a/Bingoo/base/DLTuc.c b/Bingoo/base/DLTuc.c new file mode 100644 index 0000000..b226900 --- /dev/null +++ b/Bingoo/base/DLTuc.c @@ -0,0 +1,636 @@ +/** + * @file DLTuc.c + * @author Teodor Rosolowski + * @date 1 Jul 2022 + * @brief This file is a part of DLTuc library + * + * In this source file you will find entire implementation of the DLTuc lib. + * + * Requirments: + * Around ~2kB of RAM + * Check Configuration file and defines: + * DLT_TRANSMIT_RING_BUFFER_SIZE, DLT_TRANSMIT_MAX_SINGLE_MESSAGE_SIZE + * + */ + +/* + * ******************************************************************************************* + * Includes + * ******************************************************************************************* + * */ +#include "DLTuc.h" + +#include "stdio.h" +#include "stdint.h" + +#include "stdbool.h" +#include +#include + +/* + * ******************************************************************************************* + * Local defines + * ******************************************************************************************* + * */ + +/**! +* \brief DLT_ACT_HEADER_SIZE - actual DLT header size +* \details Standard Header + Extended + TypeInfo +* Don't modify it if you aren't sure what are you doing!!! +*/ +#define DLT_ACT_HEADER_SIZE 32 + +/**! +* \brief DLT_MINIMUM_LOG_DROP_PERIOD +* \details minimum period between two drop info log +*/ +#define DLT_MINIMUM_LOG_DROP_PERIOD 200 + +/* + * ******************************************************************************************* + * Local types + * ******************************************************************************************* + * */ + +/* Prototypes to improve readability.. */ +/*typedefs for future use..*/ +// typedef +// { +// uint32_t HeaderStart; +// BaseHeaderConfig_t BaseHeaderConfig; +// uint8_t MessageCounter; +// uint16_t MessageLength; +// uint32_t EcuId; +// uint32_t TimeStamp; +// }DLT_BaseHeader_t; + +// typedef +// { +// DLT_DebugLevel_t DebugLevel; +// uint8_t NumberOfArguments; +// uint32_t AppId; +// uint32_t ContexID; +// TypeInfo_t TypeInfo; +// uint16_t Argument1; +// }DLT_ExtendedHeader_t; + + +//char DLT_LOG_ENABLE_LEVEL= 7; +char DLT_LOG_ENABLE_LEVEL= 0; +/**! + * \brief RB_Status + * \details --- + * */ +typedef enum +{ + RB_OK = 0, + RB_ERROR = 1 +} RB_Status; + +/**! + * \brief DltRingBufferTransmit_t + * \details --- + * */ +typedef struct DltRingBufferTransmit_Tag +{ + uint16_t Head; // Pointer to write + uint16_t Tail; // Pointer to read + bool readyToTransmit[DLT_TRANSMIT_RING_BUFFER_SIZE]; + uint8_t dataSize[DLT_TRANSMIT_RING_BUFFER_SIZE]; // Array to keep message size +} DltRingBufferTransmit_t; + +/**! + * \brief BluRingBufferReceive_t + * \details --- + * */ +typedef struct BluRingBufferReceive_Tag +{ + + uint16_t Head; // Pointer to write + uint16_t Tail; // Pointer to read + uint8_t MessageSize[DLT_RECEIVE_RING_BUFFER_SIZE]; // Array to keep message size + bool ReadyToRead[DLT_RECEIVE_RING_BUFFER_SIZE]; +} BluRingBufferReceive_t; + +/** + * ******************************************************************************************* + * Static variables + * ******************************************************************************************* + * */ + +/**! + * \brief ExtSerialTrDataFunctionCb + * \details --- + * */ +static void (*ExtSerialTrDataFunctionCb)(uint8_t *DltLogData, uint8_t Size); + +static void (*ExtSerialRecDataFunctionCb)(uint8_t *RecDataBuff, uint16_t Size); + +static void (*ExtInfoInjectionDataRcvdCb)(uint32_t AppId, uint32_t ConId,uint32_t ServId,uint8_t *Data, uint16_t Size); + +static uint32_t (*GetSystemTimeMs)(void); + +/**! + * \brief LogDroppedFlag + * \details --- + * */ +static bool LogDroppedFlag =false; + +static uint32_t PrevLogDropSendTime = 0u; + +static uint8_t DltLogDroppedInfo[] = "LOG DROPPED!!!"; + +static uint8_t DltLogDroppedInfoBuffer[60] = {0}; /* TODO: Remove magic number..*/ + +static uint8_t DLtLogDroppedSize = 0; + +static uint8_t ActDltMessageCounter =0; + +static DltRingBufferTransmit_t DltTrsmtRingBuffer = {.readyToTransmit[0]=true}; + +static uint8_t DltTrsmtMessagesTab[DLT_TRANSMIT_RING_BUFFER_SIZE][DLT_TRANSMIT_MAX_SINGLE_MESSAGE_SIZE]; + +static BluRingBufferReceive_t BleMainReceiveRingBuffer; + +static uint8_t BluMainReceiveMessagesTab[DLT_RECEIVE_RING_BUFFER_SIZE][DLT_REC_SINGLE_MESSAGE_MAX_SIZE]; + +static volatile uint8_t TransmitReadyStateFlag = true; /*TmpFromDma for example*/ + +/* + ********************************************************************************************* + * Prototypes of static functions + ******************************************************************************************** + */ + +/*! + ************************************************************************************************ + * \brief PrepareDltHeader + * \details A very lazy implementation of DLT Header - but it works fine + * Please refer to: https://www.autosar.org/fileadmin/user_upload/standards/foundation/1-0/AUTOSAR_PRS_DiagnosticLogAndTraceProtocol.pdf + ************************************************************************************************/ +static void PrepareDltHeader(uint8_t Level, uint32_t AppId, uint32_t ContextId, uint16_t size,uint8_t *headerAddrStart); + +/*! + ************************************************************************************************ + * \brief DLT_RB_TransmitRead Function to read data from ring buffer + * \details -- + * \param RingBuffer_t *Buf - pointer to Ring Buffer structure + * \param out MessageSize - size of the "DltLogData" (return value) + * \param out MessagePointer - pointer to the message stored in RingBuffer (return value) + * \return RB_OK if something read succesfully, otherwise RB_ERROR + * */ +static RB_Status DLT_RB_TransmitRead(DltRingBufferTransmit_t *Buf, uint8_t *MessageSize, uint8_t **MessagePointer); + +/*! + ************************************************************************************************ + * \brief DLT_RB_GetNextWriteIndex + * \details -- + * \param in RingBuffer_t *Buf - pointer to Ring Buffer structure + * \param out writeIndex - next index where DLT data should be stored, can be used only if fun return "RB_OK" + * \return RB_OK if index available, otherwise RB_ERROR + ************************************************************************************************/ +static RB_Status DLT_RB_GetNextWriteIndex(DltRingBufferTransmit_t *Buf,uint16_t *writeIndex); + +/*! + ************************************************************************************************ + * \brief DLT_RB_Receive_GetNextMessageAddress + * \details Function used to work with DMA - direct write to ring buffer by DMA + * \param in Buf - + * \param in WriteAddress - + ************************************************************************************************/ +static RB_Status DLT_RB_Receive_GetNextMessageAddress(BluRingBufferReceive_t *Buf, uint8_t **WriteAddress); + +/*! + ************************************************************************************************ + * \brief DLT_RB_Receive_Read Function to read data from ring buffer + * \details -- + * \param RingBuffer_t *Buf - pointer to Ring Buffer structure + * \param out MessageSize - size of the "BleLogData" (return value) + * \param out MessagePointer - pointer to the message stored in RingBuffer (return value) + * + * */ +static RB_Status DLT_RB_Receive_Read(BluRingBufferReceive_t *Buf, uint8_t *MessageSize, uint8_t **MessagePointer); + +/* + ********************************************************************************************* + * Static functions implementation + ******************************************************************************************** + */ + +static RB_Status DLT_RB_Receive_GetNextMessageAddress(BluRingBufferReceive_t *Buf, uint8_t **WriteAddress) +{ + /* TODO: The implementation isn't optimal...*/ + static uint8_t DefaultBlindBuffer[DLT_REC_SINGLE_MESSAGE_MAX_SIZE]; + + /*Mark previous message as ready to read*/ + Buf->ReadyToRead[Buf->Head] = true; + + // Compute new Head pointer value of a ring buffer + uint16_t HeadTmp = (Buf->Head + 1) % DLT_RECEIVE_RING_BUFFER_SIZE; + + // Check if there is one free space ahead the Head buffer + if(HeadTmp == Buf->Tail) + { + /*Even if buffer is full data must be received somewhere to don't crush application/ dma*/ + *WriteAddress = DefaultBlindBuffer; + // There is no space in the buffer - return an error + return RB_ERROR; + } + + Buf->ReadyToRead[HeadTmp] = false; + Buf->MessageSize[HeadTmp] = DLT_RECEIVE_RING_BUFFER_SIZE; + Buf->Head = HeadTmp; + + *WriteAddress = &BluMainReceiveMessagesTab[HeadTmp][0]; + + // Everything is ok - return OK status + return RB_OK; +} + +static RB_Status DLT_RB_Receive_Read(BluRingBufferReceive_t *Buf, uint8_t *MessageSize, uint8_t **MessagePointer) +{ + if(Buf->ReadyToRead[Buf->Tail] == false) + { + /*Any message in ring buffer isn't ready to read*/ + return RB_ERROR; + } + /*Mark again as not ready to read*/ + Buf->ReadyToRead[Buf->Tail] = false; + + // Check if Tail hit Head + if(Buf->Head == Buf->Tail) + { + // If yes - there is nothing to read + return RB_ERROR; + } + + // Write current value from buffer to pointer from argument + *MessageSize = Buf->MessageSize[Buf->Tail]; + *MessagePointer = &BluMainReceiveMessagesTab[Buf->Tail][0]; + + // Calculate new Tail pointer + Buf->Tail = (Buf->Tail + 1) % DLT_RECEIVE_RING_BUFFER_SIZE; + + // Everything is ok - return OK status + return RB_OK; +} + +static RB_Status DLT_RB_TransmitRead(DltRingBufferTransmit_t *Buf, uint8_t *MessageSize, uint8_t **MessagePointer) +{ + // Check if Tail hit Head + if(Buf->Head == Buf->Tail) + { + // If yes - there is nothing to read + return RB_ERROR; + } + else if(true == Buf->readyToTransmit[Buf->Tail]) + { + // Write current value from buffer to pointer from argument + *MessageSize = Buf->dataSize[Buf->Tail]; + *MessagePointer = &DltTrsmtMessagesTab[Buf->Tail][0]; + + // Calculate new Tail pointer + Buf->Tail = (Buf->Tail + 1) % DLT_TRANSMIT_RING_BUFFER_SIZE; + // Everything is ok - return OK status + return RB_OK; + } + else + { + /* Message still not ready to transmit */ + return RB_ERROR; + } + +} + +static RB_Status DLT_RB_GetNextWriteIndex(DltRingBufferTransmit_t *Buf,uint16_t *writeIndex) +{ +DLTuc_OS_CRITICAL_START(); + // Calculate new Head pointer value + uint8_t HeadTmp = (Buf->Head + 1) % DLT_TRANSMIT_RING_BUFFER_SIZE; + + // Check if there is one free space ahead the Head buffer + if(HeadTmp == Buf->Tail) + { + DLTuc_OS_CRITICAL_END(); + // There is no space in the buffer - return an error + return RB_ERROR; + } + Buf->Head = HeadTmp; + Buf->readyToTransmit[Buf->Head] = false; + *writeIndex = Buf->Head; + DLTuc_OS_CRITICAL_END(); + + return RB_OK; +} + +static void PrepareDltHeader(uint8_t Level, uint32_t AppId, uint32_t ContextId, uint16_t size,uint8_t *headerAddrStart) +{ + uint32_t ActualTime = 0; + + if(GetSystemTimeMs != NULL) + { + ActualTime = GetSystemTimeMs() * 10U; + /*Multiply by 10 to get value in MS also in DLTViewer + *Reson: Resolution in DLT Viewer is equal: 10^-4 + */ + } + + if(size > ((UINT8_MAX -1) - DLT_ACT_HEADER_SIZE) ) + { + /*Error to handle, or please develop this function to handle input size > UINT8_MAX */ + // while(1) + // { + // /*For development phase: lock the app*/ + // } + size = size - DLT_ACT_HEADER_SIZE -1; + } + + + /*START HEADER*/ + headerAddrStart[0] = 0x44; /*'D'*/ + headerAddrStart[1] = 0x4c; /*'L'*/ + headerAddrStart[2] = 0x53; /*'S'*/ + headerAddrStart[3] = 0x01; /*'0x01'*/ + + + headerAddrStart[4] = 0x35; /*'Dlt base header config + * Use extended header - true + * MSBF - false + * With ECU ID - true + * With Seesion ID - false + * With time stamp - true + * version number -random + '*/ + + headerAddrStart[5] = ActDltMessageCounter++; /*'Message counter value '*/ + + /*TODO: - it must be fixed!!!! - Length*/ + headerAddrStart[6] = 0x00; /*Message length general*/ +// headerAddrStart[7] = 0x37; /*'Message length general '*/ + headerAddrStart[7]=28+size; /*General size */ + + + uint32_t TempEcuId = DLT_LOG_ECUID_VALUE; + /*ECU ID*/ + headerAddrStart[8]= ((uint8_t*)&TempEcuId)[3]; + headerAddrStart[9]= ((uint8_t*)&TempEcuId)[2]; + headerAddrStart[10]= ((uint8_t*)&TempEcuId)[1]; + headerAddrStart[11]= ((uint8_t*)&TempEcuId)[0]; + + /*Time stamp*/ + headerAddrStart[12]= ((uint8_t*)&ActualTime)[3]; + headerAddrStart[13]= ((uint8_t*)&ActualTime)[2]; + headerAddrStart[14]= ((uint8_t*)&ActualTime)[1]; + headerAddrStart[15]= ((uint8_t*)&ActualTime)[0]; + + /*Extended header --verbose | type serial*/ +// headerAddrStart[16]= 0x41; /**/ + headerAddrStart[16]= (Level << 4) | 1; + + /*Number of arguments*/ + headerAddrStart[17]= 0x01; /**/ + + /*App id */ + headerAddrStart[18]= ((uint8_t*)&AppId)[3]; + headerAddrStart[19]= ((uint8_t*)&AppId)[2]; + headerAddrStart[20]= ((uint8_t*)&AppId)[1]; + headerAddrStart[21]= ((uint8_t*)&AppId)[0]; + + /*Contex ID (4 bytes*/ + headerAddrStart[22]= ((uint8_t*)&ContextId)[3]; + headerAddrStart[23]= ((uint8_t*)&ContextId)[2]; + headerAddrStart[24]= ((uint8_t*)&ContextId)[1]; + headerAddrStart[25]= ((uint8_t*)&ContextId)[0]; + + /*Type info*/ + headerAddrStart[26]= 0x01; /**/ + headerAddrStart[27]= 0x82; /**/ + headerAddrStart[28]= 0x00; /**/ + headerAddrStart[29]= 0x00; /**/ + + /*Argument 1*/ + headerAddrStart[30]= size; + /* Size of the load in simplified form, please verify in documentation of DLT protcool documentation */ + headerAddrStart[31]= 0x00; /**/ +} + +/* + **************************************************************************************************** + * Exported functions implementation. + * Descriptions are added in header file + ***************************************************************************************************** + */ + +void DLTuc_RawDataReceiveDone(uint16_t Size) +{ + static uint8_t *MessageReceiveBufferAddress = NULL; + uint8_t *MessageToRead_p = NULL; + uint8_t MessageToReadSize= 0U; + + DLT_RB_Receive_GetNextMessageAddress(&BleMainReceiveRingBuffer,&MessageReceiveBufferAddress); + if(ExtSerialRecDataFunctionCb != NULL){ + ExtSerialRecDataFunctionCb(MessageReceiveBufferAddress,DLT_REC_SINGLE_MESSAGE_MAX_SIZE); + } + + /* + * The receive buffer isn't handled fully correctly, it require deeper investigation. + * However, it is possible to receive the Injection messages, and base commands if are transmitted with breakes.. + * Received DTL messages are divided by the "IDLE" irq for now.., not by the size and etc... + */ + if(DLT_RB_Receive_Read(&BleMainReceiveRingBuffer, &MessageToReadSize,&MessageToRead_p) == RB_OK) + { + if(MessageToRead_p[4] == 53) /**/ + { + /*Use Extended, with EcuId, with Timestamp, end at[15] + then Extended data as follow: + [16] ==22-? - non verbose, type: control, MSTP: fatal + [17] numOfArgs == 1 - TODO: Only 1 argument is for nowsupported!!! + [18-21] - AppId + [22-25] - ContexId + [26-29] - ServiceId + [30-33] - Size*/ + + uint32_t AppId = MessageToRead_p[21] << 24 |MessageToRead_p[20] << 16 | MessageToRead_p[19] << 8 | MessageToRead_p[18] << 0; + uint32_t RecContexId = MessageToRead_p[25] << 24 |MessageToRead_p[24] << 16 | MessageToRead_p[23] << 8 | MessageToRead_p[22] << 0; + uint32_t RecServiceId = MessageToRead_p[29] << 24 |MessageToRead_p[28] << 16 | MessageToRead_p[27] << 8 | MessageToRead_p[26] << 0; + + if(RecServiceId >= DLT_SERVICE_ID_CALLSW_CINJECTION) + { + if(NULL != ExtInfoInjectionDataRcvdCb) + { + /*MSB LSB, wtf..?, it is somehow mixed? */ + uint32_t DltDatSize = MessageToRead_p[33] << 24 | MessageToRead_p[32] << 16 | MessageToRead_p[31] << 8 | MessageToRead_p[30] << 0; + + ExtInfoInjectionDataRcvdCb(AppId,RecContexId,RecServiceId,&MessageToRead_p[34],(uint16_t)DltDatSize); + } + } + else if(RecServiceId == DLT_SERVICE_ID_SET_LOG_LEVEL) + { + uint32_t NewLogLevel = MessageToRead_p[30]; + LOG("Set new log level request: %d How you triggered it?? , not supported", NewLogLevel); + /* It is handled correctly by DLT Viewer?? */ + } + else if(RecServiceId == DLT_SERVICE_ID_SET_DEFAULT_LOG_LEVEL) + { + uint32_t NewLogLevel = MessageToRead_p[30]; + LOG("Set default log level request: %d", NewLogLevel); + + LOG("Not supported yet, I'm too lazy :)"); + } + else if(DLT_SERVICE_ID_GET_SOFTWARE_VERSION == RecServiceId) + { + LOG("ECU_SW_VERSION: %d", DLT_ECU_SW_VER); + /*TODO: The lib should send here answer of control message... */ + } + else if(DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL == RecServiceId) + { + LOG("Default log level: %d", DLT_LOG_ENABLE_LEVEL); + } + } + } +} + +void DLTuc_RegisterInjectionDataReceivedCb( + void InjectionDataRcvd(uint32_t AppId, uint32_t ConId,uint32_t ServId,uint8_t *Data, uint16_t Size)) +{ + ExtInfoInjectionDataRcvdCb = InjectionDataRcvd; +} + +void DLTuc_RegisterReceiveSerialDataFunction(void LLSerialRecDataFunctionC(uint8_t *DltLogData, uint16_t Size)) +{ + ExtSerialRecDataFunctionCb = LLSerialRecDataFunctionC; + + if(ExtSerialRecDataFunctionCb != NULL) + { + ExtSerialRecDataFunctionCb(&BluMainReceiveMessagesTab[0][0],DLT_REC_SINGLE_MESSAGE_MAX_SIZE); + } +} + +void DLTuc_RegisterTransmitSerialDataFunction(void LLSerialTrDataFunctionC(uint8_t *DltLogData, uint8_t Size)) +{ + ExtSerialTrDataFunctionCb = LLSerialTrDataFunctionC; + + /*Preapre LOG DROP Info Log*/ + /* 0x444C5443 - In Ascii code it is: DLTC. It is more convience to put magic numbers here :) */ + PrepareDltHeader(DL_ERROR,0x444C5443, 0x444C5443,sizeof(DltLogDroppedInfo),DltLogDroppedInfoBuffer); + for(int i=0; i DLT_MINIMUM_LOG_DROP_PERIOD) ) + { + /* If DLTuc will always send the DROP Message info, + * then will not read any message from RB..*/ + PrevLogDropSendTime = ActualSysTime; + LogDroppedFlag = false; + + if(ExtSerialTrDataFunctionCb != NULL) + { + ExtSerialTrDataFunctionCb(DltLogDroppedInfoBuffer, DLtLogDroppedSize); + } + return; + } + + DLTuc_OS_CRITICAL_START(); + if(DLT_RB_TransmitRead(&DltTrsmtRingBuffer,&TmpMessageSize,&TmpMessagePointer) == RB_OK) + { + if(ExtSerialTrDataFunctionCb != NULL) + { + DLTuc_OS_CRITICAL_END(); + ExtSerialTrDataFunctionCb(TmpMessagePointer, TmpMessageSize); + } + } + else + { + TransmitReadyStateFlag = true; + } + DLTuc_OS_CRITICAL_END(); +} + +void DLTuc_LogOutVarArgs(DltLogLevel_t Level, uint32_t AppId, uint32_t ContextId, uint8_t *Payload, ...) +{ + uint16_t Size; /* */ + uint8_t TmpMessageSize=0U; /* */ + uint8_t *TmpMessagePointer = NULL; /* */ + uint16_t writeIndex = 0U; /* */ + + if(DLT_RB_GetNextWriteIndex(&DltTrsmtRingBuffer,&writeIndex) != RB_OK) + { + DLTuc_OS_CRITICAL_START(); + LogDroppedFlag = true; + DLTuc_OS_CRITICAL_END(); + } + else + { + /* Put the DLT message data directly in ring buffer*/ + va_list ap; /* */ + va_start(ap, Payload); + Size = vsprintf((char *)&(DltTrsmtMessagesTab[writeIndex][DLT_ACT_HEADER_SIZE]), (char *)Payload,ap); + va_end(ap); + + Size += DLT_ACT_HEADER_SIZE; + /*Add additional zeros on the end of message - thanks to that it work stable */ + Size++; + DltTrsmtMessagesTab[writeIndex][Size] = 0U; + Size++; + DltTrsmtMessagesTab[writeIndex][Size] = 0U; + + PrepareDltHeader(Level,AppId,ContextId,Size,&(DltTrsmtMessagesTab[writeIndex][0])); + + Size = Size + DLT_ACT_HEADER_SIZE; + DltTrsmtRingBuffer.dataSize[writeIndex] = Size; + + DLTuc_OS_CRITICAL_START(); + DltTrsmtRingBuffer.readyToTransmit[writeIndex] = true; + DLTuc_OS_CRITICAL_END(); + } + + DLTuc_OS_CRITICAL_START(); + if(TransmitReadyStateFlag == true) + { + if(DLT_RB_TransmitRead(&DltTrsmtRingBuffer,&TmpMessageSize,&TmpMessagePointer) == RB_OK) + { + if(TmpMessageSize != 0U) + { + TransmitReadyStateFlag = false; + DLTuc_OS_CRITICAL_END(); + /*Log transmission must be started in this contex...*/ + /***********************************************/ + /* It may be a bug in implementation - it must be investigated.. */ + /* It's important to be aware of this fact!!*/ + /***********************************************/ + if(ExtSerialTrDataFunctionCb != NULL) + { + ExtSerialTrDataFunctionCb(TmpMessagePointer, TmpMessageSize); + } + else + { + // while(1); /*Please Register the callback...*/ + } + } + } + } + DLTuc_OS_CRITICAL_END(); +} + +void DLTuc_RegisterGetTimeStampMsCallback(uint32_t GetSysTime(void)) +{ + GetSystemTimeMs = GetSysTime; +} + + diff --git a/Bingoo/base/Handset_Status_Setting.c b/Bingoo/base/Handset_Status_Setting.c new file mode 100644 index 0000000..5718025 --- /dev/null +++ b/Bingoo/base/Handset_Status_Setting.c @@ -0,0 +1,473 @@ +/* + * @file Handset_Status_Setting.c + * @brief 遥控器状态处理、模式管理、按键/摇杆检测、参数补偿驱动文件 + * @author bm673 + * @date 2026年1月15日 + * @details 实现机器人遥控模式切换、急停检测、IO状态获取、姿态补偿等功能 + */ + +#include "Handset_Status_Setting.h" +#include "BHBF_ROBOT.h" +#include + +/*=========================== 宏定义配置 ===========================*/ +// 摇杆阈值配置 +#define ROCKER_THRESHOLD_DEFAULT 300U // 摇杆死区阈值 +#define ANGLE_DEAD_ZONE 20U // 角度死区(度) + +// 机器人运动角度判断阈值 +#define ANGLE_FORWARD_LEFT_MIN 70 +#define ANGLE_FORWARD_LEFT_MAX 110 +#define ANGLE_FORWARD_RIGHT_MIN -110 +#define ANGLE_FORWARD_RIGHT_MAX -70 +#define ANGLE_REVERSE_MIN 160 + +// 摇杆方向角度区间定义 +#define ANGLE_FORWARD_LIMIT1 70 +#define ANGLE_FORWARD_LIMIT2 110 +#define ANGLE_LEFT_LIMIT1 160 +#define ANGLE_LEFT_LIMIT2 -160 +#define ANGLE_RIGHT_LIMIT1 -20 +#define ANGLE_RIGHT_LIMIT2 20 +#define ANGLE_BACK_LIMIT1 -70 +#define ANGLE_BACK_LIMIT2 -110 + +// 姿态补偿参数配置 +#define COMP_DEADZONE 300 // 遥控器补偿生效阈值 +#define COMP_COUNT_THRESH 200 // 补偿计数阈值(400ms累加一次) +#define COMP_STEP 10 // 补偿步长 +#define COMP_LIMIT_MAX 1000 // 正向补偿最大值 +#define COMP_LIMIT_MIN -1000 // 负向补偿最大值 + +/*=========================== 静态函数声明 ===========================*/ +typedef InputEvent (*ModeEventHandler)(void); + +// 急停检测 +static inline InputEvent CheckEmergencyStop(void); +// 各模式事件处理函数 +static InputEvent GetHaltModeEvents(void); +static InputEvent GetManualModeEvents(void); +static InputEvent GetHorizontalModeEvents(void); +static InputEvent GetFlatModeEvents(void); +static InputEvent GetVerticalLeftModeEvents(void); +static InputEvent GetVerticalRightModeEvents(void); +static InputEvent GetRegionalFlatTaskEvents(void); +static InputEvent GetRegionalHorizontalTaskEvents(void); +// 辅助功能函数 +static InputEvent CheckCommonKeys(void); +static InputEvent CheckCommonKeys_to_manual(void); +static InputEvent CheckAllKeys(void); +static InputEvent CalculateRockerEvent(void); +static InputEvent CalculateRockerEvent_manual(void); +static void Update_Single_Compensation(int32_t chVal, float* pComp, int* pCnt); + +/*=========================== 全局变量 ===========================*/ +extern float left_compare_value; +extern float right_compare_value; +// 模式-事件处理函数映射表 +static const ModeEventHandler modeEventHandlers[MODE_COUNT] = { + [Halt_Mode] = GetHaltModeEvents, + [Manual_Mode] = GetManualModeEvents, + [Horizontal_Mode] = GetHorizontalModeEvents, + [Flat_Mode] = GetFlatModeEvents, + [Vertical_Mode_Left] = GetVerticalLeftModeEvents, + [Vertical_Mode_Right] = GetVerticalRightModeEvents, + [Regional_Horizontal_Automatic_Task] = GetRegionalHorizontalTaskEvents, + [Regional_Flat_Automatic_Task] = GetRegionalFlatTaskEvents, +}; + +/*=========================== 函数实现 ===========================*/ +/** + * @brief 获取机器人当前运行模式 + * @param 无 + * @return Robot_Mode 当前机器人模式枚举 + */ +Robot_Mode RobotRockerState(void) +{ + if (GV.PV.Robot_Operation_Mode <= 0 || GV.PV.Robot_Operation_Mode >= MODE_COUNT) + { + return Halt_Mode; + } + + switch (GV.PV.Robot_Operation_Mode) + { + case 0: return Halt_Mode; + case 1: return Manual_Mode; + case 2: return Horizontal_Mode; + case 3: return Flat_Mode; + case 4: return Vertical_Mode_Left; + case 5: return Vertical_Mode_Right; + case 6: return Regional_Horizontal_Automatic_Task; + case 7: return Regional_Flat_Automatic_Task; + default: return Halt_Mode; + } +} + +/** + * @brief 遥控器按键/事件主检测函数 + * @param current_mode 当前机器人模式 + * @return InputEvent 触发的输入事件 + */ +InputEvent RemoteControl_GetKeyIndex(Robot_Mode current_mode) +{ + // 安全校验 + if (current_mode < 0 || current_mode >= MODE_COUNT) + { + return INPUT_NONE; + } + + // 获取对应模式的事件处理函数并执行 + ModeEventHandler handler = modeEventHandlers[current_mode]; + return (handler != NULL) ? handler() : INPUT_NONE; +} + +/** + * @brief 通用常用按键检测(手动/水平/垂直等模式共用) + * @param 无 + * @return InputEvent 按键事件 + */ +static inline InputEvent CheckCommonKeys(void) +{ + if (P_MK32->CH7_SD == -1000) return INPUT_KEY_AUTO_WORK_UP; + if (P_MK32->CH4_SA == -1000) return INPUT_KEY_LANE_CHANGE_UP; + if (P_MK32->CH5_SB == -1000) return INPUT_KEY_FORWARD_CRUISE; + if (P_MK32->CH5_SB == 1000) return INPUT_KEY_BACKWARD_CRUISE; + + return INPUT_NONE; +} + +/** + * @brief 通用常用按键检测(手动/水平/垂直等模式共用) + * @param 无 + * @return InputEvent 按键事件 + */ +static inline InputEvent CheckCommonKeys_to_manual(void) +{ + if (P_MK32->CH7_SD == -1000) return INPUT_KEY_AUTO_WORK_UP; + if (P_MK32->CH5_SB == -1000) return INPUT_KEY_FORWARD_CRUISE; + if (P_MK32->CH5_SB == 1000) return INPUT_KEY_BACKWARD_CRUISE; + + + return INPUT_NONE; +} + +/** + * @brief 全按键检测(停机模式专用) + * @param 无 + * @return InputEvent 按键事件 + */ +static inline InputEvent CheckAllKeys(void) +{ + if (P_MK32->CH7_SD == -1000) return INPUT_KEY_AUTO_WORK_UP; + if (P_MK32->CH7_SD == 1000) return INPUT_KEY_AUTO_WORK_DOWN; + if (P_MK32->CH4_SA == -1000) return INPUT_KEY_LANE_CHANGE_UP; + if (P_MK32->CH4_SA == 1000) return INPUT_KEY_LANE_CHANGE_DOWN; + if (P_MK32->CH5_SB == -1000) return INPUT_KEY_FORWARD_CRUISE; + if (P_MK32->CH5_SB == 1000) return INPUT_KEY_BACKWARD_CRUISE; + + + return INPUT_NONE; +} + +/** + * @brief 遥控器摇杆方向计算与事件转换 + * @param 无 + * @return InputEvent 摇杆方向事件 + */ +static InputEvent CalculateRockerEvent(void) +{ + int16_t vert = P_MK32->CH2_LY_V; + int16_t hori = P_MK32->CH3_LY_H; + int16_t swing = P_MK32->CH0_RY_H; + + // 摇杆中位判断 + if ((fabs(vert) < ROCKER_THRESHOLD_DEFAULT) && (fabs(hori) < ROCKER_THRESHOLD_DEFAULT)) + { + return INPUT_ROCKER_STOP; + } + + // 角度计算 + double angle_rad = atan2(vert, hori); + int16_t angle_deg = (int16_t)(angle_rad * 180.0 / M_PI); + + // 方向判断 + if (angle_deg <= ANGLE_FORWARD_LIMIT2 && angle_deg >= ANGLE_FORWARD_LIMIT1) + { + return INPUT_ROCKER_FORWARD; + } + if (angle_deg >= ANGLE_LEFT_LIMIT1 || angle_deg <= ANGLE_LEFT_LIMIT2) + { + return INPUT_ROCKER_TURN_LEFT; + } + if (angle_deg >= ANGLE_RIGHT_LIMIT1 && angle_deg <= ANGLE_RIGHT_LIMIT2) + { + return INPUT_ROCKER_TURN_RIGHT; + } + if (angle_deg >= ANGLE_BACK_LIMIT2 && angle_deg <= ANGLE_BACK_LIMIT1) + { + return INPUT_ROCKER_BACKWARD; + } + + + return INPUT_ROCKER_STOP; +} + + + + +/** + * @brief 遥控器摇杆方向计算与事件转换(用于手动模式) + * @param 无 + * @return InputEvent 摇杆方向事件 + */ +static InputEvent CalculateRockerEvent_manual(void) +{ + int16_t vert = P_MK32->CH2_LY_V; + int16_t hori = P_MK32->CH3_LY_H; + + // 摇杆中位判断 + if ((fabs(vert) < ROCKER_THRESHOLD_DEFAULT) && (fabs(hori) < ROCKER_THRESHOLD_DEFAULT)) + { + if (P_MK32->CH4_SA == -1000) + { + return INPUT_KEY_LANE_CHANGE_UP; + } + + return INPUT_ROCKER_STOP; + } + + // 角度计算 + double angle_rad = atan2(vert, hori); + int16_t angle_deg = (int16_t)(angle_rad * 180.0 / M_PI); + + // 方向判断 + if (angle_deg <= ANGLE_FORWARD_LIMIT2 && angle_deg >= ANGLE_FORWARD_LIMIT1) + { + return INPUT_ROCKER_FORWARD; + } + if (angle_deg >= ANGLE_LEFT_LIMIT1 || angle_deg <= ANGLE_LEFT_LIMIT2) + { + return INPUT_ROCKER_TURN_LEFT; + } + if (angle_deg >= ANGLE_RIGHT_LIMIT1 && angle_deg <= ANGLE_RIGHT_LIMIT2) + { + return INPUT_ROCKER_TURN_RIGHT; + } + if (angle_deg >= ANGLE_BACK_LIMIT2 && angle_deg <= ANGLE_BACK_LIMIT1) + { + return INPUT_ROCKER_BACKWARD; + } + + + + return INPUT_ROCKER_STOP; +} +/** + * @brief 急停检测(最高优先级) + * @param 无 + * @return InputEvent 急停事件/无事件 + */ +static inline InputEvent CheckEmergencyStop(void) +{ + if (P_MK32->CH8_SE == -1000 && P_MK32->CH9_SF == -1000) + { + return EMERGENCE_STOP; + } + return INPUT_NONE; +} + +/*-------------------------- 各模式事件处理函数 --------------------------*/ +static InputEvent GetHaltModeEvents(void) +{ + InputEvent key = CheckEmergencyStop(); + if (key != INPUT_NONE) return key; + + key = CheckAllKeys(); + return (key != INPUT_NONE) ? key : CalculateRockerEvent(); +} + +static InputEvent GetManualModeEvents(void) +{ + InputEvent key = CheckEmergencyStop(); + if (key != INPUT_NONE) return key; + + key = CheckCommonKeys_to_manual(); + return (key != INPUT_NONE) ? key : CalculateRockerEvent_manual(); +} + +static InputEvent GetHorizontalModeEvents(void) +{ + InputEvent key = CheckEmergencyStop(); + if (key != INPUT_NONE) return key; + + key = CheckCommonKeys(); + return (key != INPUT_NONE) ? key : CalculateRockerEvent(); +} + +static InputEvent GetFlatModeEvents(void) +{ + InputEvent key = CheckEmergencyStop(); + if (key != INPUT_NONE) return key; + + key = CheckCommonKeys(); + return (key != INPUT_NONE) ? key : CalculateRockerEvent(); +} + +static InputEvent GetVerticalLeftModeEvents(void) +{ + InputEvent key = CheckEmergencyStop(); + if (key != INPUT_NONE) return key; + + key = CheckCommonKeys(); + return (key != INPUT_NONE) ? key : CalculateRockerEvent(); +} + +static InputEvent GetVerticalRightModeEvents(void) +{ + InputEvent key = CheckEmergencyStop(); + if (key != INPUT_NONE) return key; + + key = CheckCommonKeys(); + return (key != INPUT_NONE) ? key : CalculateRockerEvent(); +} + +static InputEvent GetRegionalHorizontalTaskEvents(void) +{ + InputEvent key = CheckEmergencyStop(); + if (key != INPUT_NONE) return key; + + if (P_MK32->CH7_SD == -1000) return INPUT_KEY_AUTO_WORK_UP; + return CalculateRockerEvent(); +} + +static InputEvent GetRegionalFlatTaskEvents(void) +{ + InputEvent key = CheckEmergencyStop(); + if (key != INPUT_NONE) return key; + + if (P_MK32->CH7_SD == -1000) return INPUT_KEY_AUTO_WORK_UP; + return CalculateRockerEvent(); +} + +/** + * @brief IO状态检测(升降控制) + * @param 无 + * @return IO_State IO状态枚举 + */ +IO_State GetIOState(void) +{ + if (P_MK32->CH1_RY_V < -300) return IO_STATE_RISE; + if (P_MK32->CH1_RY_V > 300) return IO_STATE_DESCEND; + return IO_STATE_NONE; +} + +/** + * @brief PV参数更新控制 + * @param 无 + * @return 无 + */ +void PV_control(void) +{ + GV.PV = decoded_PV_variable; + GV.Robot_Move_Speed = ((float)GV.PV.Robot_Move_Speed) / 10; + GV.LaneChangeDistance = GV.PV.Robot_Change_Lane_Distance; + GV.Vertical_Adjust = ((float)GV.PV.Robot_Vertical_Adjust) / 10; + GV.symmetricalOrNot = GV.PV.Robot_symmetricalOrNot; + GV.Robot_backMode = GV.PV.Robot_backMode; + GV.Robot_Swing_Speed = GV.PV.Robot_Swing_Speed; + GV.robot_back_distance = 10;//GV.PV.Robot_Back_Distance; +} + +/** + * @brief IV状态参数更新 + * @param 无 + * @return 无 + */ +void IV_control(void) +{ + GV.PV = decoded_PV_variable; + GV.Vertical_Adjust = ((float)GV.PV.Robot_Vertical_Adjust) / 10; + GV.symmetricalOrNot = GV.PV.Robot_symmetricalOrNot; + GV.Robot_Swing_Speed = GV.PV.Robot_Swing_Speed; + IV.SystemError = GV.SystemErrorData.Com_Error_Code; + IV.Robot_Gyro = GV.TL720DParameters.RF_Angle_Roll; + IV.Is_Online = GV.P_MK32.IsOnline; + IV.Robot_Move_Deri_Speed = GV.Left_Speed_M_min * 10; + IV.LeftCompensation = GV.Left_Compensation; + IV.RightCompensation = GV.Right_Compensation; + IV.Weld_data = (int32_t)(GV.weld_data_X*100); + IV.Weld_exist = GV.weld_exist; + IV.Present_press = GV.Now_press/10; + IV.Turn_difference = GV.turn_center_difference; + IV.left_angle = left_compare_value; + IV.right_angle = right_compare_value; +} + +/** + * @brief 单通道姿态补偿更新 + * @param chVal 遥控器通道值 + * @param pComp 补偿变量指针 + * @param pCnt 补偿计数器指针 + * @return 无 + */ +static void Update_Single_Compensation(int32_t chVal, float* pComp, int* pCnt) +{ + if (chVal > COMP_DEADZONE) + { + (*pCnt)++; + if (*pCnt > COMP_COUNT_THRESH) + { + *pComp += COMP_STEP; + *pComp = (*pComp > COMP_LIMIT_MAX) ? COMP_LIMIT_MAX : *pComp; + *pCnt = 0; + } + } + else if (chVal < -COMP_DEADZONE) + { + (*pCnt)--; + if (*pCnt < -COMP_COUNT_THRESH) + { + *pComp -= COMP_STEP; + *pComp = (*pComp < COMP_LIMIT_MIN) ? COMP_LIMIT_MIN : *pComp; + *pCnt = 0; + } + } + else + { + *pCnt = 0; + } +} + +/** + * @brief 左右轮姿态补偿总更新函数 + * @param 无 + * @return 无 + */ +void Compensation_Update(void) +{ + static int leftCnt = 0; + static int rightCnt = 0; + +// static float Left_Compensation_Degre_100 = 0; +// static float Right_Compensation_Degre_100 = 0; +// +// GV.Left_Compensation = Left_Compensation_Degre_100 / 100.0f; +// GV.Right_Compensation = Right_Compensation_Degre_100 / 100.0f; + + Update_Single_Compensation(P_MK32->CH14_LT, &GV.Left_Compensation, &leftCnt); + Update_Single_Compensation(P_MK32->CH15_RT, &GV.Right_Compensation, &rightCnt); +} + +void get_weld_data(void) +{ + GV.weld_data_X = ReadLazorData->Feature_X; + GV.weld_exist = *Weld_Out_Flag; // 16说明没有焊缝 0说明有焊缝 + if((*Weld_Out_Flag)==0) + { + GV.weld_exist = 1; // 16说明没有焊缝 0说明有焊缝 + } + else + { + GV.weld_exist = 0; + } +} diff --git a/Bingoo/base/bsp_CV.pb.c b/Bingoo/base/bsp_CV.pb.c new file mode 100644 index 0000000..525d599 --- /dev/null +++ b/Bingoo/base/bsp_CV.pb.c @@ -0,0 +1,20 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "bsp_CV.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(CV_struct_define, CV_struct_define, AUTO) + + + +#ifndef PB_CONVERT_DOUBLE_FLOAT +/* On some platforms (such as AVR), double is really float. + * To be able to encode/decode double on these platforms, you need. + * to define PB_CONVERT_DOUBLE_FLOAT in pb.h or compiler command line. + */ +PB_STATIC_ASSERT(sizeof(double) == 8, DOUBLE_MUST_BE_8_BYTES) +#endif + diff --git a/Bingoo/base/bsp_Cmd.pb.c b/Bingoo/base/bsp_Cmd.pb.c new file mode 100644 index 0000000..4354a69 --- /dev/null +++ b/Bingoo/base/bsp_Cmd.pb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "bsp_Cmd.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(Cmd, Cmd, 2) + + + diff --git a/Bingoo/base/bsp_DLT_Log.c b/Bingoo/base/bsp_DLT_Log.c new file mode 100644 index 0000000..f91da33 --- /dev/null +++ b/Bingoo/base/bsp_DLT_Log.c @@ -0,0 +1,109 @@ +/* + * bsp_DLT_Log.c + * + * Created on: Aug 8, 2024 + * Author: akeguo + */ + +#include "bsp_DLT_Log.h" + +uint32_t GetSysTime(void); +void DltInjectDataRcvd(uint32_t AppId, uint32_t ConId, uint32_t ServId, + uint8_t *Data, uint16_t Size); +void DLT_LowLevelReceiveDmaToIdle(uint8_t *rxBuf, uint16_t size); +void DLT_DataReceiveEndCallback(uint8_t *rxBuf, uint16_t Size); +void DLT_DataTransmit(uint8_t *DltLogData, uint8_t Size); + +struct UARTHandler *dLT_Log_UART_Handler; + +typedef enum _send_out_port +{ + udp = 0, serialport = 1, tcp = 3, + +} send_out_port; + +char send_out_is_udp_or_serial_port = 0; + +void dLT_Log_intialize(struct UARTHandler *Handler) +{ + + dLT_Log_UART_Handler = Handler; + dLT_Log_UART_Handler->Wait_time = 40; + Handler->dispacherController->Dispacher_Enable = 1; + //log_info("angle_encoder_intialize"); + dLT_Log_UART_Handler->UART_Decode = DLT_DataReceiveEndCallback; + + /*Register Low Level Transmit/Receive functions for DLTuc Library*/ + DLTuc_RegisterTransmitSerialDataFunction(DLT_DataTransmit); + DLTuc_RegisterReceiveSerialDataFunction(DLT_LowLevelReceiveDmaToIdle); + + DLTuc_RegisterGetTimeStampMsCallback(GetSysTime); /*Register GetSysTime function*/ + /*The function "GetSysTime" must return the time in ms*/ + + DLTuc_RegisterInjectionDataReceivedCb(DltInjectDataRcvd); + send_out_is_udp_or_serial_port = serialport; +} +//dlt log 日志配置 默认为udp发送 + +/*This CallBack was registered in main function using function: DLTuc_RegisterTransmitSerialDataFunction*/ +void DLT_DataTransmit(uint8_t *DltLogData, uint8_t Size) +{ + + if (send_out_is_udp_or_serial_port == udp) + { + //udp_dlt_send_back(DltLogData, Size); + } + else if (send_out_is_udp_or_serial_port == serialport) + { + dLT_Log_UART_Handler->AddSendList(dLT_Log_UART_Handler, DltLogData, + Size, 100, NULL); + } + else if (send_out_is_udp_or_serial_port == tcp) + { + //tcp_send_to_all_clients(DltLogData, Size);// + //tcp_add_sendList(DltLogData,Size); + } + + DLTuc_MessageTransmitDone(); + +} +/*CallBacks used by ucDltLibrary section end..*/ + +void DLT_DataReceiveEndCallback(uint8_t *rxBuf, uint16_t Size) +{ + if (Size == 3) + { + if (rxBuf[2]) + { + DLT_LOG_ENABLE_LEVEL = 7; + } + else + { + DLT_LOG_ENABLE_LEVEL = 0; + } + } + DLTuc_RawDataReceiveDone(Size); + /* + *In case of STM32 HAL lib, you have to subsitute this function using: + *void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) + */ +} +//HAL_UARTEx_RxEventCallback +void DLT_LowLevelReceiveDmaToIdle(uint8_t *rxBuf, uint16_t Size) +{ + + memcpy(rxBuf, dLT_Log_UART_Handler->Rx_Buf, Size); + +} + +void DltInjectDataRcvd(uint32_t AppId, uint32_t ConId, uint32_t ServId, + uint8_t *Data, uint16_t Size) +{ + LOG("RecInjectionData: %s, ServId: %d Size: %d", Data, ServId, Size) + +} + +uint32_t GetSysTime(void) +{ + return HAL_GetTick(); +} diff --git a/Bingoo/base/bsp_EEPROM.c b/Bingoo/base/bsp_EEPROM.c new file mode 100644 index 0000000..2d1c6f1 --- /dev/null +++ b/Bingoo/base/bsp_EEPROM.c @@ -0,0 +1,570 @@ +/* + * bsp_EEPROM.c + * + * Created on: Oct 26, 2023 + * Author: shiya + */ +#include "BSP/bsp_EEPROM.h" + +void bsp_InitI2C(void); +void i2c_Start(void); +void i2c_Stop(void); +void i2c_SendByte(uint8_t _ucByte); +uint8_t i2c_ReadByte(void); +uint8_t i2c_WaitAck(void); +void i2c_Ack(void); +void i2c_NAck(void); +uint8_t i2c_CheckDevice(uint8_t _Address); + +uint16_t App_Download_EEPROM_Addr= 1024; +/* 定义读写SCL和SDA的宏 */ +#define I2C_SCL_GPIO EEPROM_SCL_GPIO_Port +#define I2C_SDA_GPIO EEPROM_SDA_GPIO_Port +#define I2C_SCL_PIN EEPROM_SCL_Pin +#define I2C_SDA_PIN EEPROM_SDA_Pin + +#define I2C_SCL_1() I2C_SCL_GPIO->BSRR = I2C_SCL_PIN /* SCL = 1 */ +#define I2C_SCL_0() I2C_SCL_GPIO->BSRR = ((uint32_t)I2C_SCL_PIN << 16U) /* SCL = 0 */ + +#define I2C_SDA_1() I2C_SDA_GPIO->BSRR = I2C_SDA_PIN /* SDA = 1 */ +#define I2C_SDA_0() I2C_SDA_GPIO->BSRR = ((uint32_t)I2C_SDA_PIN << 16U) /* SDA = 0 */ + + +#define I2C_SDA_READ() ((I2C_SDA_GPIO->IDR & I2C_SDA_PIN) != 0) /* 读SDA口线状态 */ +#define I2C_SCL_READ() ((I2C_SCL_GPIO->IDR & I2C_SCL_PIN) != 0) /* 读SCL口线状态 */ + + + +uint8_t GF_BSP_EEPROM_Init(void) +{ + bsp_InitI2C(); + return(GF_BSP_EEPROM_CheckOK()); +} + +/* +********************************************************************************************************* +* 函 数 名: bsp_InitI2C +* 功能说明: 配置I2C总线的GPIO,采用模拟IO的方式实现 +* 形 参: 无 +* 返 回 值: 无 +********************************************************************************************************* +*/ +void bsp_InitI2C(void) +{ + GPIO_InitTypeDef gpio_init; + + + gpio_init.Mode = GPIO_MODE_OUTPUT_OD; /* 设置开漏输出 */ + gpio_init.Pull = GPIO_NOPULL; /* 上下拉电阻不使能 */ + gpio_init.Speed = GPIO_SPEED_FREQ_LOW; // GPIO_SPEED_FREQ_HIGH; /* GPIO速度等级 */ + + gpio_init.Pin = I2C_SCL_PIN; + HAL_GPIO_Init(I2C_SCL_GPIO, &gpio_init); + + gpio_init.Pin = I2C_SDA_PIN; + HAL_GPIO_Init(I2C_SDA_GPIO, &gpio_init); + + /* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */ + i2c_Stop(); +} + +/* +********************************************************************************************************* +* 函 数 名: i2c_Delay +* 功能说明: I2C总线位延迟,最快400KHz +* 形 参: 无 +* 返 回 值: 无 +********************************************************************************************************* +*/ +static void i2c_Delay(void) +{ + GF_BSP_TIMER_DelayUS(2); +} + +/* +********************************************************************************************************* +* 函 数 名: i2c_Start +* 功能说明: CPU发起I2C总线启动信号 +* 形 参: 无 +* 返 回 值: 无 +********************************************************************************************************* +*/ +void i2c_Start(void) +{ + /* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */ + I2C_SDA_1(); + I2C_SCL_1(); + i2c_Delay(); + I2C_SDA_0(); + i2c_Delay(); + + I2C_SCL_0(); + i2c_Delay(); +} + +/* +********************************************************************************************************* +* 函 数 名: i2c_Start +* 功能说明: CPU发起I2C总线停止信号 +* 形 参: 无 +* 返 回 值: 无 +********************************************************************************************************* +*/ +void i2c_Stop(void) +{ + /* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */ + I2C_SDA_0(); + i2c_Delay(); + I2C_SCL_1(); + i2c_Delay(); + I2C_SDA_1(); + i2c_Delay(); +} + +/* +********************************************************************************************************* +* 函 数 名: i2c_SendByte +* 功能说明: CPU向I2C总线设备发送8bit数据 +* 形 参: _ucByte : 等待发送的字节 +* 返 回 值: 无 +********************************************************************************************************* +*/ +void i2c_SendByte(uint8_t _ucByte) +{ + uint8_t i; + + /* 先发送字节的高位bit7 */ + for (i = 0; i < 8; i++) + { + if (_ucByte & 0x80) + { + I2C_SDA_1(); + } + else + { + I2C_SDA_0(); + } + i2c_Delay(); + I2C_SCL_1(); + i2c_Delay(); + I2C_SCL_0(); + I2C_SCL_0(); /* 2019-03-14 针对GT811电容触摸,添加一行,相当于延迟几十ns */ + if (i == 7) + { + I2C_SDA_1(); // 释放总线 + } + _ucByte <<= 1; /* 左移一个bit */ + } +} + +/* +********************************************************************************************************* +* 函 数 名: i2c_ReadByte +* 功能说明: CPU从I2C总线设备读取8bit数据 +* 形 参: 无 +* 返 回 值: 读到的数据 +********************************************************************************************************* +*/ +uint8_t i2c_ReadByte(void) +{ + uint8_t i; + uint8_t value; + + /* 读到第1个bit为数据的bit7 */ + value = 0; + for (i = 0; i < 8; i++) + { + value <<= 1; + I2C_SCL_1(); + i2c_Delay(); + if (I2C_SDA_READ()) + { + value++; + } + I2C_SCL_0(); + i2c_Delay(); + } + return value; +} + +/* +********************************************************************************************************* +* 函 数 名: i2c_WaitAck +* 功能说明: CPU产生一个时钟,并读取器件的ACK应答信号 +* 形 参: 无 +* 返 回 值: 返回0表示正确应答,1表示无器件响应 +********************************************************************************************************* +*/ +uint8_t i2c_WaitAck(void) +{ + uint8_t re; + + I2C_SDA_1(); /* CPU释放SDA总线 */ + i2c_Delay(); + I2C_SCL_1(); /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */ + i2c_Delay(); + if (I2C_SDA_READ()) /* CPU读取SDA口线状态 */ + { + re = 1; + } + else + { + re = 0; + } + I2C_SCL_0(); + i2c_Delay(); + return re; +} + +/* +********************************************************************************************************* +* 函 数 名: i2c_Ack +* 功能说明: CPU产生一个ACK信号 +* 形 参: 无 +* 返 回 值: 无 +********************************************************************************************************* +*/ +void i2c_Ack(void) +{ + I2C_SDA_0(); /* CPU驱动SDA = 0 */ + i2c_Delay(); + I2C_SCL_1(); /* CPU产生1个时钟 */ + i2c_Delay(); + I2C_SCL_0(); + i2c_Delay(); + I2C_SDA_1(); /* CPU释放SDA总线 */ + + i2c_Delay(); +} + +/* +********************************************************************************************************* +* 函 数 名: i2c_NAck +* 功能说明: CPU产生1个NACK信号 +* 形 参: 无 +* 返 回 值: 无 +********************************************************************************************************* +*/ +void i2c_NAck(void) +{ + I2C_SDA_1(); /* CPU驱动SDA = 1 */ + i2c_Delay(); + I2C_SCL_1(); /* CPU产生1个时钟 */ + i2c_Delay(); + I2C_SCL_0(); + i2c_Delay(); +} + +/* +********************************************************************************************************* +* 函 数 名: i2c_CheckDevice +* 功能说明: 检测I2C总线设备,CPU向发送设备地址,然后读取设备应答来判断该设备是否存在 +* 形 参: _Address:设备的I2C总线地址 +* 返 回 值: 返回值 0 表示正确, 返回1表示未探测到 +********************************************************************************************************* +*/ +uint8_t i2c_CheckDevice(uint8_t _Address) +{ + uint8_t ucAck; + + if (I2C_SDA_READ() && I2C_SCL_READ()) + { + i2c_Start(); /* 发送启动信号 */ + + /* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 */ + i2c_SendByte(_Address | I2C_WR); + ucAck = i2c_WaitAck(); /* 检测设备的ACK应答 */ + + i2c_Stop(); /* 发送停止信号 */ + + return ucAck; + } + return 1; /* I2C总线异常 */ +} + +/* +********************************************************************************************************* +* 函 数 名: ee_CheckOk +* 功能说明: 判断串行EERPOM是否正常 +* 形 参: 无 +* 返 回 值: 1 表示正常, 0 表示不正常 +********************************************************************************************************* +*/ +uint8_t GF_BSP_EEPROM_CheckOK(void) +{ + if (i2c_CheckDevice(EE_DEV_ADDR) == 0) + { + return 1; + } + else + { + /* 失败后,切记发送I2C总线停止信号 */ + i2c_Stop(); + return 0; + } +} + + +/* +********************************************************************************************************* +* 函 数 名: GF_BSP_EEPROM_ReadBytes +* 功能说明: 从串行EEPROM指定地址处开始读取若干数据 +* 形 参: _usAddress : 起始地址 +* _usSize : 数据长度,单位为字节 +* _pReadBuf : 存放读到的数据的缓冲区指针 +* 返 回 值: 0 表示失败,1表示成功 +********************************************************************************************************* +*/ +uint8_t GF_BSP_EEPROM_ReadBytes(uint8_t *_pReadBuf, uint16_t _usAddress, uint16_t _usSize) +{ + uint16_t i; + + /* 采用串行EEPROM随即读取指令序列,连续读取若干字节 */ + + /* 第1步:发起I2C总线启动信号 */ + i2c_Start(); + + /* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */ + i2c_SendByte(EE_DEV_ADDR | I2C_WR); /* 此处是写指令 */ + + /* 第3步:发送ACK */ + if (i2c_WaitAck() != 0) + { + goto cmd_fail; /* EEPROM器件无应答 */ + } + + /* 第4步:发送字节地址,24C02只有256字节,因此1个字节就够了,如果是24C04以上,那么此处需要连发多个地址 */ + if (EE_ADDR_BYTES == 1) + { + i2c_SendByte((uint8_t)_usAddress); + if (i2c_WaitAck() != 0) + { + goto cmd_fail; /* EEPROM器件无应答 */ + } + } + else + { + i2c_SendByte(_usAddress >> 8); + if (i2c_WaitAck() != 0) + { + goto cmd_fail; /* EEPROM器件无应答 */ + } + + i2c_SendByte(_usAddress&0xff); + if (i2c_WaitAck() != 0) + { + goto cmd_fail; /* EEPROM器件无应答 */ + } + } + + /* 第6步:重新启动I2C总线。下面开始读取数据 */ + i2c_Start(); + + /* 第7步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */ + i2c_SendByte(EE_DEV_ADDR | I2C_RD); /* 此处是读指令 */ + + /* 第8步:发送ACK */ + if (i2c_WaitAck() != 0) + { + goto cmd_fail; /* EEPROM器件无应答 */ + } + + /* 第9步:循环读取数据 */ + for (i = 0; i < _usSize; i++) + { + _pReadBuf[i] = i2c_ReadByte(); /* 读1个字节 */ + + /* 每读完1个字节后,需要发送Ack, 最后一个字节不需要Ack,发Nack */ + if (i != _usSize - 1) + { + i2c_Ack(); /* 中间字节读完后,CPU产生ACK信号(驱动SDA = 0) */ + } + else + { + i2c_NAck(); /* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */ + } + } + /* 发送I2C总线停止信号 */ + i2c_Stop(); + return 1; /* 执行成功 */ + +cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */ + /* 发送I2C总线停止信号 */ + i2c_Stop(); + return 0; +} + +/* +********************************************************************************************************* +* 函 数 名: GF_BSP_EEPROM_WriteBytes +* 功能说明: 向串行EEPROM指定地址写入若干数据,采用页写操作提高写入效率 +* 形 参: _usAddress : 起始地址 +* _usSize : 数据长度,单位为字节 +* _pWriteBuf : 存放读到的数据的缓冲区指针 +* 返 回 值: 0 表示失败,1表示成功 +********************************************************************************************************* +*/ +uint8_t GF_BSP_EEPROM_WriteBytes(uint8_t *_pWriteBuf, uint16_t _usAddress, uint16_t _usSize) +{ + uint16_t i,m; + uint16_t usAddr; + + /* + 写串行EEPROM不像读操作可以连续读取很多字节,每次写操作只能在同一个page。 + 对于24xx02,page size = 8 + 简单的处理方法为:按字节写操作模式,每写1个字节,都发送地址 + 为了提高连续写的效率: 本函数采用page wirte操作。 + */ + + usAddr = _usAddress; + for (i = 0; i < _usSize; i++) + { + /* 当发送第1个字节或是页面首地址时,需要重新发起启动信号和地址 */ + if ((i == 0) || (usAddr & (EE_PAGE_SIZE - 1)) == 0) + { + /* 第0步:发停止信号,启动内部写操作 */ + i2c_Stop(); + + /* 通过检查器件应答的方式,判断内部写操作是否完成, 一般小于 10ms + CLK频率为200KHz时,查询次数为30次左右 + */ + for (m = 0; m < 1000; m++) + { + /* 第1步:发起I2C总线启动信号 */ + i2c_Start(); + + /* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */ + i2c_SendByte(EE_DEV_ADDR | I2C_WR); /* 此处是写指令 */ + + /* 第3步:发送一个时钟,判断器件是否正确应答 */ + if (i2c_WaitAck() == 0) + { + break; + } + } + if (m == 1000) + { + goto cmd_fail; /* EEPROM器件写超时 */ + } + + /* 第4步:发送字节地址,24C02只有256字节,因此1个字节就够了,如果是24C04以上,那么此处需要连发多个地址 */ + if (EE_ADDR_BYTES == 1) + { + i2c_SendByte((uint8_t)usAddr); + if (i2c_WaitAck() != 0) + { + goto cmd_fail; /* EEPROM器件无应答 */ + } + } + else + { + i2c_SendByte(usAddr >> 8); + if (i2c_WaitAck() != 0) + { + goto cmd_fail; /* EEPROM器件无应答 */ + } + + i2c_SendByte(usAddr&0xff); + if (i2c_WaitAck() != 0) + { + goto cmd_fail; /* EEPROM器件无应答 */ + } + } + } + + /* 第6步:开始写入数据 */ + i2c_SendByte(_pWriteBuf[i]); + + /* 第7步:发送ACK */ + if (i2c_WaitAck() != 0) + { + goto cmd_fail; /* EEPROM器件无应答 */ + } + + usAddr++; /* 地址增1 */ + } + + /* 命令执行成功,发送I2C总线停止信号 */ + i2c_Stop(); + + /* 通过检查器件应答的方式,判断内部写操作是否完成, 一般小于 10ms + CLK频率为200KHz时,查询次数为30次左右 + */ + for (m = 0; m < 1000; m++) + { + /* 第1步:发起I2C总线启动信号 */ + i2c_Start(); + + /* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */ + #if EE_ADDR_A8 == 1 + i2c_SendByte(EE_DEV_ADDR | I2C_WR | ((_usAddress >> 7) & 0x0E)); /* 此处是写指令 */ + #else + i2c_SendByte(EE_DEV_ADDR | I2C_WR); /* 此处是写指令 */ + #endif + + /* 第3步:发送一个时钟,判断器件是否正确应答 */ + if (i2c_WaitAck() == 0) + { + break; + } + } + if (m == 1000) + { + goto cmd_fail; /* EEPROM器件写超时 */ + } + + /* 命令执行成功,发送I2C总线停止信号 */ + i2c_Stop(); + return 1; + +cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */ + /* 发送I2C总线停止信号 */ + i2c_Stop(); + return 0; +} + +CV_struct_define GF_BSP_EEPROM_Get_CV(void) +{ + CV_struct_define cv= {0}; + //char buffer[sizeof(CV_struct_define)]; + GF_BSP_EEPROM_ReadBytes(&cv, GF_BSP_EEPROM_CV_struct_define_Start_Address, sizeof(CV_struct_define)); + return cv; + +} + +uint8_t GF_BSP_EEPROM_Set_CV(CV_struct_define cv) +{ + return GF_BSP_EEPROM_WriteBytes((uint8_t*)&cv,GF_BSP_EEPROM_CV_struct_define_Start_Address,sizeof(CV_struct_define)); +} + + +IAP_struct_define GF_BSP_EEPROM_Get_IAP(void) +{ + IAP_struct_define iap= {0}; + + GF_BSP_EEPROM_ReadBytes(&iap, IAP_struct_define_Start_Address, sizeof(IAP_struct_define)); + return iap; + +} + +uint8_t GF_BSP_EEPROM_Set_IAP(IAP_struct_define iap) +{ + return GF_BSP_EEPROM_WriteBytes((uint8_t*)&iap,IAP_struct_define_Start_Address,sizeof(IAP_struct_define)); +} + + +//PV_struct_define GF_BSP_EEPROM_Get_PV(void) +//{ +// CV_struct_define cv=GF_BSP_EEPROM_Get_CV(); +// +// return cv.PV; +// +//} + +//uint8_t GF_BSP_EEPROM_Set_PV(PV_struct_define pv) +//{ +// CV_struct_define cv=GF_BSP_EEPROM_Get_CV(); +// cv.PV=pv; +// return GF_BSP_EEPROM_Set_CV(cv); +//} + diff --git a/Bingoo/base/bsp_Error.pb.c b/Bingoo/base/bsp_Error.pb.c new file mode 100644 index 0000000..ef29e11 --- /dev/null +++ b/Bingoo/base/bsp_Error.pb.c @@ -0,0 +1,13 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "bsp_Error.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(ErrorData, ErrorData, AUTO) + + + + diff --git a/Bingoo/base/bsp_Error_Detect.c b/Bingoo/base/bsp_Error_Detect.c new file mode 100644 index 0000000..2431cd5 --- /dev/null +++ b/Bingoo/base/bsp_Error_Detect.c @@ -0,0 +1,31 @@ +/* + * bsp_Error_Detect.c + * + * Created on: Oct 23, 2024 + * Author: akeguo + */ +#include "bsp_Error_Detect.h" +void ErrorDetect(); +char Error_Detect_Enable=1; +HardWareController *HardWareErrorController; +void Error_Detect_Intialzie(uint16_t DispacherPeriod) +{ + HardWareErrorController = (HardWareController*) malloc( + sizeof(HardWareController)); + HardWareErrorController->pComHWHead = NULL; + HardWareErrorController->pComHWTail = NULL; + HardWareErrorController->Add_PCOMHardWare = ComHardWare_List_Add_t; + HardWareErrorController->Set_PCOMHardWare = Set_PCOMHardWare_t; + HardWareErrorController->PCOMHardWare_Check = PCOMHardWare_Check_t; + HardWareErrorController->DispacherCallTime = DispacherPeriod;//check the communicaton every 50ms + GF_BSP_Interrupt_Add_CallBack( + DF_BSP_InterCall_TIM8_2ms_PeriodElapsedCallback, ErrorDetect); +} + +void ErrorDetect() +{ + if (Error_Detect_Enable == 1) + { + HardWareErrorController->PCOMHardWare_Check(HardWareErrorController); + } +} diff --git a/Bingoo/base/bsp_FDCAN.c b/Bingoo/base/bsp_FDCAN.c new file mode 100644 index 0000000..5e3843e --- /dev/null +++ b/Bingoo/base/bsp_FDCAN.c @@ -0,0 +1,334 @@ +/* + * bsp_FDCAN.c + * + * Created on: Oct 26, 2023 + * Author: shiya + */ +#include "bsp_FDCAN.h" +#include "main.h" +#include +#include "bsp_Error.pb.h" +//#include "MSP/msp_TI5MOTOR.h" + +FDCANHandler FD_CAN_1_Handler; +FDCANHandler FD_CAN_2_Handler; + +FDCAN_RxHeaderTypeDef CAN_RX_HDR; + +uint8_t CAN_Buf[8]; +uint8_t CAN_Buf_2[8]; + +int32_t CAN_ID; +int32_t CAN_ID_2; + +uint8_t GF_BSP_FDCAN_Init(void) //can初始化 +{ + if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, + 0) != HAL_OK) + { + Error_Handler(); + } + + if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_BUS_OFF, 0) != HAL_OK) + { + Error_Handler(); + } + + HAL_FDCAN_Start(&hfdcan1); + + if (HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, + 0) != HAL_OK) + { + Error_Handler(); + } + + if (HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_BUS_OFF, 0) != HAL_OK) + { + Error_Handler(); + } + + HAL_FDCAN_Start(&hfdcan2); + + return 1; +} + +void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan, + uint32_t ErrorStatusITs) +{ + if (hfdcan->Instance == FDCAN1) + { + MX_FDCAN1_Init(); + } + if (hfdcan->Instance == FDCAN2) + { + MX_FDCAN2_Init(); + } +} + +void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)//can接收 +{ + if (hfdcan->Instance == FDCAN1) + { + if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &CAN_RX_HDR, CAN_Buf)//把数据存CAN_Buf里 + == HAL_OK) + { + CAN_ID = FD_CAN_1_Handler.ReceivedFrameID = + (uint32_t) CAN_RX_HDR.Identifier; //ID + + #if NewCANSendVersion + FD_CAN_1_Handler.ReceivedLength = (uint32_t) CAN_RX_HDR.DataLength;//接收长度 + #else + FD_CAN_1_Handler.ReceivedLength = (uint32_t) CAN_RX_HDR.DataLength>>16; + #endif + + if (FD_CAN_1_Handler.CAN_Decode != NULL ) + { + FD_CAN_1_Handler.CAN_Decode(FD_CAN_1_Handler.ReceivedFrameID, + CAN_Buf, FD_CAN_1_Handler.ReceivedLength); + } + GF_BSP_Interrupt_Run_CallBack(DF_BSP_InterCall_FDCAN1_RxFifo0Callback); + } + + } else if (hfdcan->Instance == FDCAN2) + { + if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &CAN_RX_HDR, + CAN_Buf_2) == HAL_OK) ////把数据存CAN_Buf2里 + { + CAN_ID_2 = FD_CAN_2_Handler.ReceivedFrameID = + (uint32_t) CAN_RX_HDR.Identifier; + +#if NewCANSendVersion + FD_CAN_2_Handler.ReceivedLength = (uint32_t) CAN_RX_HDR.DataLength; +#else + FD_CAN_2_Handler.ReceivedLength = (uint32_t) CAN_RX_HDR.DataLength>>16; +#endif + + if (FD_CAN_2_Handler.CAN_Decode != NULL) + { + FD_CAN_2_Handler.CAN_Decode(FD_CAN_2_Handler.ReceivedFrameID, + CAN_Buf_2, FD_CAN_2_Handler.ReceivedLength); + } + GF_BSP_Interrupt_Run_CallBack(DF_BSP_InterCall_FDCAN2_RxFifo0Callback); + } + + } +} + +FDCAN_TxHeaderTypeDef TXHeader1; +FDCAN_TxHeaderTypeDef TXHeader2; + +void GF_BSP_CANHandler_Init(int can1_sendListPeriod, int can1_DispacherPeriod, + int can2_sendListPeriod, int can2_DispacherPeriod) +{ + + + GF_BSP_CANHandler_Init_CAN(&FD_CAN_1_Handler, &hfdcan1, can1_sendListPeriod, + can1_DispacherPeriod); + GF_BSP_CANHandler_Init_CAN(&FD_CAN_2_Handler, &hfdcan2, can2_sendListPeriod, + can2_DispacherPeriod); + + GF_BSP_Interrupt_Add_CallBack( + DF_BSP_InterCall_TIM8_2ms_PeriodElapsedCallback, GF_BSP_CAN_Timer);//2ms一次 +} +/******************CAN初始化************************/ +void GF_BSP_CANHandler_Init_CAN(FDCANHandler *handler, + FDCAN_HandleTypeDef *canfd, int sendListPeriod, int DispacherPeriod) +{ + handler->canfd = canfd; //FD_CAN_1_Handler的的canfd与 FDCAN_HandleTypeDef hfdcan1;绑定 + handler->dispacherController = (DispacherController*) malloc( + sizeof(DispacherController)); + + + handler->dispacherController->pHead = NULL; + handler->dispacherController->pTail = NULL; + handler->dispacherController->Dispacher_Enable = 1; + handler->dispacherController->DispacherCallTime = DispacherPeriod ; // call the function every 50 ms + handler->dispacherController->Dispacher_Counter = 0; + handler->dispacherController->DispacherNumber = 0; + handler->dispacherController->Add_Dispatcher_List = Dispatcher_List_Add_t; + handler->dispacherController->Dispatcher_Run = Dispatch_t; + + handler->timeSpan = 2; + handler->SendList_time_Count = 0; + handler->AddCANSendList = CANHandlerAddTxList; + handler->SendList_Period = sendListPeriod; + + handler->CAN_Send = CAN_Send_t; + handler->CAN_Send_Data = CAN_Send_Data_t; + +} + +DispacherController *can_dispacherController; +HardWareController *can_HardWareController; +//2ms +void GF_BSP_CAN_Timer() +{ + can_dispacherController = FD_CAN_1_Handler.dispacherController; + + if (FD_CAN_1_Handler.pCurrentCANSendHadler != NULL) + { + GF_CAN_Send_List_Send(&FD_CAN_1_Handler); + + } else + { + can_dispacherController = FD_CAN_1_Handler.dispacherController; + can_dispacherController->Dispatcher_Run(can_dispacherController); + } + if (FD_CAN_2_Handler.pCurrentCANSendHadler != NULL) + { + GF_CAN_Send_List_Send(&FD_CAN_2_Handler); + } else + { + + can_dispacherController = FD_CAN_2_Handler.dispacherController; + can_dispacherController->Dispatcher_Run(can_dispacherController); + + } + +} + //发送函数 在上面定时器调用 2ms一次 +void GF_CAN_Send_List_Send(FDCANHandler *handler) +{ + + handler->SendList_time_Count++; + //timeSpan-->2 SendList_Period-->2 + if (handler->timeSpan * handler->SendList_time_Count + >= handler->SendList_Period) + { + handler->SendList_time_Count = 0; + handler->SendListExists = 1; + if (handler->pCurrentCANSendHadler != NULL) + { + //拷贝数据到相关的代码中,然后发送 + + handler->SendFrameID=handler->pCurrentCANSendHadler->CAN_ID; + + memcpy(handler->Tx_Buf, handler->pCurrentCANSendHadler->Tx_Buf, + handler->pCurrentCANSendHadler->SendLength); + handler->SendList_Period=handler->pCurrentCANSendHadler->SendListTimePeriod;//发送周期 + handler->SendLength = handler->pCurrentCANSendHadler->SendLength; + handler->CAN_Send_Data(handler); /***********发送*****************/ + + if (handler->pCurrentCANSendHadler->pNext != NULL) + { + CANSendHandler *temp = handler->pCurrentCANSendHadler->pNext; + free(handler->pCurrentCANSendHadler); //清除内存 + handler->pCurrentCANSendHadler = temp; + } else + { + free(handler->pCurrentCANSendHadler); //清除内存 + handler->pCurrentCANSendHadler = NULL; + } + + } else + { + handler->SendListExists = 0; + + } + + } + +} + +// +//handler->CAN_Send_Data = CAN_Send_Data_t; +void CAN_Send_Data_t(struct _FDCANHandler *fd) +{ + CAN_Send_t(fd, fd->SendFrameID, fd->SendLength, fd->Tx_Buf); +} +/* + * | + * | + * V + * */ +void CAN_Send_t(struct _FDCANHandler *fd, uint32_t FrameID, uint8_t DataLength, + uint8_t *Txdata) +{ + + //Function_code = Txdata[0]; + + if (DataLength > 8) + { + return; + } + if (fd->canfd == &hfdcan1) + { + TXHeader1.BitRateSwitch = FDCAN_BRS_OFF; + + #if NewCANSendVersion + TXHeader1.DataLength = (uint32_t) DataLength ; + #else + TXHeader1.DataLength = (uint32_t) DataLength << 16; //数据长度大于8的话会有错误 + #endif + + + TXHeader1.FDFormat = FDCAN_CLASSIC_CAN; + TXHeader1.IdType = FDCAN_STANDARD_ID; + TXHeader1.Identifier = FrameID; + TXHeader1.TxFrameType = FDCAN_DATA_FRAME; + HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TXHeader1, Txdata); + } else if (fd->canfd == &hfdcan2) + { + TXHeader2.BitRateSwitch = FDCAN_BRS_OFF; + + #if NewCANSendVersion + TXHeader2.DataLength = (uint32_t) DataLength ; + #else + TXHeader2.DataLength = (uint32_t) DataLength << 16; //数据长度大于8的话会有错误 + #endif + //TXHeader2.DataLength = (uint32_t) DataLength << 16; //数据长度大于8的话会有错误 + TXHeader2.FDFormat = FDCAN_CLASSIC_CAN; + TXHeader2.IdType = FDCAN_STANDARD_ID; + TXHeader2.Identifier = FrameID; + TXHeader2.TxFrameType = FDCAN_DATA_FRAME; + HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan2, &TXHeader2, Txdata); + } +} + + + +//handler->AddCANSendList = CANHandlerAddTxList;该函数由AddCANSendList调用 + +//把多个 CAN 消息按顺序添加到发送队列。系统按照设定的时间周期或者优先级依次发送队列中的消息。 +/* + * Motor_Controller->AddCANSendList(Motor_Controller, 0x600 + MotorID, 8, + Motor_Controller->Tx_Buf, WaitTime, NULL); + * */ +void CANHandlerAddTxList(FDCANHandler *handler, uint32_t CAN_ID, + uint8_t SendLength, uint8_t *Tx_Buf,uint32_t sendListTimePeriod, + void (*CAN_Decode)(uint32_t, uint8_t*, uint32_t)) //参数其实就是一组can数据 在FDHandler添加东西 +{ + + CANSendHandler *pTmp = NULL; //临时指针 链表中的节点 + + //临时指针2用于逐个申请内存 + pTmp = (CANSendHandler*) malloc(sizeof(CANSendHandler));//节点申请内存 + memcpy(pTmp->Tx_Buf, Tx_Buf, SendLength);//把参数2的内容复制到节点上 + pTmp->pNext = NULL; //下一个节点暂时为空 + pTmp->CAN_ID=CAN_ID; //设置节点ID + pTmp->SendLength = SendLength; + //pTmp->CAN_Decode = CAN_Decode; + pTmp->SendListTimePeriod=sendListTimePeriod;//节点的发送周期 + + +//if NULL, call intialize one + if (handler->pCurrentCANSendHadler == NULL) + { + handler->pCurrentCANSendHadler = pTmp; //空链表 + } else + { + char i = 0; + //插到尾部 + CANSendHandler *phead = NULL; + phead = handler->pCurrentCANSendHadler; + while (phead->pNext != NULL) + { + i++; + phead = phead->pNext; + } + phead->pNext = pTmp; + + } + +} + diff --git a/Bingoo/base/bsp_GPIO.c b/Bingoo/base/bsp_GPIO.c new file mode 100644 index 0000000..8a77775 --- /dev/null +++ b/Bingoo/base/bsp_GPIO.c @@ -0,0 +1,104 @@ +/* + * bsp_GPIO.c + * + * Created on: Oct 26, 2023 + * Author: shiya + */ +#include "BSP/bsp_GPIO.h" + +uint8_t GF_BSP_GPIO_Init() +{ + + return 1; +} + +/* IO配置 + * IO_Index : 0-5 + * Level : 0:PIN_RESET; 1:PIN_SET; + * */ +void GF_BSP_GPIO_SetIO(uint8_t IO_Index,uint8_t Level) +{ + GPIO_PinState PinState; + if(Level == 0) + PinState=GPIO_PIN_RESET; + else + PinState=GPIO_PIN_SET; + + switch(IO_Index) + { + case 0: + HAL_GPIO_WritePin(OUT_0_GPIO_Port, OUT_0_Pin, PinState); + break; + case 1: + HAL_GPIO_WritePin(OUT_1_GPIO_Port, OUT_1_Pin, PinState);//pc3 + break; + case 2: + HAL_GPIO_WritePin(OUT_2_GPIO_Port, OUT_2_Pin, PinState); + break; + case 3: + HAL_GPIO_WritePin(OUT_3_GPIO_Port, OUT_3_Pin, PinState); + break; + case 4: + HAL_GPIO_WritePin(OUT_4_GPIO_Port, OUT_4_Pin, PinState); + break; + case 5: + HAL_GPIO_WritePin(OUT_5_GPIO_Port, OUT_5_Pin, PinState); + break; + } +} + +uint8_t GF_BSP_GPIO_ToggleIO(uint8_t IO_Index) +{ + + switch(IO_Index) + { + case 0: + HAL_GPIO_TogglePin(OUT_0_GPIO_Port, OUT_0_Pin); + break; + case 1: + HAL_GPIO_TogglePin(OUT_1_GPIO_Port, OUT_1_Pin); + break; + case 2: + HAL_GPIO_TogglePin(OUT_2_GPIO_Port, OUT_2_Pin); + break; + case 3: + HAL_GPIO_TogglePin(OUT_3_GPIO_Port, OUT_3_Pin); + break; + case 4: + HAL_GPIO_TogglePin(OUT_4_GPIO_Port, OUT_4_Pin); + break; + case 5: + HAL_GPIO_TogglePin(OUT_5_GPIO_Port, OUT_5_Pin); + break; + } + + +} + + +uint8_t GF_BSP_GPIO_ReadIO(uint8_t IO_Index) +{ + GPIO_PinState PinState; + switch(IO_Index) + { + case 0: + PinState = HAL_GPIO_ReadPin(IN_0_GPIO_Port, IN_0_Pin); + break; + case 1: + PinState = HAL_GPIO_ReadPin(IN_1_GPIO_Port, IN_1_Pin); + break; + case 2: + PinState = HAL_GPIO_ReadPin(IN_2_GPIO_Port, IN_2_Pin); + break; + case 3: + PinState = HAL_GPIO_ReadPin(IN_3_GPIO_Port, IN_3_Pin); + break; + case 4: + PinState = HAL_GPIO_ReadPin(IN_4_GPIO_Port, IN_4_Pin); + break; + case 5: + PinState = HAL_GPIO_ReadPin(IN_5_GPIO_Port, IN_5_Pin); + break; + } + return((uint8_t)PinState); +} diff --git a/Bingoo/base/bsp_GV.pb.c b/Bingoo/base/bsp_GV.pb.c new file mode 100644 index 0000000..bf47c58 --- /dev/null +++ b/Bingoo/base/bsp_GV.pb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "bsp_GV.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(GV_struct_define, GV_struct_define, 2) + + + diff --git a/Bingoo/base/bsp_IAP.pb.c b/Bingoo/base/bsp_IAP.pb.c new file mode 100644 index 0000000..991e03b --- /dev/null +++ b/Bingoo/base/bsp_IAP.pb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "bsp_IAP.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(IAP_struct_define, IAP_struct_define, AUTO) + + + diff --git a/Bingoo/base/bsp_INTERCALL.c b/Bingoo/base/bsp_INTERCALL.c new file mode 100644 index 0000000..8c5a95c --- /dev/null +++ b/Bingoo/base/bsp_INTERCALL.c @@ -0,0 +1,41 @@ +/* + * bsp_INTERCALL.c + * + * Created on: 2023年11月8日 + * Author: shiya + */ +#include "BSP/bsp_include.h" + +typedef struct + { + uint8_t num; //调用函数指针数量 + void(*fn[DF_BSP_InterCall_Num])(void); //被调用函数指针,最多20个回调函数 + }SD_BSP_InterCall; + +SD_BSP_InterCall V_BSP_InterCall_Array[DF_BSP_InterCall_Type_Num] = {0}; + +//给中断函数链接一个回调函数,直接添加空函数指针 +//返回值1表示添加成功,返回值0表示添加失败 +uint8_t GF_BSP_Interrupt_Add_CallBack(enum DF_BSP_InterCall_Type _type,void(*_fn)(void)) +{ + V_BSP_InterCall_Array[_type].num++; + if(V_BSP_InterCall_Array[_type].num>=DF_BSP_InterCall_Num) + { + return 0; + } + V_BSP_InterCall_Array[_type].fn[V_BSP_InterCall_Array[_type].num-1]=_fn; + return 1; +} + +//放到中断函数中,运行相应的回调函数,有几个运行几个 +void GF_BSP_Interrupt_Run_CallBack(enum DF_BSP_InterCall_Type _type) +{ + uint8_t i=0; + if(V_BSP_InterCall_Array[_type].num>0) + { + for(i=0;i> 8; /* 寄存器地址 高字节 */ + Tx_Buf[TxCount++] = _reg; /* 寄存器地址 低字节 */ + Tx_Buf[TxCount++] = _num >> 8; /* 线圈(bit)个数 高字节 */ + Tx_Buf[TxCount++] = _num; /* 线圈(bit)个数 低字节 */ + + crc = MB_CRC16(Tx_Buf, TxCount); + Tx_Buf[TxCount++] = crc; /* crc 低字节 */ + Tx_Buf[TxCount++] = crc >> 8; /* crc 高字节 */ + *TxCount_t = TxCount; + //uartHandler->UART_Tx(uartHandler,(uint8_t *)&Tx_Buf,TxCount); + //UART_Tx((uint8_t *)&Tx_Buf,TxCount); +} + +/** + * 函数功能: 写单个线圈状态(CoilStatue) + * 输入参数: _addr:从站地址,_reg:寄存器地址,_sta:待写入的线圈状态(0,1) + * 返 回 值: 无 + * 说 明: 填充数据发送缓存区,然后发送 + */ +void MB_WriteCoil(uint8_t *Tx_Buf, uint8_t *TxCount_t, uint8_t _addr, + uint16_t _reg, uint16_t _sta) +{ + uint16_t TxCount = 0; + uint16_t crc = 0; + Tx_Buf[TxCount++] = _addr; /* 从站地址 */ + Tx_Buf[TxCount++] = 0x05; /* 功能码 */ + Tx_Buf[TxCount++] = _reg >> 8; /* 寄存器地址 高字节 */ + Tx_Buf[TxCount++] = _reg; /* 寄存器地址 低字节 */ + Tx_Buf[TxCount++] = _sta >> 8; /* 线圈(bit)个数 高字节 */ + Tx_Buf[TxCount++] = _sta; /* 线圈(bit)个数 低字节 */ + + + + crc = MB_CRC16(Tx_Buf, TxCount); + Tx_Buf[TxCount++] = crc; /* crc 低字节 */ + Tx_Buf[TxCount++] = crc >> 8; /* crc 高字节 */ + *TxCount_t = TxCount; + + //UART_Tx((uint8_t *)&Tx_Buf,TxCount); + + //uartHandler->UART_Tx(uartHandler,(uint8_t *)&Tx_Buf,TxCount); +} + +void MB_WriteNumCoil(uint8_t *Tx_Buf, uint8_t *TxCount_t, uint8_t _addr, + uint16_t _reg, uint16_t _num, uint8_t *_databuf) +{ + + uint16_t i; + uint16_t TxCount = 0; + uint16_t crc = 0; + Tx_Buf[TxCount++] = _addr; /* 从站地址 */ + Tx_Buf[TxCount++] = 0x0F; /* 功能码 */ + Tx_Buf[TxCount++] = _reg >> 8; /* 寄存器地址 高字节 */ + Tx_Buf[TxCount++] = _reg; /* 寄存器地址 低字节 */ + Tx_Buf[TxCount++] = _num >> 8; /* 寄存器(16bits)个数 高字节 */ + Tx_Buf[TxCount++] = _num; /* 低字节 */ + + if(_num%8==0) + { + Tx_Buf[TxCount++] = _num / 8; + }else + { + Tx_Buf[TxCount++] = _num / 8 + 1; + } + /* 数据个数 */ + uint16_t ij=TxCount++; + for (i = 0; i < _num; i++) + { + Tx_Buf[ij]|= _databuf[i]<> 8; /* crc 高字节 */ + //UART_Tx((uint8_t *)&Tx_Buf,TxCount); + *TxCount_t = TxCount; +} + + + +/** + * 函数功能: 读输入状态状态(InputStatue) + * 输入参数: _addr:从站地址,_reg:寄存器地址,_num:待读取的输入数量 + * 返 回 值: 无 + * 说 明: 填充数据发送缓存区,然后发送 + */ +void MB_ReadInput(uint8_t *Tx_Buf, uint8_t *TxCount_t, uint8_t _addr, + uint16_t _reg, uint16_t _num) +{ + uint16_t TxCount = 0; + uint16_t crc = 0; + Tx_Buf[TxCount++] = _addr; /* 从站地址 */ + Tx_Buf[TxCount++] = 0x02; /* 功能码 */ + Tx_Buf[TxCount++] = _reg >> 8; /* 寄存器地址 高字节 */ + Tx_Buf[TxCount++] = _reg; /* 寄存器地址 低字节 */ + Tx_Buf[TxCount++] = _num >> 8; /* 开关(Input)个数 高字节 */ + Tx_Buf[TxCount++] = _num; /* 开关(Input)个数 低字节 */ + + crc = MB_CRC16(Tx_Buf, TxCount); + Tx_Buf[TxCount++] = crc; /* crc 低字节 */ + Tx_Buf[TxCount++] = crc >> 8; /* crc 高字节 */ + *TxCount_t = TxCount; + //UART_Tx((uint8_t *)&Tx_Buf,TxCount); + //uartHandler->UART_Tx(uartHandler,(uint8_t *)&Tx_Buf,TxCount); +} + +/** + * 函数功能: 读保持寄存器(HoldingRegister) + * 输入参数: _addr:从站地址,_reg:寄存器地址,_num:待读取的寄存器数量 + * 返 回 值: 无 + * 说 明: 填充数据发送缓存区,然后发送 + */ +void MB_ReadHoldingReg(uint8_t *Tx_Buf, uint8_t *TxCount_t, uint8_t _addr, + uint16_t _reg, uint16_t _num) +{ + MB_rx_flag = 2; + Read_Reg_Num = _num; + Read_Slave_ID = _addr; + + uint16_t TxCount = 0; + uint16_t crc = 0; + Tx_Buf[TxCount++] = _addr; /* 从站地址 */ + Tx_Buf[TxCount++] = 0x03; /* 功能码 */ + Tx_Buf[TxCount++] = _reg >> 8; /* 寄存器地址 高字节 */ + Tx_Buf[TxCount++] = _reg; /* 寄存器地址 低字节 */ + Tx_Buf[TxCount++] = _num >> 8; /* 寄存器(16bits)个数 高字节 */ + Tx_Buf[TxCount++] = _num; /* 低字节 */ + + crc = MB_CRC16(Tx_Buf, TxCount); + Tx_Buf[TxCount++] = crc; /* crc 低字节 */ + Tx_Buf[TxCount++] = crc >> 8; /* crc 高字节 */ + + *TxCount_t = TxCount; + //UART_Tx((uint8_t *)&Tx_Buf,TxCount); + //uartHandler->UART_Tx(uartHandler,(uint8_t *)&Tx_Buf,TxCount); +} + +/** + * 函数功能: 读N个输入寄存器(InputRegister) + * 输入参数: _addr:从站地址,_reg:寄存器地址,_num:待读取的寄存器数量 + * 返 回 值: 无 + * 说 明: 填充数据发送缓存区,然后发送. + */ +void MB_ReadInputReg(uint8_t *Tx_Buf, uint8_t *TxCount_t, uint8_t _addr, + uint16_t _reg, uint16_t _num) +{ + uint16_t TxCount = 0; + uint16_t crc = 0; + Tx_Buf[TxCount++] = _addr; /* 从站地址 */ + Tx_Buf[TxCount++] = 0x04; /* 功能码 */ + Tx_Buf[TxCount++] = _reg >> 8; /* 寄存器地址 高字节 */ + Tx_Buf[TxCount++] = _reg; /* 寄存器地址 低字节 */ + Tx_Buf[TxCount++] = _num >> 8; /* 寄存器(16bits)个数 高字节 */ + Tx_Buf[TxCount++] = _num; /* 低字节 */ + + crc = MB_CRC16(Tx_Buf, TxCount); + Tx_Buf[TxCount++] = crc; /* crc 低字节 */ + Tx_Buf[TxCount++] = crc >> 8; /* crc 高字节 */ + *TxCount_t = TxCount; + //UART_Tx((uint8_t *)&Tx_Buf,TxCount); +} + +/** + * 函数功能: 写单个保持寄存器(HoldingRegister) + * 输入参数: _addr:从站地址,_reg:寄存器地址,_data:待写入的寄存器数据 + * 返 回 值: 无 + * 说 明: 填充数据发送缓存区,然后发送 + */ +void MB_WriteHoldingReg(uint8_t *Tx_Buf, uint8_t *TxCount_t, uint8_t _addr, + uint16_t _reg, uint16_t _data) +{ + uint16_t TxCount = 0; + uint16_t crc = 0; + Tx_Buf[TxCount++] = _addr; /* 从站地址 */ + Tx_Buf[TxCount++] = 0x06; /* 功能码 */ + Tx_Buf[TxCount++] = _reg >> 8; /* 寄存器地址 高字节 */ + Tx_Buf[TxCount++] = _reg; /* 寄存器地址 低字节 */ + Tx_Buf[TxCount++] = _data >> 8; /* 寄存器(16bits)个数 高字节 */ + Tx_Buf[TxCount++] = _data; /* 低字节 */ + + crc = MB_CRC16(Tx_Buf, TxCount); + Tx_Buf[TxCount++] = crc; /* crc 低字节 */ + Tx_Buf[TxCount++] = crc >> 8; /* crc 高字节 */ + *TxCount_t = TxCount; + //UART_Tx((uint8_t *)&Tx_Buf,TxCount); + //uartHandler->UART_Tx(uartHandler,(uint8_t *)&Tx_Buf,TxCount); +} + +/** + * 函数功能: 写N个保持寄存器(HoldingRegister) + * 输入参数: _addr:从站地址,_reg:寄存器地址,_num:待写入的寄存器数量,_databuf:待写入的寄存器数据 + * 返 回 值: 无 + * 说 明: 填充数据发送缓存区,然后发送._databuf的长度需 >= _num*2 + */ +void MB_WriteNumHoldingReg(uint8_t *Tx_Buf, uint8_t *TxCount_t, uint8_t _addr, + uint16_t _reg, uint16_t _num, uint8_t *_databuf) +{ + + uint16_t i; + uint16_t TxCount = 0; + uint16_t crc = 0; + Tx_Buf[TxCount++] = _addr; /* 从站地址 */ + Tx_Buf[TxCount++] = 0x10; /* 功能码 */ + Tx_Buf[TxCount++] = _reg >> 8; /* 寄存器地址 高字节 */ + Tx_Buf[TxCount++] = _reg; /* 寄存器地址 低字节 */ + Tx_Buf[TxCount++] = _num >> 8; /* 寄存器(16bits)个数 高字节 */ + Tx_Buf[TxCount++] = _num; /* 低字节 */ + Tx_Buf[TxCount++] = _num << 1; /* 数据个数 */ + + for (i = 0; i < 2 * _num; i++) + { + Tx_Buf[TxCount++] = _databuf[i]; /* 后面的数据长度 */ + } + crc = MB_CRC16(Tx_Buf, TxCount); + Tx_Buf[TxCount++] = crc; /* crc 低字节 */ + Tx_Buf[TxCount++] = crc >> 8; /* crc 高字节 */ + //UART_Tx((uint8_t *)&Tx_Buf,TxCount); + *TxCount_t = TxCount; +} +/** + * 函数功能: 解析读取Read_Reg_Num个保持寄存器的值 (HoldingRegister) + * 输入参数: buffer:数据值,length:数据长度, Read_Reg_Num 读取几个保持寄存器, 将解析出来的数据存入 Decoded_Reg_Value 这个16进制的数据中 + * 返 回 值: 1 表示解析正确,0 表示解析错误 CRC验证错误 + * 说 明: + */ +uint8_t MB_Decode_HoldingRegs(uint8_t buffer[], uint16_t length,uint16_t Read_Reg_Num,uint16_t* Decoded_Reg_Value) +{ + /* CRC 校验 */ + uint16_t crc_check = ((buffer[length - 1] << 8) | buffer[length - 2]); + /* CRC 校验正确 */ + if (crc_check == MB_CRC16(buffer, length - 2)) + { + int i = 0; + for (i = 0; i < Read_Reg_Num; i++) + { + + Decoded_Reg_Value[ i] = + (buffer[3 + 2 * i] << 8) + buffer[4 + 2 * i]; + } + return 1; //Decoded successfully + } + else + { + return 0; //Decode Error; + } +} +uint8_t MB_Decode_InputRegs(uint8_t buffer[], uint16_t length,uint16_t Read_Reg_Num,uint16_t* Decoded_Reg_Value) +{ + /* CRC 校验 */ + uint16_t crc_check = ((buffer[length - 1] << 8) | buffer[length - 2]); + /* CRC 校验正确 */ + if (crc_check == MB_CRC16(buffer, length - 2)) + { + int i = 0; + for (i = 0; i < Read_Reg_Num; i++) + { + + Decoded_Reg_Value[ i] = + (buffer[3 + 2 * i] << 8) + buffer[4 + 2 * i]; + } + return 1; //Decoded successfully + } + else + { + + return 0; //Decode Error; + } +} + + diff --git a/Bingoo/base/bsp_PID.pb.c b/Bingoo/base/bsp_PID.pb.c new file mode 100644 index 0000000..0000d2f --- /dev/null +++ b/Bingoo/base/bsp_PID.pb.c @@ -0,0 +1,20 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "bsp_PID.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(PID_Parameters, PID_Parameters, AUTO) + + + +#ifndef PB_CONVERT_DOUBLE_FLOAT +/* On some platforms (such as AVR), double is really float. + * To be able to encode/decode double on these platforms, you need. + * to define PB_CONVERT_DOUBLE_FLOAT in pb.h or compiler command line. + */ +PB_STATIC_ASSERT(sizeof(double) == 8, DOUBLE_MUST_BE_8_BYTES) +#endif + diff --git a/Bingoo/base/bsp_PV.pb.c b/Bingoo/base/bsp_PV.pb.c new file mode 100644 index 0000000..5afe52f --- /dev/null +++ b/Bingoo/base/bsp_PV.pb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "bsp_PV.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(PV_struct_define, PV_struct_define, AUTO) + + + diff --git a/Bingoo/base/bsp_ReCmd.pb.c b/Bingoo/base/bsp_ReCmd.pb.c new file mode 100644 index 0000000..073320b --- /dev/null +++ b/Bingoo/base/bsp_ReCmd.pb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "bsp_ReCmd.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(ReCmd, ReCmd, 2) + + + diff --git a/Bingoo/base/bsp_TCPClient.c b/Bingoo/base/bsp_TCPClient.c new file mode 100644 index 0000000..b96347b --- /dev/null +++ b/Bingoo/base/bsp_TCPClient.c @@ -0,0 +1,186 @@ +#include "BSP/bsp_TCPClient.h" +#include "lwip/netif.h" +#include "lwip/ip.h" +#include "lwip/tcp.h" +#include "lwip/init.h" +#include "netif/etharp.h" +#include "lwip/udp.h" +#include "lwip/pbuf.h" +#include +#include +#include "BHBF_ROBOT.h" + +#pragma pack (1) /*指定按1字节对齐*/ + + + +#pragma pack () /*取消指定对齐,恢复缺省对齐*/ +LazorData *ReadLazorData; +unsigned char *Weld_Out_Flag; +unsigned char Weld_Out_Count; +unsigned char Weld_Out_SafeCount = 500; + +uint8_t ReceivedData[3000]; +static uint16_t receivedLength = 0; + +void IntiazlieLazor(); + +void IntiazlieLazor1(); + +static err_t client_connected(void *arg, struct tcp_pcb *pcb, err_t err); + +ip4_addr_t server_ip; +static struct tcp_pcb *client_pcb = NULL; + +static void client_err(void *arg, err_t err) +{ + //printf("connect error! closed by core!!\n"); + //printf("try to connect to server again!!\n"); + + //连接失败的时候释放TCP控制块的内存 + tcp_close(client_pcb); + + //重新连接 + TCP_Client_Init(); +} + + + +int index_0 = 0; +int count_Client; +static err_t client_send(void *arg, struct tcp_pcb *tpcb) +{ +// count_Client++; +// if(count_Client >= 50) +// { +// count_Client = 49; + switch (index_0) + { + + case 0:case 1: + { + uint8_t send_buf[] = + {0x00,0x15,0x00,0x00,0x00,0x1B,0x01,0x10,0x03,0xE8,0x00,0x0A,0x14, + 0x0D,0x0C,0x0B,0x0A,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + tcp_write(tpcb, send_buf, sizeof(send_buf), 1); + tcp_output(client_pcb); + index_0++; + break; + } + + case 2:case 3: + { + uint8_t send_buf[] = + {0x00,0x15,0x00,0x00,0x00,0x1B,0x01,0x10,0x03,0xE8,0x00,0x0A,0x14, + 0x0D,0x0C,0x0B,0x0A,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + tcp_write(tpcb, send_buf, sizeof(send_buf), 1); + tcp_output(client_pcb); + index_0++; + break; + } + case 4: + { + uint8_t send_buf[] = + {0x00,0x05,0x00,0x00,0x00,0x06,0x01,0x03,0x07,0xD0,0x00,0x12}; + tcp_write(tpcb, send_buf, sizeof(send_buf), 1); + tcp_output(client_pcb); + break; + } + +// case 0:case 1: +// { +// uint8_t send_buf[4] = +// { 0x01, 0x00, 0x00, 0x00 }; +// tcp_write(tpcb, send_buf, sizeof(send_buf), 1); +// tcp_output(client_pcb); +// index_0++; +// break; +// } +// +// case 2:case 3: +// { +// uint8_t send_buf[4] = +// { 0x08, 0x00, 0x04, 0x00 }; +// tcp_write(tpcb, send_buf, sizeof(send_buf), 1); +// tcp_output(client_pcb); +// index_0++; +// break; +// } + } + +// } + + return ERR_OK; +} + +static err_t client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, + err_t err) +{ + if (p != NULL) + { + /* 接收数据*/ + + + + /* 返回接收到的数据*/ + //tcp_write(tpcb, p->payload, p->tot_len, 1); + receivedLength = p->tot_len; +// if (p->tot_len == 36) +// { + memcpy(ReceivedData, p->payload, p->tot_len); +// } + + //memset(p->payload, 0, p->tot_len); + tcp_recved(tpcb, p->tot_len); + pbuf_free(p); + } else if (err == ERR_OK) + { + //服务器断开连接 + //printf("server has been disconnected!\n"); + tcp_close(tpcb); + + //重新连接 + TCP_Client_Init(); + // tcp_connect(client_pcb, &server_ip, TCP_CLIENT_PORT, client_connected); + } + return ERR_OK; +} + +static err_t client_connected(void *arg, struct tcp_pcb *pcb, err_t err) +{ + // printf("connected ok!\n"); + + //注册一个周期性回调函数 + tcp_poll(pcb, client_send, 1); + + //注册一个接收函数 + + tcp_recv(pcb, client_recv); //TCP_TMR_INTERVAL == 50 在tcp_priv.h + + return ERR_OK; +} + +void TCP_Client_Init(void) +{ + + ReadLazorData = &ReceivedData[25]; + + Weld_Out_Flag = &ReceivedData[11]; + + /* 创建一个TCP控制块 */ + client_pcb = tcp_new(); + client_pcb->flags |= TF_NODELAY; + IP4_ADDR(&server_ip, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, + DEST_IP_ADDR3); + + //printf("client start connect!\n"); + + //开始连接 + tcp_connect(client_pcb, &server_ip, DEST_PORT, client_connected); + + //注册异常处理 + tcp_err(client_pcb, client_err); +} + diff --git a/Bingoo/base/bsp_TIMER.c b/Bingoo/base/bsp_TIMER.c new file mode 100644 index 0000000..4ee2128 --- /dev/null +++ b/Bingoo/base/bsp_TIMER.c @@ -0,0 +1,71 @@ +/* + * bsp_TIMER.c + * + * Created on: Oct 26, 2023 + * Author: shiya + */ +#include "BSP/bsp_TIMER.h" +#include "lwip.h" +#include "BSP/bsp_mqtt.h" + +//返回值::1-正常;0-错误 +uint8_t GF_BSP_TIMER_Init() +{ + HAL_TIM_Base_Start_IT(&htim1); + HAL_TIM_Base_Start_IT(&htim8); + return 1; +} + +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + //100ms - WatchDog + if(htim->Instance == TIM1)//APB2=200Mhz,htim1.Init.Prescaler = 2000-1;htim1.Init.Period = 10000-1; TIM1=100ms + { + + GF_BSP_Interrupt_Run_CallBack(DF_BSP_InterCall_TIM1_100ms_PeriodElapsedCallback); + + } + //2ms - MainLoop + if(htim->Instance == TIM8)//APB2=200Mhz,htim8.Init.Prescaler = 2000-1;htim8.Init.Period = 200-1; TIM8=2ms + { + MX_LWIP_Process(); + GF_BSP_Interrupt_Run_CallBack(DF_BSP_InterCall_TIM8_2ms_PeriodElapsedCallback); + //bsp_mqtt_test(); + } +} + +void GF_BSP_TIMER_DelayUS(uint32_t n) +{ + uint32_t ticks; + uint32_t told; + uint32_t tnow; + uint32_t tcnt = 0; + uint32_t reload; + + reload = SysTick->LOAD; + ticks = n * (SystemCoreClock / 1000000); + + tcnt = 0; + told = SysTick->VAL; + + while (1) + { + tnow = SysTick->VAL; + if (tnow != told) + { + if (tnow < told) + { + tcnt += told - tnow; + } + else + { + tcnt += reload - tnow + told; + } + told = tnow; + if (tcnt >= ticks) + { + break; + } + } + } +} diff --git a/Bingoo/base/bsp_UART.c b/Bingoo/base/bsp_UART.c new file mode 100644 index 0000000..746310d --- /dev/null +++ b/Bingoo/base/bsp_UART.c @@ -0,0 +1,553 @@ +#include "BSP/bsp_UART.h" +#include "main.h" +#include + +void GF_UART_Send_List_Send(struct UARTHandler *handler); +void Dispatcher_List_Add(struct UARTHandler *uartHandler, + void (*dispache)(void)); + + + +void UARTHandlerAddTxList(struct UARTHandler *uartHandler, uint8_t *data, + uint16_t length, uint32_t txListTimePeriod, void (*UART_Decode)(uint8_t*, uint16_t)); + +//Store all the data in these buffer +uint8_t RS485_1_RxMA_buf[UART_Receive_MAX_NUM]; +uint8_t RS485_2_RxDMA_buf[UART_Receive_MAX_NUM]; +uint8_t RS485_3_RxDMA_buf[UART_Receive_MAX_NUM]; +uint8_t RS485_4_RxDMA_buf[UART_Receive_MAX_NUM]; +uint8_t Debug_RxDMA_buf[UART_Receive_MAX_NUM]; +uint8_t ExternSerial_RxDMA_buf[UART_Receive_MAX_NUM]; + +uint8_t RS485_1_TxDMA_buf[UART_Transmit_MAX_NUM]; +uint8_t RS485_2_TxDMA_buf[UART_Transmit_MAX_NUM]; +uint8_t RS485_3_TxDMA_buf[UART_Transmit_MAX_NUM]; +uint8_t RS485_4_TxDMA_buf[UART_Transmit_MAX_NUM]; +uint8_t Debug_TxDMA_buf[UART_Transmit_MAX_NUM]; +uint8_t ExternSerial_TxDMA_buf[UART_Transmit_MAX_NUM]; +#define InterCall_DEBUG_UART huart4 +#define E28_SBUS_UART huart5 +#define RS485_4_UART huart7 +#define RS485_1_UART huart1 +#define LTE_7S0_Serial_UART huart2 + + +#define RS485_2_UART huart3 +#define RS485_3_UART huart6 + + +struct UARTHandler RS_485_1_UART_Handler; +struct UARTHandler RS_485_2_UART_Handler; +struct UARTHandler RS_485_3_UART_Handler; +struct UARTHandler RS_485_4_UART_Handler; +struct UARTHandler InterCall_DEBUG_UART_Handler; +struct UARTHandler E28_SBUS_UART_Handler; +struct UARTHandler LTE_7S0_Serial_UART_Handler; + + + +#if defined (hlpuart1Exit) + + #define LPUART1UART hlpuart1 + struct UARTHandler LPUART1_UART_Handler; + +#endif + +void GF_BSP_UARTHandlers_Intialize( + int32_t RS485_1_WaitTime, + int32_t RS485_2_WaitTime, + int32_t RS485_3_WaitTime, + int32_t RS485_4_WaitTime, + int32_t LTE_7S0_Serial_WaitTime, + int32_t InterCall_DEBUG_WaitTime, + int32_t E28_SBUS_WaitTime, + int32_t LPUART1_UART_WaitTime, + int32_t RS485_1_Dispacher_Time, + int32_t RS485_2_Dispacher_Time, + int32_t RS485_3_Dispacher_Time, + int32_t RS485_4_Dispacher_Time, + int32_t LTE_7S0_Serial_Dispacher_Time, + int32_t InterCall_DEBUG_Dispacher_Time, + int32_t E28_SBUS_Dispacher_Time, + int32_t LPUART1_UART_Dispacher_Time +) +{ + + IntializeUARTHandler(&RS_485_1_UART_Handler, &RS485_1_UART, RS485_1_WaitTime, 2,RS485_1_Dispacher_Time); + IntializeUARTHandler(&RS_485_2_UART_Handler, &RS485_2_UART, RS485_2_WaitTime, 2,RS485_2_Dispacher_Time); + IntializeUARTHandler(&RS_485_3_UART_Handler, &RS485_3_UART, RS485_3_WaitTime, 2,RS485_3_Dispacher_Time); + IntializeUARTHandler(&RS_485_4_UART_Handler, &RS485_4_UART, RS485_4_WaitTime, 2,RS485_4_Dispacher_Time); + IntializeUARTHandler(<E_7S0_Serial_UART_Handler, <E_7S0_Serial_UART, LTE_7S0_Serial_WaitTime, 2,LTE_7S0_Serial_Dispacher_Time); + IntializeUARTHandler(&InterCall_DEBUG_UART_Handler, &InterCall_DEBUG_UART, InterCall_DEBUG_WaitTime, 2,InterCall_DEBUG_Dispacher_Time); + IntializeUARTHandler(&E28_SBUS_UART_Handler, &E28_SBUS_UART, E28_SBUS_WaitTime, 2,E28_SBUS_Dispacher_Time); + + + HAL_UART_Receive_IT((E28_SBUS_UART_Handler.uart), + (uint8_t*) &E28_SBUS_UART_Handler.tmp_Rx_Buf, 1); + + + HAL_UART_Receive_IT((InterCall_DEBUG_UART_Handler.uart), + (uint8_t*) &InterCall_DEBUG_UART_Handler.tmp_Rx_Buf, 1); + HAL_UART_Receive_IT((RS_485_1_UART_Handler.uart), + (uint8_t*) &RS_485_1_UART_Handler.tmp_Rx_Buf, 1); + + HAL_UART_Receive_IT((RS_485_2_UART_Handler.uart), + (uint8_t*) &RS_485_2_UART_Handler.tmp_Rx_Buf, 1); + + HAL_UART_Receive_IT((RS_485_3_UART_Handler.uart), + (uint8_t*) &RS_485_3_UART_Handler.tmp_Rx_Buf, 1); + + HAL_UART_Receive_IT((RS_485_4_UART_Handler.uart), + (uint8_t*) &RS_485_4_UART_Handler.tmp_Rx_Buf, 1); + + HAL_UART_Receive_IT((LTE_7S0_Serial_UART_Handler.uart), + (uint8_t*) <E_7S0_Serial_UART_Handler.tmp_Rx_Buf, 1); + + + + +#if defined (hlpuart1Exit) + IntializeUARTHandler(&LPUART1_UART_Handler, &LPUART1UART, LPUART1_UART_WaitTime, 2,LPUART1_UART_Dispacher_Time); //10ms 剩余2ms + HAL_UART_Receive_IT((LPUART1_UART_Handler.uart), + (uint8_t*) &LPUART1_UART_Handler.tmp_Rx_Buf, 1); + +#endif + + + + + GF_BSP_Interrupt_Add_CallBack( + DF_BSP_InterCall_TIM8_2ms_PeriodElapsedCallback, GF_BSP_UART_Timer); + + //RS_485_2_UART_Handler.send_finished=1; +} +//Count Every 2 ms +void GF_BSP_UART_Timer() +{ + Counting(&RS_485_1_UART_Handler); + Counting(&RS_485_2_UART_Handler); + Counting(&RS_485_3_UART_Handler); + Counting(&RS_485_4_UART_Handler); + Counting(<E_7S0_Serial_UART_Handler); + Counting(&InterCall_DEBUG_UART_Handler); + Counting(&E28_SBUS_UART_Handler); + +#if defined (hlpuart1Exit) + Counting(&LPUART1_UART_Handler); +#endif + + + +} + +void UARTHandlerAddTxList(struct UARTHandler *uartHandler, uint8_t *data, + uint16_t length, uint32_t txListTimePeriod, void (*UART_Decode)(uint8_t*, uint16_t)) +{ + + UARTSendHandler *pTmp = NULL; //临时指针 + //临时指针2用于逐个申请内存 + pTmp = (UARTSendHandler*) malloc(sizeof(UARTSendHandler)); + memcpy(pTmp->Tx_Buf, data, length); + pTmp->pNext = NULL; + pTmp->SendListTimePeriod=txListTimePeriod; + pTmp->SendLength = length; + pTmp->UART_Decode = UART_Decode; + +//if NULL, call intialize one + if (uartHandler->pCurrentUARTSendHadler == NULL) + { + uartHandler->pCurrentUARTSendHadler = pTmp; //空链表 + } else + { + char i = 0; + //插到尾部 + UARTSendHandler *phead = NULL; + phead = uartHandler->pCurrentUARTSendHadler; + while (phead->pNext != NULL) + { + i++; + phead = phead->pNext; + } + phead->pNext = pTmp; + + } + +} + +void UARTHandlerTx(struct UARTHandler *uartHandler) +{ + + if (uartHandler->uart == NULL) + { + LOGFF(DL_ERROR, + "the UART Hardware did not intialize,check the setting"); + return; + } + + uartHandler->RxCount=0;//设定RxCount为0 +#if defined (hlpuart1Exit) + if(uartHandler->uart->Instance == LPUART1) + { + + HAL_UART_Transmit(uartHandler->uart, uartHandler->Tx_Buf, + uartHandler->TxCount,100); + }else + { +#endif + + if (uartHandler->uart->Instance == UART4) //**DEBUG + { + + } else if (uartHandler->uart->Instance == USART1) //**RS485_1 + { + + HAL_GPIO_WritePin(RS485_1_DIR_GPIO_Port, RS485_1_DIR_Pin, GPIO_PIN_SET); + + } else if (uartHandler->uart->Instance == USART3) //**RS485_2 + { + + HAL_GPIO_WritePin(RS485_2_DIR_GPIO_Port, RS485_2_DIR_Pin, GPIO_PIN_SET); + + } else if (uartHandler->uart->Instance == USART6) //**RS485_3 + { + + HAL_GPIO_WritePin(RS485_3_DIR_GPIO_Port, RS485_3_DIR_Pin, GPIO_PIN_SET); + + } else if (uartHandler->uart->Instance == UART7) //**RS485_4 + { + HAL_GPIO_WritePin(RS485_4_DIR_GPIO_Port, RS485_4_DIR_Pin, GPIO_PIN_SET); + + } else if (uartHandler->uart->Instance == USART2)//**E22 // External serial port + { + + } else if (uartHandler->uart->Instance == UART5) //**E28 // SBUS + { + + } + + SCB_CleanInvalidateDCache_by_Addr((uint32_t*) uartHandler->Tx_Buf, + uartHandler->TxCount); + + HAL_UART_Transmit_DMA(uartHandler->uart, uartHandler->Tx_Buf, + uartHandler->TxCount); +#if defined (hlpuart1Exit) + } +#endif + + + if (uartHandler->uart == UART4) //**DEBUG + { + + } else if (uartHandler->uart == USART1) //**RS485_1 + { + HAL_GPIO_WritePin(RS485_1_DIR_GPIO_Port, RS485_1_DIR_Pin, + GPIO_PIN_RESET); + } else if (uartHandler->uart == USART3) //**RS485_2 + { + HAL_GPIO_WritePin(RS485_2_DIR_GPIO_Port, RS485_2_DIR_Pin, + GPIO_PIN_RESET); + } else if (uartHandler->uart == USART6) //**RS485_3 + { + HAL_GPIO_WritePin(RS485_3_DIR_GPIO_Port, + RS485_3_DIR_Pin, GPIO_PIN_RESET); + } else if (uartHandler->uart == UART7) //**RS485_4 + { + HAL_GPIO_WritePin(RS485_4_DIR_GPIO_Port, + RS485_4_DIR_Pin, GPIO_PIN_RESET); + } else if (uartHandler->uart == USART2) //**E22 // External serial port + { + + } else if (uartHandler->uart == UART5) //**E28 // SBUS + { + + } +} +void UARTHandlerRX(struct UARTHandler *uartHandler) +{ + //uartHandler->Wait_Time_Count = 0; + if (uartHandler->startCountFlag == 0) + { + uartHandler->startCountFlag = 1; + uartHandler->RxCount = 0; + } + + uartHandler->Rx_Buf[uartHandler->RxCount] = uartHandler->tmp_Rx_Buf[0]; + uartHandler->RxCount++; + + HAL_UART_Receive_IT(uartHandler->uart, uartHandler->tmp_Rx_Buf, 1); + + uartHandler->Wait_Time_Count = 0; + if(uartHandler->RxCount>=1024)//接收数据过多,直接抛弃 + { + uartHandler->RxCount=0; + } + //HAL_UART_Receive_IT(uartHandler->uart, RS_485_2_UART_Handler.tmp_Rx_Buf, 1); +} + +void IntializeUARTHandler(struct UARTHandler *uartHandler, + UART_HandleTypeDef *uart, int32_t WaitTime, unsigned char timeSpan,int32_t Dispacher_Time) +{ + uartHandler->Wait_Time_Count = 0; + uartHandler->Wait_time = WaitTime; + + uartHandler->uart = uart; + uartHandler->UART_Rx = UARTHandlerRX; + uartHandler->UART_Tx = UARTHandlerTx; + uartHandler->AddSendList = UARTHandlerAddTxList; + + uartHandler->dispacherController = (DispacherController*) malloc( + sizeof(DispacherController)); + + uartHandler->dispacherController->pHead = NULL; + uartHandler->dispacherController->pTail = NULL; + uartHandler->dispacherController->Dispacher_Enable = 0; + uartHandler->dispacherController->DispacherCallTime = Dispacher_Time ; // call the function every 50 ms + uartHandler->dispacherController->Dispacher_Counter = 0; + uartHandler->dispacherController->DispacherNumber = 0; + uartHandler->dispacherController->Add_Dispatcher_List = Dispatcher_List_Add_t; + uartHandler->dispacherController->Dispatcher_Run = Dispatch_t; + + uartHandler->timeSpan = 2; + uartHandler->SendList_time_Count = 0; + uartHandler->SendList_Period = 100; + +} + +void Counting(struct UARTHandler *uartHandler) +{ + + if (uartHandler->UART_Decode == NULL) //不解析,直接返回true + { + uartHandler->decode_finished = 1; + } else + { + if (uartHandler->startCountFlag == 1) + { + uartHandler->Wait_Time_Count++; + if (uartHandler->timeSpan * uartHandler->Wait_Time_Count + >= uartHandler->Wait_time) + { + uartHandler->Wait_Time_Count = 0; + uartHandler->startCountFlag = 0; + //启动解析函数 + if (uartHandler->RxCount >= 1) + { + if(uartHandler->UART_Decode!=NULL) + { + uartHandler->UART_Decode(uartHandler->Rx_Buf, + uartHandler->RxCount); + } + + uartHandler->RxCount = 0; + } + } + + } + } + + if (uartHandler->pCurrentUARTSendHadler != NULL) + { + + GF_UART_Send_List_Send(uartHandler); + } else + { + uartHandler->dispacherController->Dispatcher_Run( + uartHandler->dispacherController); + } + + + +} +//_weak +void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) +{ + if (huart->Instance == UART4) //**DEBUG + { + UARTHandlerRX(&InterCall_DEBUG_UART_Handler); + + //GF_BSP_Interrupt_Run_CallBack(DF_BSP_InterCall_DEBUG_RxCpltCallback); + + } else if (huart->Instance == USART1) //**RS485_1 + { + //GF_BSP_Interrupt_Run_CallBack(DF_BSP_InterCall_RS485_1_RxCpltCallback); + + UARTHandlerRX(&RS_485_1_UART_Handler); + } else if (huart->Instance == USART3) //**RS485_2 + { + //GF_BSP_Interrupt_Run_CallBack(DF_BSP_InterCall_RS485_2_RxCpltCallback); + UARTHandlerRX(&RS_485_2_UART_Handler); + } else if (huart->Instance == USART6) //**RS485_3 + { + //GF_BSP_Interrupt_Run_CallBack(DF_BSP_InterCall_RS485_3_RxCpltCallback); + UARTHandlerRX(&RS_485_3_UART_Handler); + } else if (huart->Instance == UART7) //**RS485_4 + { +// UARTHandlerRX(&RS_485_4_UART_Handler); + //GF_BSP_Interrupt_Run_CallBack(DF_BSP_InterCall_RS485_4_RxCpltCallback); + UARTHandlerRX(&RS_485_4_UART_Handler); + + } else if (huart->Instance == USART2) //**E22 // External serial port + { +// GF_BSP_Interrupt_Run_CallBack( +// DF_BSP_InterCall_E22_Serial_RxCpltCallback); + UARTHandlerRX(<E_7S0_Serial_UART_Handler); + } else if (huart->Instance == UART5) //**E28 // SBUS + { + +// GF_BSP_Interrupt_Run_CallBack( +// DF_BSP_InterCall_E28_SBUS_RxFifo0Callback); + UARTHandlerRX(&E28_SBUS_UART_Handler); + } + + + #if defined (hlpuart1Exit) + else if (huart->Instance == LPUART1) //**E28 // SBUS + { + UARTHandlerRX(&LPUART1_UART_Handler); + } + + + #endif +} + +void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) +{ + + if (huart->Instance == UART4) //**DEBUG + { + + } else if (huart->Instance == USART1) //**RS485_1 + { + HAL_GPIO_WritePin(RS485_1_DIR_GPIO_Port, RS485_1_DIR_Pin, + GPIO_PIN_RESET); + } else if (huart->Instance == USART3) //**RS485_2 + { + HAL_GPIO_WritePin(RS485_2_DIR_GPIO_Port, RS485_2_DIR_Pin, + GPIO_PIN_RESET); + } else if (huart->Instance == USART6) //**RS485_3 + { + HAL_GPIO_WritePin(RS485_3_DIR_GPIO_Port, + RS485_3_DIR_Pin, GPIO_PIN_RESET); + } else if (huart->Instance == UART7) //**RS485_4 + { + HAL_GPIO_WritePin(RS485_4_DIR_GPIO_Port, + RS485_4_DIR_Pin, GPIO_PIN_RESET); + } else if (huart->Instance == USART2) //**E22 // External serial port + { + + } else if (huart->Instance == UART5) //**E28 // SBUS + { + + } + +} + +//RS485_Index:1-4 RS485; 5 ExternSerial; 6 Debug; +void GF_BSP_UART_Transmit(const uint8_t RS485_Index, const uint8_t *pData, + uint16_t Size) +{ + UART_HandleTypeDef *huart; + if (Size > UART_Transmit_MAX_NUM) + Size = UART_Transmit_MAX_NUM; + + switch (RS485_Index) + { + case 1: + huart = &huart1; + HAL_GPIO_WritePin(RS485_1_DIR_GPIO_Port, RS485_1_DIR_Pin, + GPIO_PIN_SET); + memcpy(RS485_1_TxDMA_buf, pData, Size); + SCB_CleanInvalidateDCache_by_Addr((uint32_t*) RS485_1_TxDMA_buf, + Size); + HAL_UART_Transmit_DMA(huart, RS485_1_TxDMA_buf, Size); + //HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff); + + break; + case 2: + huart = &huart3; + HAL_GPIO_WritePin(RS485_2_DIR_GPIO_Port, RS485_2_DIR_Pin, + GPIO_PIN_SET); + memcpy(RS485_2_TxDMA_buf, pData, Size); + SCB_CleanInvalidateDCache_by_Addr((uint32_t*) RS485_2_TxDMA_buf, + Size); + HAL_UART_Transmit_DMA(huart, RS485_2_TxDMA_buf, Size); + break; + case 3: + huart = &huart6; + HAL_GPIO_WritePin(RS485_3_DIR_GPIO_Port, RS485_3_DIR_Pin, + GPIO_PIN_SET); + memcpy(RS485_3_TxDMA_buf, pData, Size); + SCB_CleanInvalidateDCache_by_Addr((uint32_t*) RS485_3_TxDMA_buf, + Size); + HAL_UART_Transmit_DMA(huart, RS485_3_TxDMA_buf, Size); + break; + case 4: + huart = &huart7; + HAL_GPIO_WritePin(RS485_4_DIR_GPIO_Port, RS485_4_DIR_Pin, + GPIO_PIN_SET); + memcpy(RS485_4_TxDMA_buf, pData, Size); + SCB_CleanInvalidateDCache_by_Addr((uint32_t*) RS485_4_TxDMA_buf, + Size); + HAL_UART_Transmit_DMA(huart, RS485_4_TxDMA_buf, Size); + break; + case 5: + huart = &huart2; + memcpy(ExternSerial_TxDMA_buf, pData, Size); + SCB_CleanInvalidateDCache_by_Addr( + (uint32_t*) ExternSerial_TxDMA_buf, Size); + HAL_UART_Transmit_DMA(huart, ExternSerial_TxDMA_buf, Size); + break; + default: + huart = &huart4; + memcpy(Debug_TxDMA_buf, pData, Size); + SCB_CleanInvalidateDCache_by_Addr((uint32_t*) Debug_TxDMA_buf, + Size); + HAL_UART_Transmit_DMA(huart, Debug_TxDMA_buf, Size); + break; + } +} +void GF_UART_Send_List_Send(struct UARTHandler *handler) +{ + + handler->SendList_time_Count++; + if (handler->timeSpan * handler->SendList_time_Count + >= handler->SendList_Period) + { + handler->SendList_time_Count = 0; + handler->SendListExists = 1; + if (handler->pCurrentUARTSendHadler != NULL) + { + //拷贝数据到相关的代码中,然后发送 + + //handler->CAN_Decode = handler->pCurrentCANSendHadler->CAN_Decode; // + memcpy(handler->Tx_Buf, handler->pCurrentUARTSendHadler->Tx_Buf, + handler->pCurrentUARTSendHadler->SendLength); + handler->SendList_Period = + handler->pCurrentUARTSendHadler->SendListTimePeriod; + handler->TxCount = handler->pCurrentUARTSendHadler->SendLength; + //添加了新的UARTDecode代码,需要做测试,适合一个485线上挂至少2个设备 + handler->UART_Tx(handler); + handler->UART_Decode=handler->pCurrentUARTSendHadler->UART_Decode; + //计数重新开始 + //handler->RxCount=0; + + if (handler->pCurrentUARTSendHadler->pNext != NULL) + { + UARTSendHandler *temp = handler->pCurrentUARTSendHadler->pNext; + free(handler->pCurrentUARTSendHadler); //清除内存 + handler->pCurrentUARTSendHadler = temp; + } else + { + free(handler->pCurrentUARTSendHadler); //清除内存 + handler->pCurrentUARTSendHadler = NULL; + } + + } else + { + handler->SendListExists = 0; + + } + + } + +} diff --git a/Bingoo/base/bsp_UDP.c b/Bingoo/base/bsp_UDP.c new file mode 100644 index 0000000..10ca979 --- /dev/null +++ b/Bingoo/base/bsp_UDP.c @@ -0,0 +1,430 @@ +/* + * bsp_UDP.c + * + * Created on: Aug 13, 2024 + * Author: akeguo + */ + +#include "stm32h7xx_hal.h" +#include "lwip.h" +#include "udp.h" +#include "string.h" +#include "bsp_UDP.h" +#include "bsp_DLT_Log.h" +#include +#include "BSP/bsp_GPIO.h" +void UDP_GV_Dispatch(); +void UDP_IV_Dispatch(); +void udp_cmd_send_GV(char *pData, uint16_t Size); +/* 定义端口号 */ +#define UDP_DLT_LOCAL_PORT 8000 /* 本地端口 */ +#define UDP_CMD_LOCAL_PORT 8002 /* 本地端口 */ +#define UDP_CMD_LOCAL_Android_Listen_PORT 8006 /* 本地端口 接收安卓 */ + +#define UDP_DLT_Send_LOCAL_PORT 7000 /* 本地端口 */ +#define UDP_CMD_Send_LOCAL_PORT 7002 /* 本地端口 */ +#define UDP_GV_Send_LOCAL_PORT 7004 /* 本地端口 */ +#define UDP_Android_Send_LOCAL_PORT 7006 /* 本地端口 发给安卓*/ +/*32从7006发往安卓9006*/ +/*安卓从9006发往32的8006*/ +#define UDP_REMOTE_DLT_PORT 9000 /* 远端端口 */ +#define UDP_REMOTE_CMD_PORT 9002 /* 远端端口 */ +#define UDP_REMOTE_GV_PORT 9004 /* 远端端口 */ +#define UDP_REMOTE_Android_PORT 9006 /* 远端端口 */ + +int8_t is_udp_GV_update_loop_enalbed = 0; +unsigned char received_data[1000]; + +/* udp控制块 */ +static struct udp_pcb *upcb_Rx_DLT; +static struct udp_pcb *upcb_Rx_Cmd; +static struct udp_pcb *upcb_Rx_From_Android; + +static struct udp_pcb *upcb_Tx_DLT; +static struct udp_pcb *upcb_Tx_Cmd; +static struct udp_pcb *upcb_Tx_GV; +static struct udp_pcb *upcb_Tx_Android; + +ip_addr_t serverIP; + +ip_addr_t Android_ServerIP; + +DLT_DecodeFuncPtr UDP_DLT_ReceivedCallback; + +/****************************************************************************** + * 描述 : 接收回调函数 + * 参数 : - + * 返回 : 无 + ******************************************************************************/ +static void udp_receive_callback(void *arg, struct udp_pcb *upcb, + struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + if (p == NULL) return; + + memcpy(received_data, p->payload, p->len); + + if (upcb->local_port == UDP_DLT_LOCAL_PORT) + { + UDP_DLT_ReceivedCallback(received_data, p->len); + //DLT_DataReceiveEndCallback(received_data, p->len); + } + else if (upcb->local_port == UDP_CMD_LOCAL_PORT) + { + + if (*received_data == 0x55 && *(received_data + 1) == 0x55 + && p->len >= 3) + { + decode_command_and_feedback(received_data + 2, p->len - 2, 2, + NULL); //0代表UDP + } + else if (*received_data == 0x66 && *(received_data + 1) == 0x66 + && p->len >= 3) + { + GF_BSP_GPIO_SetIO(received_data[3], received_data[2]); + + } + else + { + udp_cmd_send_back(received_data, p->len); + } + } + else if (upcb->local_port == UDP_CMD_LOCAL_Android_Listen_PORT) + { + //对PV数据进行修改 + //if (*buffer == 0x55 && *(buffer + 1) == 0x55 && length >= 4) + if (received_data[0] != 0x55 || received_data[1] != 0x55 || p->len < 4) + { + return; + } + + uint16_t crc_check = ((received_data[p->len - 1] << 8) + | received_data[p->len - 2]); + uint16_t crc_check1 = MB_CRC16(received_data, p->len - 2); + /* CRC 校验正确 */ + if (crc_check != MB_CRC16(received_data, p->len - 2)) return; + + if (received_data[2] != 0x01 || received_data[3] != 0x01) return; + + pb_istream_t i_pv_stream = + { 0 }; + + i_pv_stream = pb_istream_from_buffer(&received_data[4], p->len - 4); + pb_decode(&i_pv_stream, PV_struct_define_fields, &decoded_PV); + + } + pbuf_free(p); + +} + +//char UDPprintf[100]; + +void udp_dlt_send_back(char *pData, uint16_t Size) +{ + struct pbuf *p; + + /* 分配缓冲区空间 */ + p = pbuf_alloc(PBUF_TRANSPORT, Size, PBUF_RAM); + if (p != NULL) + { + /* 填充缓冲区数据 */ + pbuf_take(p, pData, Size); + + /* 发送udp数据 */ + + //udp_send(upcb_DLT, p); + err_t t = udp_sendto(upcb_Tx_DLT, p, &serverIP, + UDP_REMOTE_DLT_PORT); + /* 释放缓冲区空间 */ + pbuf_free(p); + } +} +void udp_cmd_send_back(char *pData, uint16_t Size) +{ + struct pbuf *p; + + /* 分配缓冲区空间 */ + p = pbuf_alloc(PBUF_TRANSPORT, Size, PBUF_RAM); + + if (p != NULL) + { + /* 填充缓冲区数据 */ + pbuf_take(p, pData, Size); + + /* 发送udp数据 */ + err_t err = udp_send(upcb_Tx_Cmd, p); + if (err != ERR_OK) + { + // 发送失败 + printf("Failed to send UDP data: %d\n", err); + } + /* 释放缓冲区空间 */ + pbuf_free(p); + } +} + +void udp_cmd_send_GV(char *pData, uint16_t Size) +{ + struct pbuf *p; + + /* 分配缓冲区空间 */ + p = pbuf_alloc(PBUF_TRANSPORT, Size, PBUF_RAM); + + if (p != NULL) + { + /* 填充缓冲区数据 */ + pbuf_take(p, pData, Size); + + /* 发送udp数据 */ + err_t err = udp_send(upcb_Tx_GV, p); + if (err != ERR_OK) + { + // 发送失败 + //printf("Failed to send UDP data: %d\n", err); + } + /* 释放缓冲区空间 */ + pbuf_free(p); + } +} + +void udp_send_by_pcb(struct udp_pcb *upcb, char *pData, uint16_t Size) +{ + struct pbuf *p; + + /* 分配缓冲区空间 */ + p = pbuf_alloc(PBUF_TRANSPORT, Size, PBUF_RAM); + + if (p != NULL) + { + /* 填充缓冲区数据 */ + pbuf_take(p, pData, Size); + + /* 发送udp数据 */ + err_t err = udp_send(upcb, p); + if (err != ERR_OK) + { + // 发送失败 + //printf("Failed to send UDP data: %d\n", err); + } + /* 释放缓冲区空间 */ + pbuf_free(p); + } +} + +/****************************************************************************** + * 描述 : 创建udp客户端 + * 参数 : 无 + * 返回 : 无 + ******************************************************************************/ +void udp_client_init(void) +{ + + GF_BSP_Interrupt_Add_CallBack( + DF_BSP_InterCall_TIM8_2ms_PeriodElapsedCallback, UDP_GV_Dispatch); + //将UDP上传IV关闭 + GF_BSP_Interrupt_Add_CallBack( + DF_BSP_InterCall_TIM8_2ms_PeriodElapsedCallback, UDP_IV_Dispatch); + //Timer intialize(); + err_t err; + + IP4_ADDR(&serverIP, 192, 168, 144, 255); + IP4_ADDR(&Android_ServerIP, 192, 168, 144, 20); + + /* 创建udp控制块 */ + upcb_Rx_DLT = udp_new(); + + if (upcb_Rx_DLT != NULL) + { + /* 配置本地端口 */ + //upcb_DLT->local_port = UDP_DLT_LOCAL_PORT; + /* 配置服务器IP和端口 */ + //upcb_DLT->so_options |= SOF_BROADCAST; + //err = udp_connect(upcb_DLT, &serverIP, UDP_REMOTE_DLT_PORT); + err = udp_bind(upcb_Rx_DLT, IP_ADDR_ANY, UDP_DLT_LOCAL_PORT); + if (err == ERR_OK) + { + /* 注册接收回调函数 */ + /* 注册接收回调函数 */ + udp_recv(upcb_Rx_DLT, udp_receive_callback, NULL); + } + else + { + udp_remove(upcb_Rx_DLT); + + } + } + + upcb_Rx_From_Android = udp_new(); + + if (upcb_Rx_From_Android != NULL) + { + /* 配置本地端口 */ + //upcb_DLT->local_port = UDP_DLT_LOCAL_PORT; + /* 配置服务器IP和端口 */ + //upcb_DLT->so_options |= SOF_BROADCAST; + //err = udp_connect(upcb_DLT, &serverIP, UDP_REMOTE_DLT_PORT); + err = udp_bind(upcb_Rx_From_Android, IP_ADDR_ANY, + UDP_CMD_LOCAL_Android_Listen_PORT); + if (err == ERR_OK) + { + /* 注册接收回调函数 */ + /* 注册接收回调函数 */ + udp_recv(upcb_Rx_From_Android, udp_receive_callback, NULL); + } + else + { + udp_remove(upcb_Rx_From_Android); + + } + } + + upcb_Rx_Cmd = udp_new(); + + if (upcb_Rx_Cmd != NULL) + { + /* 配置本地端口 */ + //upcb_Cmd->local_port = UDP_CMD_LOCAL_PORT; + /* 配置服务器IP和端口 */ + //upcb_Cmd->so_options |= SOF_BROADCAST; + //err = udp_connect(upcb_Cmd, &serverIP, UDP_REMOTE_CMD_PORT); + err = udp_bind(upcb_Rx_Cmd, IP_ADDR_ANY, UDP_CMD_LOCAL_PORT); + if (err == ERR_OK) + { + /* 注册接收回调函数 */ + udp_recv(upcb_Rx_Cmd, udp_receive_callback, NULL); + } + else + { + udp_remove(upcb_Rx_Cmd); + } + } + + upcb_Tx_Cmd = udp_new(); + + if (upcb_Tx_Cmd != NULL) + { + /* 配置本地端口 */ + upcb_Tx_Cmd->local_port = UDP_CMD_Send_LOCAL_PORT; + + /* 配置服务器IP和端口 */ + //upcb_Cmd->so_options |= SOF_BROADCAST; + err = udp_connect(upcb_Tx_Cmd, &serverIP, UDP_REMOTE_CMD_PORT); + + if (err == ERR_OK) + { + /* 注册接收回调函数 */ + //udp_recv(upcb_Tx_Cmd, udp_receive_callback, NULL); + } + else + { + udp_remove(upcb_Tx_Cmd); + } + } + upcb_Tx_DLT = udp_new(); + + if (upcb_Tx_DLT != NULL) + { + /* 配置本地端口 */ + upcb_Tx_Cmd->local_port = UDP_DLT_Send_LOCAL_PORT; + /* 配置服务器IP和端口 */ + //upcb_Cmd->so_options |= SOF_BROADCAST; + err = udp_connect(upcb_Tx_DLT, &serverIP, UDP_REMOTE_DLT_PORT); + + if (err == ERR_OK) + { + /* 注册接收回调函数 */ + //udp_recv(upcb_Tx_Cmd, udp_receive_callback, NULL); + } + else + { + udp_remove(upcb_Tx_DLT); + } + } + + upcb_Tx_GV = udp_new(); + + if (upcb_Tx_GV != NULL) + { + /* 配置本地端口 */ + upcb_Tx_Cmd->local_port = UDP_GV_Send_LOCAL_PORT; + /* 配置服务器IP和端口 */ + //upcb_Cmd->so_options |= SOF_BROADCAST; + err = udp_connect(upcb_Tx_GV, &serverIP, UDP_REMOTE_GV_PORT); + + if (err == ERR_OK) + { + /* 注册接收回调函数 */ + //udp_recv(upcb_Tx_Cmd, udp_receive_callback, NULL); + } + else + { + udp_remove(upcb_Tx_GV); + } + } + + upcb_Tx_Android = udp_new(); + + if (upcb_Tx_Android != NULL) + { + /* 配置本地端口 */ + upcb_Tx_Android->local_port = UDP_Android_Send_LOCAL_PORT; + /* 配置服务器IP和端口 */ + //upcb_Cmd->so_options |= SOF_BROADCAST; + err = udp_connect(upcb_Tx_Android, &Android_ServerIP, + UDP_REMOTE_Android_PORT); + + if (err == ERR_OK) + { + /* 注册接收回调函数 */ + //udp_recv(upcb_Tx_Cmd, udp_receive_callback, NULL); + } + else + { + udp_remove(upcb_Tx_Android); + } + } + +} +int counter_index = 0; +int iv_counter_index = 0; +void UDP_GV_Dispatch() +{ + counter_index++; + if (counter_index <= 50) return; + if (is_udp_GV_update_loop_enalbed == 0) return; + counter_index = 0; + pb_ostream_t GV_o_stream = + { 0 }; + char buf[1024]; + GV_o_stream = pb_ostream_from_buffer(&buf[2], sizeof(buf)); + pb_encode(&GV_o_stream, GV_struct_define_fields, &GV); + buf[1] = 0xfe; + buf[0] = 0xfe; + //memcpy(&wh_LTE_7S0_Handler->Tx_Buf[2], buf, GV_o_stream.bytes_written); + udp_cmd_send_GV(buf, GV_o_stream.bytes_written + 2); + +} +//现在是每一百ms执行一次 +void UDP_IV_Dispatch() +{ + iv_counter_index++; + if (iv_counter_index <= 50) return; + iv_counter_index=0; + char Tx_Buf[1024]; + pb_ostream_t IV_o_stream = pb_ostream_from_buffer(&Tx_Buf[2], + sizeof(Tx_Buf) - 2); + pb_encode(&IV_o_stream, IV_struct_define_fields, &IV); + + Tx_Buf[0] = 0x55; + Tx_Buf[1] = 0x55; + int32_t TxCount = IV_o_stream.bytes_written + 4; + uint16_t crc = MB_CRC16(Tx_Buf, IV_o_stream.bytes_written + 2); + + Tx_Buf[IV_o_stream.bytes_written + 2] = (crc >> 8) & 0xff; + Tx_Buf[IV_o_stream.bytes_written + 3] = crc & 0xff; + + udp_send_by_pcb(upcb_Tx_Android, Tx_Buf, IV_o_stream.bytes_written + 4); + +} + +/******************************** END OF FILE ********************************/ + diff --git a/Bingoo/base/bsp_UpperComputer_Handler.c b/Bingoo/base/bsp_UpperComputer_Handler.c new file mode 100644 index 0000000..503f1cc --- /dev/null +++ b/Bingoo/base/bsp_UpperComputer_Handler.c @@ -0,0 +1,114 @@ +/* + * bsp_desulfurizer_handler.c + * + * Created on: Jul 29, 2024 + * Author: akeguo + */ +#include "msp_WH_LTE_7S0.h" + +#include "pb_decode.h" +#include "pb_encode.h" +#include "bsp_include.h" +#include "pb.h" + +#include "bsp_Cmd.pb.h" +#include +#include +#include + + +#include "BHBF_ROBOT.h" +#include "bsp_cpu_flash.h" +#include +#include + +#include "bsp_decode_command.h" +void decode_command_from_computer(uint8_t *buffer, uint16_t length); +struct UARTHandler *desulfurizer_message_UART_Handler; + +void upper_Computer_UART_Handler_intialize(struct UARTHandler *Handler) +{ + + //LOG("desulfurizer_message_UART_Handler_intialize"); + desulfurizer_message_UART_Handler = Handler; + desulfurizer_message_UART_Handler->dispacherController->Dispacher_Enable=0;//不周期性发送 + desulfurizer_message_UART_Handler->Wait_time=30; + desulfurizer_message_UART_Handler->UART_Decode = + decode_command_from_computer; //indicate that there is no need to listen + //desulfurizer_message_UART_Handler->DispacherCallPeriod=200; + + //desulfurizer_message_UART_Handler->Add_Dispatcher_List(desulfurizer_message_UART_Handler,steering_set_angle); + } + + + + +void send_data_to_upper_computer(double Angle, double WireLength, + double Thickness, char IsFittingPoint,char isMqtt,struct UARTHandler *send_UART_Handler) +{ +// LOG("send collected data to computer"); +// DesulfurizerMessage _desulfurizer = DesulfurizerMessage_init_default; +// pb_ostream_t output_stream = +// { 0 }; +// +// _desulfurizer.Angle = Angle; +// _desulfurizer.WireLength = WireLength; +// _desulfurizer.Thickness = Thickness; +// _desulfurizer.IsFittingPoint = IsFittingPoint; +// char buf[1024]; +// output_stream = pb_ostream_from_buffer(buf, sizeof(buf)); +// pb_encode(&output_stream, DesulfurizerMessage_fields, &_desulfurizer); //encode to buffer + +// Cmd send_Cmd = Cmd_init_default; +// +// //将数据拷贝到Command中 +// send_Cmd.CommadNum = 5; +// send_Cmd.Buff_Data_Length = output_stream.bytes_written; +// //拷贝数据到send_Cmd.Buff_Data中 +// memcpy(send_Cmd.Buff_Data, buf, send_Cmd.Buff_Data_Length); +// pb_ostream_t Cmd_out_stream = +// { 0 }; +// +// if(isMqtt==1) +// { +// Cmd_out_stream = pb_ostream_from_buffer( +// &send_UART_Handler->Tx_Buf[2], +// sizeof(desulfurizer_message_UART_Handler->Tx_Buf)-2); +// pb_encode(&Cmd_out_stream, Cmd_fields, &send_Cmd); //encode to buffer +// send_UART_Handler->Tx_Buf[0]='3'; +// send_UART_Handler->Tx_Buf[1]=','; +// send_UART_Handler->TxCount = Cmd_out_stream.bytes_written+2; +// send_UART_Handler->UART_Tx( +// send_UART_Handler); +// } +// else +// { +// Cmd_out_stream = pb_ostream_from_buffer( +// send_UART_Handler->Tx_Buf, +// sizeof(send_UART_Handler->Tx_Buf)); +// pb_encode(&Cmd_out_stream, Cmd_fields, &send_Cmd); //encode to buffer +// +// send_UART_Handler->TxCount = Cmd_out_stream.bytes_written; +// send_UART_Handler->UART_Tx( +// send_UART_Handler); +// } + +} + + + + + +void decode_command_from_computer(uint8_t *buffer, uint16_t length) +{ + + if(*buffer==0x55 && *(buffer+1)==0x55 && length>=3) + { + decode_command_and_feedback(buffer+2, length-2, 0, + desulfurizer_message_UART_Handler);//0代表非mqtt + } + +} + + + diff --git a/Bingoo/base/bsp_client_setting.c b/Bingoo/base/bsp_client_setting.c new file mode 100644 index 0000000..636607e --- /dev/null +++ b/Bingoo/base/bsp_client_setting.c @@ -0,0 +1,126 @@ +/* + * bsp_pv_setting.c + * + * Created on: Jan 8, 2025 + * Author: akeguo + */ +#include +#include "BHBF_ROBOT.h" + +#include "gpio.h" + +#include "BSP/bsp_UART.h" + +void UpdateIV(); +void decode_received_data_from_client(uint8_t *buffer, uint16_t length); + +struct UARTHandler *client_setting_Handler; +DispacherController *client_setting_dispacher; + +void client_setting_intialize(struct UARTHandler *Handler) +{ + + client_setting_Handler = Handler; + client_setting_Handler->Wait_time = 6; // 最低不要低于4; + + client_setting_dispacher = Handler->dispacherController; + client_setting_dispacher->Add_Dispatcher_List(client_setting_dispacher, + UpdateIV); + client_setting_dispacher->DispacherCallTime = 500; + client_setting_dispacher->Dispacher_Enable=1;//不周期性发送 + LOG("client_setting_intialize"); + + client_setting_Handler->UART_Decode = decode_received_data_from_client; //indicate that there is no need to listen + +} + +void UpdateIV() +{ + + pb_ostream_t IV_o_stream = pb_ostream_from_buffer( + &client_setting_Handler->Tx_Buf[2], + sizeof(client_setting_Handler->Tx_Buf) - 2); + pb_encode(&IV_o_stream, IV_struct_define_fields, &IV); + + client_setting_Handler->Tx_Buf[0] = 0x55; + client_setting_Handler->Tx_Buf[1] = 0x55; + client_setting_Handler->TxCount = IV_o_stream.bytes_written + 4; + + uint16_t crc=MB_CRC16(&(client_setting_Handler->Tx_Buf[0]), IV_o_stream.bytes_written + 2); + + client_setting_Handler->Tx_Buf[IV_o_stream.bytes_written + 2] = (crc>>8) &0xff; + client_setting_Handler->Tx_Buf[IV_o_stream.bytes_written + 3] = crc & 0xff;; + + + client_setting_Handler->UART_Tx(client_setting_Handler); +} + +void decode_received_data_from_client(uint8_t *buffer, uint16_t length) +{ + if(length>100) + { + return; + } + uint8_t data[100]; + memcpy(data,buffer,length); + + //if (*buffer == 0x55 && *(buffer + 1) == 0x55 && length >= 4) + if (buffer[0] == 0x55 && buffer[1] == 0x55 && length >= 4) + { + uint16_t crc_check = ((buffer[length - 1] << 8) | buffer[length - 2]); + uint16_t crc_check1 = MB_CRC16(buffer, length - 2); + /* CRC 校验正确 */ + if (crc_check == MB_CRC16(buffer, length - 2)) + { + //if (*(buffer + 2) == 0x01 && *(buffer + 3) == 0x01) //01 01 设置PV + if (buffer[2] == 0x01 && buffer[3] == 0x01) //01 01 设置PV + { + + pb_istream_t i_pv_stream = + { 0 }; + + i_pv_stream = pb_istream_from_buffer(&buffer[4], length - 4); + pb_decode(&i_pv_stream, PV_struct_define_fields, &decoded_PV_variable); + //pb_decode(&i_pv_stream, PV_struct_define_fields, &decoded_PV); + + +// if(decoded_PV_variable.TimeStamp>decoded_PV.TimeStamp) +// { +// decoded_PV=decoded_PV_variable; +// } + //将CV写入EEPROM + //CV_struct_define saved_cV = GF_BSP_EEPROM_Get_CV(); + //GV.PV = decoded_PV; + //GF_BSP_EEPROM_Set_CV(CV); + } + else if (*(buffer + 2) == 0x02 && *(buffer + 3) == 0x01) //设置PV + { + + } + else if (*(buffer + 2) == 0x03 && *(buffer + 3) == 0x01) //返回IV + { + + } + else + { + + } + + } + else + { + //Decode Error; + //log_error("wire sensor decoding failed"); + LOGFF(DL_ERROR, "android decoding failed"); + + } + + } + +// client_setting_Handler->Tx_Buf[0]='1'; +// client_setting_Handler->Tx_Buf[1]=','; +// //wh_LTE_7S0_Handler->Tx_Buf[2]='1'; +// client_setting_Handler->TxCount = 2; +// client_setting_Handler->UART_Tx(client_setting_Handler); +} + diff --git a/Bingoo/base/bsp_com_helper.c b/Bingoo/base/bsp_com_helper.c new file mode 100644 index 0000000..c1fc03e --- /dev/null +++ b/Bingoo/base/bsp_com_helper.c @@ -0,0 +1,191 @@ +/* + * bsp_com_helper.c + * + * Created on: Oct 9, 2024 + * Author: akeguo + */ +#include "bsp_com_helper.h" +#include +#include "DLTuc.h" +#include "BHBF_ROBOT.h" + +void Dispatch_t(DispacherController *uartHandler) +{ +//2ms + + if (uartHandler->Dispacher_Enable == 1) + { + if (uartHandler->DispacherNumber > 0) //列表中有数据 + { + uartHandler->Dispacher_Counter++; + + if (uartHandler->Dispacher_Counter + >= uartHandler->DispacherCallTime / 2 + / (uartHandler->DispacherNumber)) //多长时间运行一次 + { + uartHandler->Dispacher_Counter = 0; + if (uartHandler->pHead != NULL + && uartHandler->pHead->pNext != NULL) + { + + uartHandler->pHead->dispache(); + + uartHandler->pHead = uartHandler->pHead->pNext; + + } else + { + + } + } + } + + } +} + +void Dispatcher_List_Add_t(DispacherController *uartHandler, + void (*dispache)(void)) +{ + Dispatcher *pTmp = NULL; //临时指针2 + + if (uartHandler->pHead == NULL && uartHandler->pTail == NULL) //头尾部都为空 + { + uartHandler->pHead = uartHandler->pTail = (Dispatcher*) malloc( + sizeof(Dispatcher)); + uartHandler->pHead->dispache = dispache; + uartHandler->pTail->dispache = dispache; + + + + uartHandler->pHead->pNext = uartHandler->pTail; + + uartHandler->pTail->pNext = uartHandler->pHead; + uartHandler->DispacherNumber++; + } else + { + //临时指针2用于逐个申请内存 + pTmp = (Dispatcher*) malloc(sizeof(Dispatcher)); + pTmp->dispache = dispache; + + + pTmp->pNext = uartHandler->pHead; //set the new dispatcher .next to the header, thus make it a circle + + //临时指针1的next指向刚分配内存的临时指针2 + uartHandler->pTail->pNext = pTmp; + + uartHandler->pTail = pTmp; //set pTail the last node of this ring + uartHandler->DispacherNumber++; + } +} + +void ComHardWare_List_Add_t(HardWareController *uartHandler, char *name, + char value,uint32_t bitFlag) +{ + + ComHardWare *pTmp = NULL; //临时指针2 + if (uartHandler->pComHWHead == NULL && uartHandler->pComHWTail == NULL) //头尾部都为空 + { + uartHandler->pComHWHead = uartHandler->pComHWTail = + (ComHardWare*) malloc(sizeof(ComHardWare)); + + memset(uartHandler->pComHWHead->Name, '\0', + sizeof(uartHandler->pComHWHead->Name)); + memcpy(uartHandler->pComHWHead->Name, name, strlen(name)); + uartHandler->pComHWHead->IsOnline = value; + uartHandler->pComHWHead->BitFlag = bitFlag; + uartHandler->pComHWHead->pNext = NULL; + } else + { + + pTmp = (ComHardWare*) malloc(sizeof(ComHardWare)); + memset(pTmp->Name, '\0', sizeof(pTmp->Name)); + memcpy(pTmp->Name, name, strlen(name)); + + pTmp->BitFlag = bitFlag; + pTmp->IsOnline = value; + pTmp->pNext = NULL; //set the new dispatcher .next to the header, thus make it a circle + uartHandler->pComHWTail->pNext = pTmp; + uartHandler->pComHWTail = pTmp; + + } + +} +//HardWareErrorController->Set_PCOMHardWare = Set_PCOMHardWare_t; +int Set_PCOMHardWare_t(HardWareController *uartHandler, char *name, char value) +{ + + ComHardWare *ptr = uartHandler->pComHWHead; + char finddata = 0; + + if (ptr == NULL) + { + + return 0; + } + + while (ptr != NULL) + { + if (strcmp(ptr->Name, name) == 0)//相等为0 + { + ptr->IsOnline = value; + finddata = 1; + return finddata; + } else + { + ptr = ptr->pNext; + } + + } + return finddata; + +} + +char str1[50] = "\0"; +void PCOMHardWare_Check_t(HardWareController *uartHandler) +{ + uartHandler->HardWare_Check_Counter++; +// if (uartHandler->HardWare_Check_Counter*2 +// >= uartHandler->DispacherCallTime * 6) //make sure every + if (uartHandler->HardWare_Check_Counter * 2 >= uartHandler->DispacherCallTime) //make sure every + { + ComHardWare *ptr = uartHandler->pComHWHead; + + if (!ptr) + { + uartHandler->HardWare_Check_Counter = 0; + //printf("链表为空\n"); + return; + } + char IsAbnornalStatus = 0; + + //check invalid state + while (ptr != NULL) + { + if (ptr->IsOnline != 1) //在线设为1 + { + memset(str1, '\0', 50); + memcpy(str1, ptr->Name, strlen(ptr->Name)); + LOGFF(DL_ERROR, "connecting Error %s", ptr->Name); + SET_BIT_1(SystemErrorCode,ptr->BitFlag); + //*SystemErrorCode=*SystemErrorCode|(1<BitFlag); + IsAbnornalStatus = 1; + }else + { + //*SystemErrorCode=*SystemErrorCode|(1<BitFlag); + SET_BIT_0(SystemErrorCode,ptr->BitFlag); + } + ptr = ptr->pNext; + } + + //set invalid state + ptr = uartHandler->pComHWHead; + while (ptr != NULL) + { + ptr->IsOnline = 0; + ptr = ptr->pNext; + } + uartHandler->HardWare_Check_Counter = 0;//perform the check of connection + } +} + + + diff --git a/Bingoo/base/bsp_cpu_flash.c b/Bingoo/base/bsp_cpu_flash.c new file mode 100644 index 0000000..7d1959c --- /dev/null +++ b/Bingoo/base/bsp_cpu_flash.c @@ -0,0 +1,499 @@ +/* +********************************************************************************************************* +* +* 模块名称 : cpu内部falsh操作模块(for STM32H743 H750) +* 文件名称 : bsp_cpu_flash.c +* 版 本 : V1.1 +* 说 明 : 提供读写CPU内部Flash的函数 +* 修改记录 : +* 版本号 日期 作者 说明 +* V1.0 2019-09-20 armfly 正式发布 +* V1.1 2019-10-03 armfly 写flash函数,修正长度不是32字节整数倍的bug,末尾补0写入。 +* 解决HAL库函数的 HAL_FLASH_Program()的bug, +* 问题现象是大批量连续编程失败(报编程指令顺序错, PGSERR1、 PGSERR2) +* Copyright (C), 2019-2030, 安富莱电子 www.armfly.com +* +********************************************************************************************************* +*/ + +#include "BSP/bsp_cpu_flash.h" +#include +/* +********************************************************************************************************* +* 函数 +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* 宏定义 +********************************************************************************************************* +*/ +//0x08020000 - 0x08000000 = 128k;//bootload 128k // every sector 448k + +/* +********************************************************************************************************* +* 变量 +********************************************************************************************************* +*/ +__IO uint32_t uwCRCValue; +__IO uint32_t uwExpectedCRCValue; +__IO uint32_t uwAppSize; + +uint8_t buf[1024]; +uint32_t RecCount = 0; +uint32_t RecCount0 = 0; +uint32_t RecSize = 0; +uint8_t RecCplt = 0; +uint32_t filesize = 0; + +uint32_t Bus_Error=0; +uint32_t update_index = 0; +uint32_t update_index_true = 0; +uint32_t update_sum = 0; +uint32_t update_sum_true = 0; + + +/* +********************************************************************************************************* +* 函 数 名: bsp_GetSector +* 功能说明: 根据地址计算扇区首地址 +* 形 参: 无 +* 返 回 值: 扇区号(0-7) +********************************************************************************************************* +*/ +uint32_t bsp_GetSector(uint32_t Address) +{ + uint32_t sector = 0; + + if (((Address < ADDR_FLASH_SECTOR_1_BANK1) && (Address >= ADDR_FLASH_SECTOR_0_BANK1)) || \ + ((Address < ADDR_FLASH_SECTOR_1_BANK2) && (Address >= ADDR_FLASH_SECTOR_0_BANK2))) + { + sector = FLASH_SECTOR_0; + } + else if (((Address < ADDR_FLASH_SECTOR_2_BANK1) && (Address >= ADDR_FLASH_SECTOR_1_BANK1)) || \ + ((Address < ADDR_FLASH_SECTOR_2_BANK2) && (Address >= ADDR_FLASH_SECTOR_1_BANK2))) + { + sector = FLASH_SECTOR_1; + } + else if (((Address < ADDR_FLASH_SECTOR_3_BANK1) && (Address >= ADDR_FLASH_SECTOR_2_BANK1)) || \ + ((Address < ADDR_FLASH_SECTOR_3_BANK2) && (Address >= ADDR_FLASH_SECTOR_2_BANK2))) + { + sector = FLASH_SECTOR_2; + } + else if (((Address < ADDR_FLASH_SECTOR_4_BANK1) && (Address >= ADDR_FLASH_SECTOR_3_BANK1)) || \ + ((Address < ADDR_FLASH_SECTOR_4_BANK2) && (Address >= ADDR_FLASH_SECTOR_3_BANK2))) + { + sector = FLASH_SECTOR_3; + } + else if (((Address < ADDR_FLASH_SECTOR_5_BANK1) && (Address >= ADDR_FLASH_SECTOR_4_BANK1)) || \ + ((Address < ADDR_FLASH_SECTOR_5_BANK2) && (Address >= ADDR_FLASH_SECTOR_4_BANK2))) + { + sector = FLASH_SECTOR_4; + } + else if (((Address < ADDR_FLASH_SECTOR_6_BANK1) && (Address >= ADDR_FLASH_SECTOR_5_BANK1)) || \ + ((Address < ADDR_FLASH_SECTOR_6_BANK2) && (Address >= ADDR_FLASH_SECTOR_5_BANK2))) + { + sector = FLASH_SECTOR_5; + } + else if (((Address < ADDR_FLASH_SECTOR_7_BANK1) && (Address >= ADDR_FLASH_SECTOR_6_BANK1)) || \ + ((Address < ADDR_FLASH_SECTOR_7_BANK2) && (Address >= ADDR_FLASH_SECTOR_6_BANK2))) + { + sector = FLASH_SECTOR_6; + } + else if (((Address < ADDR_FLASH_SECTOR_0_BANK2) && (Address >= ADDR_FLASH_SECTOR_7_BANK1)) || \ + ((Address < CPU_FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_7_BANK2))) + { + sector = FLASH_SECTOR_7; + } + else + { + sector = FLASH_SECTOR_7; + } + + return sector; +} + +/* +********************************************************************************************************* +* 函 数 名: bsp_ReadCpuFlash +* 功能说明: 读取CPU Flash的内容 +* 形 参: _ucpDst : 目标缓冲区 +* _ulFlashAddr : 起始地址 +* _ulSize : 数据大小(单位是字节) +* 返 回 值: 0=成功,1=失败 +********************************************************************************************************* +*/ +uint8_t bsp_ReadCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpDst, uint32_t _ulSize) +{ + uint32_t i; + + if (_ulFlashAddr + _ulSize > CPU_FLASH_BASE_ADDR + CPU_FLASH_SIZE) + { + return 1; + } + + /* 长度为0时不继续操作,否则起始地址为奇地址会出错 */ + if (_ulSize == 0) + { + return 1; + } + + for (i = 0; i < _ulSize; i++) + { + *_ucpDst++ = *(uint8_t *)_ulFlashAddr++; + } + + return 0; +} + +/* +********************************************************************************************************* +* 函 数 名: bsp_CmpCpuFlash +* 功能说明: 比较Flash指定地址的数据. +* 形 参: _ulFlashAddr : Flash地址 +* _ucpBuf : 数据缓冲区 +* _ulSize : 数据大小(单位是字节) +* 返 回 值: +* FLASH_IS_EQU 0 Flash内容和待写入的数据相等,不需要擦除和写操作 +* FLASH_REQ_WRITE 1 Flash不需要擦除,直接写 +* FLASH_REQ_ERASE 2 Flash需要先擦除,再写 +* FLASH_PARAM_ERR 3 函数参数错误 +********************************************************************************************************* +*/ +uint8_t bsp_CmpCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpBuf, uint32_t _ulSize) +{ + uint32_t i; + uint8_t ucIsEqu; /* 相等标志 */ + uint8_t ucByte; + + /* 如果偏移地址超过芯片容量,则不改写输出缓冲区 */ + if (_ulFlashAddr + _ulSize > CPU_FLASH_BASE_ADDR + CPU_FLASH_SIZE) + { + return FLASH_PARAM_ERR; /* 函数参数错误 */ + } + + /* 长度为0时返回正确 */ + if (_ulSize == 0) + { + return FLASH_IS_EQU; /* Flash内容和待写入的数据相等 */ + } + + ucIsEqu = 1; /* 先假设所有字节和待写入的数据相等,如果遇到任何一个不相等,则设置为 0 */ + for (i = 0; i < _ulSize; i++) + { + ucByte = *(uint8_t *)_ulFlashAddr; + + if (ucByte != *_ucpBuf) + { + if (ucByte != 0xFF) + { + return FLASH_REQ_ERASE; /* 需要擦除后再写 */ + } + else + { + ucIsEqu = 0; /* 不相等,需要写 */ + } + } + + _ulFlashAddr++; + _ucpBuf++; + } + + if (ucIsEqu == 1) + { + return FLASH_IS_EQU; /* Flash内容和待写入的数据相等,不需要擦除和写操作 */ + } + else + { + return FLASH_REQ_WRITE; /* Flash不需要擦除,直接写 */ + } +} + +/* +********************************************************************************************************* +* 函 数 名: bsp_EraseCpuFlash +* 功能说明: 擦除CPU FLASH一个扇区 (128KB) +* 形 参: _ulFlashAddr : Flash地址 +* 返 回 值: 0 成功, 1 失败 +* HAL_OK = 0x00, +* HAL_ERROR = 0x01, +* HAL_BUSY = 0x02, +* HAL_TIMEOUT = 0x03 +* +********************************************************************************************************* +*/ +uint8_t bsp_EraseCpuFlash(uint32_t _ulFlashAddr) +{ + uint32_t FirstSector = 0, NbOfSectors = 0; + FLASH_EraseInitTypeDef EraseInitStruct; + uint32_t SECTORError = 0; + uint8_t re; + + /* 解锁 */ + HAL_FLASH_Unlock(); + + /* 获取此地址所在的扇区 */ + FirstSector = bsp_GetSector(_ulFlashAddr); + + /* 固定1个扇区 */ + NbOfSectors = 1; + + /* 擦除扇区配置 */ + EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; + EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; + + if (_ulFlashAddr >= ADDR_FLASH_SECTOR_0_BANK2) + { + EraseInitStruct.Banks = FLASH_BANK_2; + } + else + { + EraseInitStruct.Banks = FLASH_BANK_1; + } + + EraseInitStruct.Sector = FirstSector; + EraseInitStruct.NbSectors = NbOfSectors; + + /* 扇区擦除 */ + re = HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError); + + /* 擦除完毕后,上锁 */ + HAL_FLASH_Lock(); + + return re; +} + +/* +********************************************************************************************************* +* 函 数 名: bsp_WriteCpuFlash +* 功能说明: 写数据到CPU 内部Flash。 必须按32字节整数倍写。不支持跨扇区。扇区大小128KB. \ +* 写之前需要擦除扇区. 长度不是32字节整数倍时,最后几个字节末尾补0写入. +* 形 参: _ulFlashAddr : Flash地址 +* _ucpSrc : 数据缓冲区 +* _ulSize : 数据大小(单位是字节, 必须是32字节整数倍) +* 返 回 值: 0-成功,1-数据长度或地址溢出,2-写Flash出错(估计Flash寿命到) +********************************************************************************************************* +*/ +uint8_t bsp_WriteCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpSrc, uint32_t _ulSize) +{ + uint32_t i; + uint8_t ucRet; + + /* 如果偏移地址超过芯片容量,则不改写输出缓冲区 */ + if (_ulFlashAddr + _ulSize > CPU_FLASH_BASE_ADDR + CPU_FLASH_SIZE) + { + return 1; + } + + /* 长度为0时不继续操作 */ + if (_ulSize == 0) + { + return 0; + } + + ucRet = bsp_CmpCpuFlash(_ulFlashAddr, _ucpSrc, _ulSize); + + if (ucRet == FLASH_IS_EQU) + { + return 0; + } + + __set_PRIMASK(1); /* 关中断 */ + + /* FLASH 解锁 */ + HAL_FLASH_Unlock(); + + for (i = 0; i < _ulSize / 32; i++) + { + uint64_t FlashWord[4]; + + memcpy((char *)FlashWord, _ucpSrc, 32); + _ucpSrc += 32; + + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, _ulFlashAddr, (uint64_t)((uint32_t)FlashWord)) == HAL_OK) + { + _ulFlashAddr = _ulFlashAddr + 32; /* 递增,操作下一个256bit */ + } + else + { + goto err; + } + } + + /* 长度不是32字节整数倍 */ + if (_ulSize % 32) + { + uint64_t FlashWord[4]; + + FlashWord[0] = 0; + FlashWord[1] = 0; + FlashWord[2] = 0; + FlashWord[3] = 0; + memcpy((char *)FlashWord, _ucpSrc, _ulSize % 32); + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, _ulFlashAddr, (uint64_t)((uint32_t)FlashWord)) == HAL_OK) + { + ; // _ulFlashAddr = _ulFlashAddr + 32; + } + else + { + goto err; + } + } + + /* Flash 加锁,禁止写Flash控制寄存器 */ + HAL_FLASH_Lock(); + + __set_PRIMASK(0); /* 开中断 */ + + return 0; + +err: + /* Flash 加锁,禁止写Flash控制寄存器 */ + HAL_FLASH_Lock(); + + __set_PRIMASK(0); /* 开中断 */ + + return 1; +} +/* +********************************************************************************************************* +* 函 数 名: JumpToApp +* 功能说明: 跳转到应用JumpToApp +* 形 参: 无 +* 返 回 值: 无 +********************************************************************************************************* +*/ +void JumpToApp(void) +{ + uint32_t i=0; + void (*AppJump)(void); /* 声明一个函数指针 */ + + /* 关闭全局中断 */ + DISABLE_INT(); + + /* 设置所有时钟到默认状态,使用HSI时钟 */ + + __HAL_RCC_GPIOH_CLK_DISABLE(); + __HAL_RCC_GPIOB_CLK_DISABLE(); + HAL_RCC_DeInit(); + + /* 关闭滴答定时器,复位到默认值 */ + SysTick->CTRL = 0; + SysTick->LOAD = 0; + SysTick->VAL = 0; + + /* 关闭所有中断,清除所有中断挂起标志 */ + for (i = 0; i < 8; i++) + { + NVIC->ICER[i]=0xFFFFFFFF; + NVIC->ICPR[i]=0xFFFFFFFF; + } + + /* 使能全局中断 */ + ENABLE_INT(); + + /* 跳转到应用程序,首地址是MSP,地址+4是复位中断服务程序地址 */ + AppJump = (void (*)(void)) (*((uint32_t *) (App_Run_Addr + 4))); + + /* 设置主堆栈指针 */ + __set_MSP(*(uint32_t *)App_Run_Addr); + + /* 在RTOS工程,这条语句很重要,设置为特权级模式,使用MSP指针 */ + __set_CONTROL(0); + + /* 跳转到系统BootLoader */ + AppJump(); + + /* 跳转成功的话,不会执行到这里,用户可以在这里添加代码 */ + while (1) + { + + } +} + +/* +********************************************************************************************************* +* 函 数 名: JumpToApp +* 功能说明: 跳转到应用JumpToApp +* 形 参: 无 +* 返 回 值: 无 +********************************************************************************************************* +*/ +void Copy_Download_Flash_to_Start() +{ + + uint32_t startIndex=0; + + for(startIndex = 0; startIndex < 3; startIndex++) + { + bsp_EraseCpuFlash((uint32_t)(App_Run_Addr + startIndex*128*1024));//Erase this function + } + + + uint8_t readData[32]; + uint32_t total=3*128*1024/sizeof(readData); + uint8_t retult=0; + for(startIndex=0;startIndex= 1) +// { +// +// i_stream = pb_istream_from_buffer(buffer, length); +// +// pb_decode(&i_stream, Cmd_fields, &decoded_Cmd); +// +// memcpy(&decoded_Cmd.Buff_Data, +// &buffer[length - decoded_Cmd.Buff_Data_Length], +// decoded_Cmd.Buff_Data_Length); +// +// switch (decoded_Cmd.CommadNum) +// { +// +// case 17: // 上位机获取控制权 +// { +// +// switch (decoded_Cmd.Parameter0) +// { +// case 0: +// { +// +// //read CV +// CV = GF_BSP_EEPROM_Get_CV(); //重新配置CV +// is_upper_computer_take_over_control = 0; +// +// WrapInCmdAndSendMessage(send_Cmd, 10, success, +// "return contorl to Remote Controller success", +// sendWay, send_Handler); +// fsm_state_set(¤t_robot_move_state, +// &robot_halt_state); +// //设置电机供电为 On +// //fsm_state_set(¤t_motor_power_state, &motor_power_off_state); +// break; +// } +// case 1: +// { +// +// is_upper_computer_take_over_control = 1; +// WrapInCmdAndSendMessage(send_Cmd, 17, success, +// "Take control success", sendWay, send_Handler); +// fsm_state_set(¤t_motor_power_state, +// &motor_power_on_state); +// fsm_state_set(¤t_robot_move_state, +// &robot_halt_state); +// GV.Robot_Move_Speed = 1000; +// CV.LeftTurnSpeed = 1; +// CV.RightTurnSpeed = 1; +// break; +// } +// +// default: +// break; +// +// } +// +// break; +// } +// case 16: // 上位机手动控制机器人运动 +// { +// +// switch (decoded_Cmd.Parameter0) +// { +// case 0: +// { +// +// WrapInCmdAndSendMessage(send_Cmd, 16, success, +// "manual control halt success", sendWay, +// send_Handler); +// fsm_state_set(¤t_robot_move_state, +// &robot_halt_state); +// break; +// } +// case 1: +// { +// WrapInCmdAndSendMessage(send_Cmd, 16, success, +// "manual control forward success", sendWay, +// send_Handler); +// fsm_state_set(¤t_robot_move_state, +// &robot_forwards_state); +// break; +// } +// case 2: +// { +// WrapInCmdAndSendMessage(send_Cmd, 16, success, +// "manual control backward success", sendWay, +// send_Handler); +// fsm_state_set(¤t_robot_move_state, +// &robot_backwards_state); +// break; +// } +// case 3: +// { +// WrapInCmdAndSendMessage(send_Cmd, 16, success, +// "manual control turn left success", sendWay, +// send_Handler); +// fsm_state_set(¤t_robot_move_state, +// &robot_turn_left_state); +// break; +// } +// case 4: +// { +// WrapInCmdAndSendMessage(send_Cmd, 16, success, +// "manual control turn right success", sendWay, +// send_Handler); +// fsm_state_set(¤t_robot_move_state, +// &robot_turn_right_state); +// break; +// } +// default: +// break; +// +// } +// +// break; +// } +// +// case 15: // 返回错误信息 +// { +// +// pb_ostream_t Error_o_stream = +// { 0 }; +// char buf[1024]; +// Error_o_stream = pb_ostream_from_buffer(buf, sizeof(buf)); +// pb_encode(&Error_o_stream, ErrorData_fields, +// &GV.SystemErrorData); +// +// //将数据拷贝到Command中 +// send_Cmd.CommadNum = 16; +// send_Cmd.Buff_Data_Length = Error_o_stream.bytes_written; +// +// WrapInCmdAndSend(send_Cmd, buf, sendWay, send_Handler); +// +// break; +// } +// +// case 14: //这里是初始化Flash 好重新写入 +// { +// NeedToFeedBackToComputer = 1; +// +// WrapInCmdAndSendMessage(send_Cmd, 14, success, +// "disable periodical call of serialports and can", +// sendWay, send_Handler); +// +// Error_Detect_Enable = 0; //disable ErrorDetect Function; +// +// DLT_LOG_ENABLE_LEVEL = 0; //7 send all information //0 send nothing +// +// //将所有串口的周期性调用暂停 +// RS_485_1_UART_Handler.dispacherController->Dispacher_Enable = 0; +// RS_485_2_UART_Handler.dispacherController->Dispacher_Enable = 0; +// RS_485_3_UART_Handler.dispacherController->Dispacher_Enable = 0; +// RS_485_4_UART_Handler.dispacherController->Dispacher_Enable = 0; +// E28_SBUS_UART_Handler.dispacherController->Dispacher_Enable = 0; +// LPUART1_UART_Handler.dispacherController->Dispacher_Enable = 0; +// InterCall_DEBUG_UART_Handler.dispacherController->Dispacher_Enable = +// 0; +// LTE_7S0_Serial_UART_Handler.dispacherController->Dispacher_Enable = +// 0; +// RS_485_4_UART_Handler.dispacherController->Dispacher_Enable = 0; +// is_udp_GV_update_loop_enalbed = 0; +// +// //将CAN总线的周期性调用停掉 +// //因为电机有可能处于运动状态,所有CAN线不能停,得发送下去 +// //FD_CAN_1_Handler.dispacherController->Dispacher_Enable = 0; +// //FD_CAN_2_Handler.dispacherController->Dispacher_Enable = 0; +// fsm_state_set(¤t_robot_move_state, &robot_halt_state); +// +// break; +// } +// case 13: // 使能 GV 周期性性发送数据 +// { +// if (decoded_Cmd.Parameter0 == 0) //关闭上传 +// { +// NeedToFeedBackToComputer = 1; +// LTE_7S0_Serial_UART_Handler.dispacherController->Dispacher_Enable = +// 0; +// WrapInCmdAndSendMessage(send_Cmd, 14, success, +// "disable send GV", sendWay, send_Handler); +// +// is_udp_GV_update_loop_enalbed = 0; +// } +// +// if (decoded_Cmd.Parameter0 == 1) //打开上传 +// { +// NeedToFeedBackToComputer = 0; +// LTE_7S0_Serial_UART_Handler.dispacherController->Dispacher_Enable = +// 1; +// WrapInCmdAndSendMessage(send_Cmd, 14, success, +// "enable send GV", sendWay, send_Handler); +// +// is_udp_GV_update_loop_enalbed = 1; +// } +// +// break; +// } +// case 12: //重启系统,进入bootloader +// { +// +// WrapInCmdAndSendMessage(send_Cmd, 12, success, "STM32 reboot", +// sendWay, send_Handler); +// NVIC_SystemReset(); +// +// break; +// } +// case 11: //配置无线网络模块,此处为透传指令 +// { +// Send_WH_LTE_7S0_Data(decoded_Cmd.Buff_Data, +// decoded_Cmd.Parameter0); +// break; +// } +// case 10: //擦除flash +// { +// WrapInCmdAndSendMessage(send_Cmd, 10, success, +// "start erasing flash ", sendWay, send_Handler); +// QSPI_W25Qx_EraseDownLoadFlash(); +// downloadCount = 0; +// WrapInCmdAndSendMessage(send_Cmd, 10, success, +// "erase flash success", sendWay, send_Handler); +// break; +// } +// case 9: //上位机下发保存软件代码指令 +// { +// memcpy(ReceivedData, +// &buffer[length - decoded_Cmd.Buff_Data_Length], +// decoded_Cmd.Buff_Data_Length); +// +// calbriation = MB_CRC16(&ReceivedData, +// decoded_Cmd.Buff_Data_Length); +// +// if (calbriation == decoded_Cmd.Parameter4) //Parameter4是校验 +// { +// +// if (downloadCount == decoded_Cmd.Parameter3) +// { +// QSPI_W25Qx_Write_Buffer(&decoded_Cmd.Buff_Data, +// CODE_DOWNLOAD_FLASH_BEGIN_ADDRESS +// + decoded_Cmd.Parameter3, +// decoded_Cmd.Buff_Data_Length); +// downloadCount += decoded_Cmd.Buff_Data_Length; +// send_Cmd.Parameter3 = length; +// WrapInCmdAndSendMessage(send_Cmd, 9, success, +// "download success", sendWay, send_Handler); +// +// } +// else +// { +// decoded_Cmd.Parameter2 = downloadCount; //返回download count; +// send_Cmd.Parameter3 = length; +// WrapInCmdAndSendMessage(send_Cmd, 9, fail, +// "downloadCount!=Parameter3", sendWay, +// send_Handler); +// } +// +// if (decoded_Cmd.Parameter1 == 1) +// { +// WrapInCmdAndSendMessage(send_Cmd, 9, success, +// "download new software sucess", sendWay, +// send_Handler); +// IAP_struct_define iap = GF_BSP_EEPROM_Get_IAP();//Get the version of the code +// iap.UpgradeSucceeded = 1; +// iap.Total_Bytes = decoded_Cmd.Parameter2; +// StartDownLoadFlag = 0; +// downloadCount = 0; +// GF_BSP_EEPROM_Set_IAP(iap); +// +// } +// } +// else +// { +// +// decoded_Cmd.Parameter2 = downloadCount; //返回download count; +// send_Cmd.Parameter3 = length; +// WrapInCmdAndSendMessage(send_Cmd, 9, fail, +// "MB CRC failed and the length ", sendWay, +// send_Handler); +// +// } +// +// break; +// } +// +//// 定义 7 上位机获取拟合点 +//// 定义 8 上位机获取位置点 */ +// case 8: +// { +//// send_data_to_upper_computer(*Desulfurizer_Angle, +//// *Desulfurizer_Wire_Length, *Desulfurizer_Thickness, 0, +//// 0, desulfurizer_message_UART_Handler); +// break; +// } +// case 7: +// { +//// send_data_to_upper_computer(*Desulfurizer_Angle, +//// *Desulfurizer_Wire_Length, *Desulfurizer_Thickness, 1, +//// 0, desulfurizer_message_UART_Handler); +// break; +// } +// //定义 6 上位机设定编码器角度值为0 +// case 6: +// { +// //reset_current_value_0(); +// break; +// } +// //定义 4 上位机设定Trace等级值,无返回 +// case 4: +// { +// +// break; +// } +// //定义 3 上位机设定CV值 +// case 3: +// { +// CV_struct_define decoded_CV = CV_struct_define_init_default; +// pb_istream_t i_cv_stream = +// { 0 }; +// +// i_cv_stream = pb_istream_from_buffer(decoded_Cmd.Buff_Data, +// decoded_Cmd.Buff_Data_Length); +// pb_decode(&i_cv_stream, CV_struct_define_fields, &decoded_CV); +// //将CV写入EEPROM +// GF_BSP_EEPROM_Set_CV(decoded_CV); +// CV = decoded_CV; +// send_Cmd.Parameter3 = length; +// WrapInCmdAndSendMessage(send_Cmd, 3, success, +// "Set CV succeeded", sendWay, send_Handler); +// CV_GV_Init(); +// break; +// } +// //定义 1 上位机获取默认CV值, 下位机返回CV的值, +// //定义 2 下位机返回CV值 +// case 1: +// { +// CV = GF_BSP_EEPROM_Get_CV(); +// pb_ostream_t CV_o_stream = +// { 0 }; +// char buf[1024]; +// CV_o_stream = pb_ostream_from_buffer(buf, sizeof(buf)); +// pb_encode(&CV_o_stream, CV_struct_define_fields, &CV); +// +// //将数据拷贝到Command中 +// send_Cmd.CommadNum = 2; +// send_Cmd.Buff_Data_Length = CV_o_stream.bytes_written; +// +// WrapInCmdAndSend(send_Cmd, buf, sendWay, send_Handler); +// +// break; +// } +// default: +// WrapInCmdAndSendMessage(send_Cmd, -1, fail, +// "Not the right command", sendWay, send_Handler); +// break; +// +// } +// +// } +// else +// { +// +// } + +} +void WrapInCmdAndSend(ReCmd send_Cmd, uint8_t *buf, int8_t sendWay, + struct UARTHandler *send_Handler) +{ + + memcpy(send_Cmd.Buff_Data, buf, send_Cmd.Buff_Data_Length); + pb_ostream_t ReCmd_out_stream = + { 0 }; + + if (sendWay == 1) //MQTT + { + ReCmd_out_stream = pb_ostream_from_buffer(&send_Handler->Tx_Buf[4], + sizeof(send_Handler->Tx_Buf) - 4); + pb_encode(&ReCmd_out_stream, ReCmd_fields, &send_Cmd); //encode to buffer + + send_Handler->Tx_Buf[0] = '3'; + send_Handler->Tx_Buf[1] = ','; + send_Handler->Tx_Buf[2] = 0xfe; + send_Handler->Tx_Buf[3] = 0xfe; + send_Handler->TxCount = ReCmd_out_stream.bytes_written + 4; + send_Handler->UART_Tx(send_Handler); + } + else if (sendWay == 2) //UDP 发送 + { + uint8_t Tx_Buf[2048]; + ReCmd_out_stream = pb_ostream_from_buffer(&Tx_Buf[2], + sizeof(Tx_Buf) - 2); + pb_encode(&ReCmd_out_stream, ReCmd_fields, &send_Cmd); //encode to buffer + Tx_Buf[0] = 0xfe; + Tx_Buf[1] = 0xfe; + udp_cmd_send_back(Tx_Buf, ReCmd_out_stream.bytes_written + 2); + + } + else //485发送 + { + ReCmd_out_stream = pb_ostream_from_buffer(&send_Handler->Tx_Buf[2], + sizeof(send_Handler->Tx_Buf) - 2); + pb_encode(&ReCmd_out_stream, ReCmd_fields, &send_Cmd); //encode to buffer + send_Handler->Tx_Buf[0] = 0xfe; + send_Handler->Tx_Buf[1] = 0xfe; + //send_Handler->AddSendList(send_Handler,send_Handler->Tx_Buf,send_Handler->TxCount,NULL); + send_Handler->TxCount = ReCmd_out_stream.bytes_written + 2; + //send_Handler->TxCount = 200; + send_Handler->UART_Tx(send_Handler); + } + +} + +//send_Cmd.CommadNum=0xff;//代表返回信息 +//send_Cmd.Parameter0 代表执行的指令,发过来的命令号; +//send_Cmd.Parameter1 1 代表成功,0 代表失败; +//send_Cmd.databuf 存的是相关信息,可以通过ACII转成string; + +void WrapInCmdAndSendMessage(ReCmd send_Cmd, int8_t functionNum, + int8_t isSuccess, uint8_t *buf, int8_t sendWay, + struct UARTHandler *send_Handler) +{ + + send_Cmd.CommadNum = 0xff; //代表返回信息 + send_Cmd.Parameter0 = functionNum; //代表返回信息 + send_Cmd.Parameter1 = isSuccess; //1 代表成功,0 代表失败; + send_Cmd.Buff_Data_Length = strlen(buf); + WrapInCmdAndSend(send_Cmd, buf, sendWay, send_Handler); +} + +void send_received_data_to_upper_computer(uint8_t *buffer, uint16_t length) +{ + send_Cmd.CommadNum = 12; //定义12为设定Mqtt透传向上返回的数据 + send_Cmd.Buff_Data_Length = length; + + WrapInCmdAndSend(send_Cmd, buffer, 0, desulfurizer_message_UART_Handler); + +} diff --git a/Bingoo/base/bsp_ground_management.pb.c b/Bingoo/base/bsp_ground_management.pb.c new file mode 100644 index 0000000..6851011 --- /dev/null +++ b/Bingoo/base/bsp_ground_management.pb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "bsp_ground_management.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(ground_management_struct, ground_management_struct, AUTO) + + + diff --git a/Bingoo/base/bsp_qspi_w25q128.c b/Bingoo/base/bsp_qspi_w25q128.c new file mode 100644 index 0000000..35131e5 --- /dev/null +++ b/Bingoo/base/bsp_qspi_w25q128.c @@ -0,0 +1,488 @@ +/* + * bsp_quadspi_W25Q128.c + * + * Created on: Apr 25, 2021 + * Author: Administrator + * + * + * + * + * + */ +#include +#include "quadspi.h" + +/* 仅限本文件使用的函数 */ +static void QSPI_W25Qx_Write_Enable(QSPI_HandleTypeDef *hqspi); +static uint8_t QSPI_W25Qx_AutoPollingMemRead(uint32_t Timeout); +static void QSPI_W25Qx_Enter(QSPI_HandleTypeDef *hqspi); +static void QSPI_W25Qx_Exit(QSPI_HandleTypeDef *hqspi); + +/** + * 函数功能: 读取Flash状态并等待操作结束 + * 输入参数: Timeout:等待时间 + * + * 返回值: Flash的状态 + * 说明: + * + * + */ + + + +static uint8_t QSPI_W25Qx_AutoPollingMemRead(uint32_t Timeout) +{ + QSPI_CommandTypeDef s_command={0}; + QSPI_AutoPollingTypeDef s_config={0}; + + /* 基本配置 */ + s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; //1线方式发送指令 + s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址 + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节 + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式 + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟 + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令 + + /* 配置自动轮询模式 */ + s_command.Instruction = READ_STATUS_REG1_CMD; //读取状态寄存器 + s_command.AddressMode = QSPI_ADDRESS_NONE; //没有地址 + s_command.DataMode = QSPI_DATA_1_LINE; //1线数据 + s_command.DummyCycles = 0; //无空周期 + + /* 配置自动轮询寄存器(不断查询状态寄存器bit0,等待其为0) */ + s_config.Match = 0x00; //等待其为0 + s_config.Mask = W25Q128FV_FSR_BUSY; //状态寄存器bit0 + s_config.MatchMode = QSPI_MATCH_MODE_AND; //逻辑与 + s_config.StatusBytesSize = 1; + s_config.Interval = 0x10; + s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + + /* 自动轮询模式等待编程结束 */ + if(HAL_QSPI_AutoPolling(&hqspi,&s_command,&s_config,Timeout) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + + return FLASH_OK; + +} + +/** + * 函数功能: 读取外部FLASH的ID + * 输入参数: 无 + * + * 返回值: uint32_t + * 说明: + * 1、使用SPI模式的指令 + * + */ +uint32_t QSPI_W25Qx_ReadID(void) +{ + uint32_t uiID; + + QSPI_CommandTypeDef s_command = {0}; + uint8_t buf[3]; + + /* 基本配置 */ + s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; //1线方式发送指令 + s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址 + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节 + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式 + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟 + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令 + + /* 读取JEDEC ID */ + s_command.Instruction = READ_JEDEC_ID_CMD; //读取ID命令: 0x9F + s_command.AddressMode = QSPI_ADDRESS_NONE; //没有地址 + s_command.DataMode = QSPI_DATA_1_LINE; //1线数据 + s_command.DummyCycles = 0; //无空周期 + s_command.NbData = 3; //读取三个数据 + + /* 发送指令 */ + if(HAL_QSPI_Command(&hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + + /* 启动接收 */ + if(HAL_QSPI_Receive(&hqspi,buf,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + + uiID = (buf[0] << 16) | (buf[1] << 8) | buf[2]; + + return uiID; +} + +/** + * 函数功能: 外部FLASH写使能 + * 输入参数: hqspi QSPI_HandleTypeDef句柄 + * + * 返回值: 无 + * 说明: + * 1、使用SPI模式的指令 + * + */ +static void QSPI_W25Qx_Write_Enable(QSPI_HandleTypeDef *hqspi) +{ + QSPI_CommandTypeDef s_command = {0}; + QSPI_AutoPollingTypeDef s_config={0}; + + /* 基本配置 */ + s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; //1线方式发送指令 + //s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址 + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节 + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式 + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟 + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令 + + /* 写入使能配置 */ + s_command.Instruction = WRITE_ENABLE_CMD; //写使能命令 + s_command.AddressMode = QSPI_ADDRESS_NONE; //没有地址 + s_command.DataMode = QSPI_DATA_NONE; //没有数据 + s_command.DummyCycles = 0; //无空周期 + s_command.NbData = 0; //空数据 + + /* 发送指令 */ + if(HAL_QSPI_Command(hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + + /* 配置自动轮询模式等待操作完成 */ + s_config.Match = W25Q128FV_FSR_WREN; + s_config.Mask = W25Q128FV_FSR_WREN; + s_config.MatchMode = QSPI_MATCH_MODE_AND; + s_config.StatusBytesSize = 1; + s_config.Interval = 0x10; + s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + + s_command.Instruction = READ_STATUS_REG1_CMD; + s_command.DataMode = QSPI_DATA_1_LINE; + s_command.NbData = 1; + + if(HAL_QSPI_AutoPolling(hqspi,&s_command,&s_config,HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + +} + +/** + * 函数功能: 擦除外部FLASH的扇区(大小:4KB) + * 输入参数: _uiSectorAddr: 扇区地址,以4KB为单位的地址,比如0,4096,8192等 + * + * 返回值: 无 + * 说明: + * 1、 + * + */ +void QSPI_W25Qx_EraseSector(uint32_t _SectorAddr) +{ + QSPI_CommandTypeDef s_command = {0}; + + /* 写使能 */ + QSPI_W25Qx_Write_Enable(&hqspi); + + /* 基本配置 */ + s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; //1线方式发送指令 + s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址 + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节 + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式 + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟 + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令 + + /* 擦除扇区配置 */ + s_command.Instruction = SECTOR_ERASE_CMD; //扇区擦除指令 + s_command.AddressMode = QSPI_ADDRESS_1_LINE; //1线地址方式 + s_command.DataMode = QSPI_DATA_NONE; //没有数据 + s_command.Address = _SectorAddr; //扇区的首地址,保证是4KB整数倍 + s_command.DummyCycles = 0; //无空周期 + + /* 发送指令 */ + if(HAL_QSPI_Command(&hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + + /* 自动轮询模式等待编程结束 */ + if(QSPI_W25Qx_AutoPollingMemRead(W25Q128FV_SUBSECTOR_ERASE_MAX_TIME) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + +} + +/** + * 函数功能: 页编程,通过QSPI将数据写入外部FALSH + * 输入参数: _pBuf: 需要存入数据的指针 + * _write_Addr: 目标区域首地址,即页首地址,比如0,256,512等。 + * _write_Size: 数据个数,不能超过页的大小,可以填入(1 ~ 256) + * 返回值: 无 + * 说明: + * 1、华邦的W25Q128FV仅仅支持SPI模式写入 + */ +uint8_t QSPI_W25Qx_Write_Buffer(uint8_t *_pBuf,uint32_t _write_Addr,uint16_t _write_Size) +{ + QSPI_CommandTypeDef s_command = {0}; + + /* 防止写入的大小超过256字节 */ + if(_write_Size > W25Q128FV_PAGE_SIZE) + { + /* 进入断言,提示错误 */ + user_Assert(__FILE__,__LINE__); + } + + QSPI_W25Qx_Write_Enable(&hqspi); //写使能 + + /* 基本配置 */ + s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; //1线方式发送指令 + s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址 + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节 + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式 + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟 + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令 + + /*写入序列配置 */ + s_command.Instruction = QUAD_INPUT_PAGE_PROG_CMD; //24位四线快速写入指令 + s_command.AddressMode = QSPI_ADDRESS_1_LINE; //1线地址方式 + s_command.DataMode = QSPI_DATA_4_LINES; //4线数据方式 + s_command.Address = _write_Addr; //写入数据的地址 + s_command.NbData = _write_Size; //写入数据的大小 + s_command.DummyCycles = 0; //无空周期 + + /* 发送指令 */ + if(HAL_QSPI_Command(&hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + + /* 启动传输 */ + if(HAL_QSPI_Transmit(&hqspi,_pBuf,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + + /* 自动轮询模式等待编程结束 */ + if(QSPI_W25Qx_AutoPollingMemRead(W25Q128FV_SUBSECTOR_ERASE_MAX_TIME) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + + return 1; +} + +/** + * 函数功能: 外部FLASH芯片进入QSPI模式 + * 输入参数: *hqspi: qspi句柄 + * + * 返回值: 无 + * 说明: + * + */ +static void QSPI_W25Qx_Enter(QSPI_HandleTypeDef *hqspi) +{ + QSPI_CommandTypeDef s_command = {0}; + /* 配置FLASH进入QPSI模式 */ + /* 基本配置 */ + s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; //1线方式发送指令 + s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址 + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节 + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式 + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟 + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令 + + /* 写入序列配置 */ + s_command.Instruction = ENTER_QPI_MODE_CMD; //进入QSPI模式 + s_command.AddressMode = QSPI_ADDRESS_NONE; //无地址方式 + s_command.DataMode = QSPI_DATA_NONE; //无数据方式 + s_command.DummyCycles = 0; //0空闲状态周期 + + /* 发送指令 */ + if(HAL_QSPI_Command(hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + +} + +/** + * 函数功能: 外部FLASH芯片退出QSPI模式 + * 输入参数: *hqspi: qspi句柄 + * + * 返回值: 无 + * 说明: + * + */ +static void QSPI_W25Qx_Exit(QSPI_HandleTypeDef *hqspi) +{ + QSPI_CommandTypeDef s_command = {0}; + + /* 基本配置 */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; //4线方式发送指令 + s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址 + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节 + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式 + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟 + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令 + + /* 写入序列配置 */ + s_command.Instruction = EXIT_QPI_MODE_CMD; //进入QSPI模式 + s_command.AddressMode = QSPI_ADDRESS_NONE; //无地址方式 + s_command.DataMode = QSPI_DATA_NONE; //无数据方式 + s_command.DummyCycles = 0; //0空闲状态周期 + + /* 发送指令 */ + if(HAL_QSPI_Command(hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } +} + +/** + * 函数功能: 连续读取若干字节,字节的个数不能超出芯片容量 + * 输入参数: _pBuf: 读取数据的存放地址 + * _read_Addr: 起始的地址 + * _read_Size: 数据个数,可以大于W25Q128FV_PAGE_SIZE,但不能超出芯片总容量 + * 返回值: 无 + * 说明: + * 1、从SPI模式切换到QSPI模式,读取完毕后切换回SPI模式(其他函数仅仅支持SPI模式)。 + */ +void QSPI_W25Qx_Read_Buffer(uint8_t *_pBuf,uint32_t _read_Addr,uint32_t _read_Size) +{ + QSPI_CommandTypeDef s_command = {0}; + + /* 进入QSPI模式 */ + QSPI_W25Qx_Enter(&hqspi); + + /* 开始从FLASH读取数据 */ + /* 基本配置 */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; //1线方式发送指令 + s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址 + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节 + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式 + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟 + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令 + + /*读取序列配置 */ + s_command.Instruction = QUAD_INOUT_FAST_READ_CMD; //24位四线快速写入指令 + s_command.AddressMode = QSPI_ADDRESS_4_LINES; //4线地址方式 + s_command.DataMode = QSPI_DATA_4_LINES; //4线数据方式 + s_command.Address = _read_Addr; //写入数据的地址 + s_command.NbData = _read_Size; //写入数据的大小 + s_command.DummyCycles = 2; //两个空闲状态周期(4个时钟周期),结合时序理解 + + /* 发送指令 */ + if(HAL_QSPI_Command(&hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + + /* 读取数据 */ + if(HAL_QSPI_Receive(&hqspi,_pBuf,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + + /* 退出QSPI模式 */ + QSPI_W25Qx_Exit(&hqspi); + +} + +/** + * 函数功能: 复位外部Flash + * 输入参数: 无 + * + * 返回值: void + * 说明: + * + */ +void QSPI_W25Qx_Reset_Memory() +{ + QSPI_CommandTypeDef s_command = {0}; + + /* 基本配置 */ + s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; //1线方式发送指令 + s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址 + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节 + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式 + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟 + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令 + + /* 复位使能W25x */ + s_command.Instruction = RESET_ENABLE_CMD; //复位使能命令 + s_command.AddressMode = QSPI_ADDRESS_NONE; //没有地址 + s_command.DataMode = QSPI_DATA_NONE; //没有数据 + s_command.DummyCycles = 0; //无空周期 + + /* 发送复位使能命令 */ + if(HAL_QSPI_Command(&hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + + /* 发送复位命令 */ + s_command.Instruction = RESET_MEMORY_CMD; //复位命令 + /* 发送复位使能命令 */ + if(HAL_QSPI_Command(&hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + + /* 自动轮询模式等待等待完成 */ + if(QSPI_W25Qx_AutoPollingMemRead(HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + user_Assert(__FILE__,__LINE__); + } + +} + + + +/** + * 函数功能: 检查代码异常,打印出异常的位置(文件名与行号) + * 输入参数: file: 源代码文件名称。关键字__FILE__表示源代码文件名。 + * line: 代码行号,关键字__LINE__表示源代码行号 + * 返回值: void + + * 说明: + * 1、在需要断言的地方直接调用user_Assert(__FILE__,__LINE__); + */ +void user_Assert(char *file,uint32_t line) +{ + printf("Wrong parameters value: file %s on line %d\r\n",file, (unsigned int)line); + + /* 这是一个死循环,断言失败时程序会卡此处死机,以便于用户差错 */ + if(line == 0) + { + return; + } + while(1) + { + + } +} + + +/** + * 函数功能: 读取Flash状态并等待操作结束 + * 输入参数: Timeout:等待时间 + * + * 返回值: Flash的状态 + * 说明: + * + * + */ + +void QSPI_W25Qx_EraseDownLoadFlash() +{ + int i =0; + int count=CODE_FLASH_STORAGE_SIZE/4/1024; + for(i=0;i<=count;i++) + { + QSPI_W25Qx_EraseSector(i*4*1024); + // HAL_Delay(10); + } + i=10; +} diff --git a/Bingoo/base/bsp_slide_averager.c b/Bingoo/base/bsp_slide_averager.c new file mode 100644 index 0000000..20ac99c --- /dev/null +++ b/Bingoo/base/bsp_slide_averager.c @@ -0,0 +1,58 @@ +/* + * bsp_slide_averager.c + * + * Created on: 2026年3月20日 + * Author: L1ng the codeGod + */ + +#include +#include +#include "bsp_slide_averager.h" + +// 滑动均值配置(按需修改) +#define WINDOW_SIZE 5 // 窗口长度 + +/** + * @brief 初始化滑动均值的核心变量(替代结构体初始化) + * @param buffer: 窗口缓冲区(外部定义的数组) + * @param p_index: 指向当前写入索引的指针(外部定义的变量) + * @param p_count: 指向有效数据计数的指针(外部定义的变量) + */ +void slide_averager_init(float buffer[], uint8_t *p_index, uint8_t *p_count) { + // 清空缓冲区 + for (uint8_t i = 0; i < WINDOW_SIZE; i++) { + buffer[i] = 0.0f; + } + // 初始化索引和计数 + *p_index = 0; + *p_count = 0; +} + +/** + * @brief 添加新数据并计算滑动均值(无结构体,全传参) + * @param buffer: 窗口缓冲区(外部数组) + * @param p_index: 当前写入索引(指针) + * @param p_count: 有效数据计数(指针) + * @param new_data: 新增原始数据 + * @retval 当前滑动均值 + */ +float slide_averager_calc(float buffer[], uint8_t *p_index, uint8_t *p_count, float new_data) { + // 1. 存入新数据(覆盖最旧数据) + buffer[*p_index] = new_data; + + // 2. 更新索引(循环滑动) + *p_index = (*p_index + 1) % WINDOW_SIZE; + + // 3. 更新有效数据计数(窗口未满时累加) + if (*p_count < WINDOW_SIZE) { + (*p_count)++; + } + + // 4. 计算均值 + float sum = 0.0f; + for (uint8_t i = 0; i < *p_count; i++) { + sum += buffer[i]; + } + return sum / *p_count; +} + diff --git a/Bingoo/base/bsp_strain_gauge.pb.c b/Bingoo/base/bsp_strain_gauge.pb.c new file mode 100644 index 0000000..ac41fee --- /dev/null +++ b/Bingoo/base/bsp_strain_gauge.pb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "bsp_strain_gauge.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(Strain_Gauge_Struct, Strain_Gauge_Struct, AUTO) + + + diff --git a/Bingoo/base/bsp_tempature.c b/Bingoo/base/bsp_tempature.c new file mode 100644 index 0000000..74a68f7 --- /dev/null +++ b/Bingoo/base/bsp_tempature.c @@ -0,0 +1,81 @@ +/* + * bsp_adc.c + * + * Created on: Feb 21, 2025 + * Author: akeguo + */ + +#include +#include "adc.h" +#include "BSP/bsp_include.h" +#include "stm32h7xx_hal_adc.h" + +#include + +// 硬件相关参数配置 +#define ADC_MAX_VALUE 0xffff // 16位ADC最大值,若为10位ADC改为1023 +#define VREF 3.3f // ADC参考电压 + +// 热敏电阻参数 (需根据实际型号确认) +#define R_REF 10000.0f // 分压电阻阻值(与热敏电阻串联) +#define B_VALUE 3380.0f // B常数 (需确认具体型号参数) +#define R0 10000.0f // 25°C时的标称阻值 +#define T0 298.15f // 25°C对应的开尔文温度(25 + 273.15) +int32_t adc_value; + +void GF_ADC_Collect(); + +int32_t * tempature; + +void ADC_Intialize() +{ + + GF_BSP_Interrupt_Add_CallBack( + DF_BSP_InterCall_TIM1_100ms_PeriodElapsedCallback, GF_ADC_Collect); +} + +void GF_ADC_Collect() +{ + *tempature = read_temperature(); +} +int32_t read_temperature() +{ + + HAL_ADC_Start(&hadc2); //开启ADC1 + + if (HAL_ADC_PollForConversion(&hadc2, 100) == HAL_OK) + { + //16 bit resolution + adc_value = HAL_ADC_GetValue(&hadc2); + + HAL_ADC_Stop(&hadc2); + // 1. 计算热敏电阻两端电压 + float voltage = (adc_value / (float) ADC_MAX_VALUE) * VREF; + + // 2. 计算热敏电阻阻值(分压电路公式) + float ntc_resistance = (voltage * R_REF) / (VREF - voltage); + //float ntc_resistance = (voltage * R_REF) / (VREF); + // 3. 使用Steinhart-Hart方程计算温度 + float steinhart; + steinhart = ntc_resistance / R0; // (R/R0) + steinhart = log(steinhart); // ln(R/R0) + steinhart /= B_VALUE; // 1/B * ln(R/R0) + steinhart += 1.0 / T0; // + (1/T0) + steinhart = 1.0 / steinhart; // 取倒数得到开尔文温度 + + + // 4. 转换为摄氏度并返回 + return (int32_t)((steinhart - 273.15)*100); + } + else + { + adc_value = 0; + HAL_ADC_Stop(&hadc2); + return 0; + } + +} + +int32_t temperature; + + diff --git a/Bingoo/base/change_line_control.c b/Bingoo/base/change_line_control.c new file mode 100644 index 0000000..1429e9b --- /dev/null +++ b/Bingoo/base/change_line_control.c @@ -0,0 +1,404 @@ +/* + * change_line_control.c + * + * Created on: 2025年8月12日 + * Author: xsq + */ +#include "change_line_control.h" +#include "BHBF_ROBOT.h" + +#define Veritical_To_Left_Flag 1 +#define Veritical_To_Right_Flag 2 + + +int LaneChangeWaittime_ms = 0; +/* + * return: ms + */ +int32_t RunTime_DistanceCm_SpeedE_2MPMin(); +int LaneChangeWaittime = 0; + +char LaneChangeFlage = -1; + + +Lane_Vertical_ChangeState Current_Vertical_ChangeState; + +LaneChangeControlSTATE VerticalLaneChangeState; /*当前换道处于开始或者结束*/ + +/* 手动换道 + * 换道依据当前车头朝向 +// * */ +//int LaneChangeControl_Paint() +//{ +////机器人SA按键处于中间状态 +//// if (P_MK32->CH4_SA == 0) +//// { +//// VerticalLaneChangeState = Lane_Change_Start; +//// Current_Vertical_ChangeState = VerticalChange_StateZero; +//// +//// if (abs(GV.Robot_Angle_Desire - CV.RobotUpAngleValue) //头朝上 +//// <= 45 * 100) +//// { +//// if (GV.PV.RunMode == Move_Vertical_Move_To_Left) +//// { +//// LaneChangeFlage = Veritical_To_Left_Flag; +//// +//// } +//// if (GV.PV.RunMode == Move_Vertical_Move_To_Right) +//// { +//// LaneChangeFlage = Veritical_To_Right_Flag; +//// +//// } +//// return 0; +//// } +//// LaneChangeFlage = -1; +//// return 0; +//// } +//// +//// if (P_MK32->CH4_SA == -1000) /*竖直上or水平换道*/ +//// { +//// +//// if (GV.PV.RunMode != Move_Vertical_Move_To_Left +//// && GV.PV.RunMode != Move_Vertical_Move_To_Right)/*竖直换道*/ +//// { +//// return 1; +//// } +//// +//// +//// if (VerticalLaneChangeState != Lane_Change_Start) +//// { +//// fsm_state_set(¤t_robot_move_state, &robot_halt_state); +//// return 1; +//// } +//// +//// if (LaneChangeFlage == Veritical_To_Left_Flag) /*向左作业*/ +//// { +//// Vertical_Lane_Change_From_Right_To_Left_UP_Control(); /*竖直上换道*/ +//// return 1; +//// } +//// if (LaneChangeFlage == Veritical_To_Right_Flag) /*向右作业*/ +//// { +//// Vertical_Lane_Change_From_Left_To_Right_UP_Control(); /*竖直上换道*/ +//// return 1; +//// } +//// return 1; +//// +//// } +//// +//// if (P_MK32->CH4_SA == 1000) //竖直下换道 +//// { +//// if (GV.PV.RunMode != Move_Vertical_Move_To_Left +//// && GV.PV.RunMode != Move_Vertical_Move_To_Right) +//// { +//// return 1; +//// } +//// +//// if (VerticalLaneChangeState != Lane_Change_Start) /*换道结束了*/ +//// { +//// fsm_state_set(¤t_robot_move_state, &robot_halt_state); +//// return 1; +//// } +//// if (LaneChangeFlage == Veritical_To_Left_Flag) /*向左作业*/ +//// { +//// Vertical_Lane_Change_From_Right_To_Left_Down_Control(); /*竖直下换道*/ +//// return 1; +//// } +//// if (LaneChangeFlage == Veritical_To_Right_Flag) /*向右作业*/ +//// { +//// Vertical_Lane_Change_From_Left_To_Right_Down_Control(); /*竖直下换道*/ +//// return 1; +//// } +//// return 1; +//// } +//// +//// return 0; +// +//} +// +// +// +///* 竖直从左往右作业 上端 向右换道 最终头朝上 +// * */ +//void Vertical_Lane_Change_From_Left_To_Right_UP_Control() +//{ +// +// GV.Robot_Move_Speed = speed_M_min_toE01_M_min( CV.Lane_Change_Speed_m_per_min); +// switch (Current_Vertical_ChangeState) +// { +// case VerticalChange_StateZero: +// { +// Current_Vertical_ChangeState = VerticalChange_TurnToLeft; +// break; +// } +// case VerticalChange_TurnToLeft: +// { +// if (abs(GV.Robot_Angle_Desire - CV.RobotLeftAngleValue) +// >= CV.Allowable_Error_For_Angle_Tracking) +// { +// fsm_state_set(¤t_robot_move_state, +// &robot_move_head_to_left_enum_state); /* 移动至头朝左 */ +// } +// else +// { +// +// fsm_state_set(¤t_robot_move_state, +// &robot_move_horizontal_task_backwards_left_state);/* 水平纠偏后退 头朝左*/ +// //开启计时 +// timer_handler_1.start_timer = 1; +// Current_Vertical_ChangeState = VerticalChange_DelayMove; +// } +// break; +// } +// case VerticalChange_DelayMove: +// { +// LaneChangeWaittime = RunTime_DistanceCm_SpeedE_2MPMin(); +// if (CompareTimer(LaneChangeWaittime, &timer_handler_1)) +// { +// +// Current_Vertical_ChangeState = VerticalChange_TurnToUP; +// } +// break; +// } +// case VerticalChange_TurnToUP: +// { +// if (abs(GV.Robot_Angle_Desire - CV.RobotUpAngleValue) +// >= CV.Allowable_Error_For_Angle_Tracking) +// { +// fsm_state_set(¤t_robot_move_state, +// &robot_move_head_to_up_enum_state); /* 移动至头朝上 */ +// } +// else +// { +// Current_Vertical_ChangeState = VerticalChange_End; +// } +// +// break; +// } +// case VerticalChange_End: +// { +// VerticalLaneChangeState = Lane_Change_Stop; +// break; +// } +// default: +// break; +// } +//} +// +///* 竖直从左往右作业 下端 向右换道 最终头朝上 +// * */ +//void Vertical_Lane_Change_From_Left_To_Right_Down_Control() +//{ +// +// GV.Robot_Move_Speed = speed_M_min_toE01_M_min( CV.Lane_Change_Speed_m_per_min); +// switch (Current_Vertical_ChangeState) +// { +// case VerticalChange_StateZero: +// { +// Current_Vertical_ChangeState = VerticalChange_TurnToRight; +// +// break; +// } +// case VerticalChange_TurnToRight: +// { +// if (abs(GV.Robot_Angle_Desire - CV.RobotRightAngleValue) +// >= CV.Allowable_Error_For_Angle_Tracking) +// { +// fsm_state_set(¤t_robot_move_state, +// &robot_move_head_to_right_enum_state); /* 移动至头朝右 */ +// } +// else +// { +// +// fsm_state_set(¤t_robot_move_state, +// &robot_move_horizontal_task_forwards_right_state);/* 水平纠偏前进 头朝右*/ +// //开启计时 +// timer_handler_1.start_timer = 1; +// Current_Vertical_ChangeState = VerticalChange_DelayMove; +// } +// break; +// } +// case VerticalChange_DelayMove: +// { +// LaneChangeWaittime = RunTime_DistanceCm_SpeedE_2MPMin(); +// if (CompareTimer(LaneChangeWaittime, &timer_handler_1)) +// { +// +// Current_Vertical_ChangeState = VerticalChange_TurnToUP; +// +// } +// break; +// } +// case VerticalChange_TurnToUP: +// { +// if (abs(GV.Robot_Angle_Desire - CV.RobotUpAngleValue) +// >= CV.Allowable_Error_For_Angle_Tracking) //误差在1度内 +// { +// fsm_state_set(¤t_robot_move_state, +// &robot_move_head_to_up_enum_state); /* 移动至头朝上 */ +// } +// else +// { +// Current_Vertical_ChangeState = VerticalChange_End; +// } +// break; +// } +// case VerticalChange_End: +// { +// VerticalLaneChangeState = Lane_Change_Stop; +// break; +// } +// default: +// break; +// } +// +//} +// +// +///* 竖直从右往左作业 上端 向左换道 最终头朝上 +// * */ +//void Vertical_Lane_Change_From_Right_To_Left_UP_Control() +//{ +// +// GV.Robot_Move_Speed = speed_M_min_toE01_M_min( CV.Lane_Change_Speed_m_per_min); +// switch (Current_Vertical_ChangeState) +// { +// case VerticalChange_StateZero: +// { +// Current_Vertical_ChangeState = VerticalChange_TurnToRight; +// break; +// } +// case VerticalChange_TurnToRight: +// { +// if (abs(GV.Robot_Angle_Desire - CV.RobotRightAngleValue) +// >= CV.Allowable_Error_For_Angle_Tracking) +// { +// fsm_state_set(¤t_robot_move_state, +// &robot_move_head_to_right_enum_state); /* 移动至头朝右 */ +// } +// else +// { +// +// fsm_state_set(¤t_robot_move_state, +// &robot_move_horizontal_task_backwards_right_state);/* 水平纠偏后退 头朝右*/ +// //开启计时 +// timer_handler_1.start_timer = 1; +// Current_Vertical_ChangeState = VerticalChange_DelayMove; +// } +// break; +// } +// case VerticalChange_DelayMove: +// { +// LaneChangeWaittime = RunTime_DistanceCm_SpeedE_2MPMin(); +// if (CompareTimer(LaneChangeWaittime, &timer_handler_1)) +// { +// Current_Vertical_ChangeState = VerticalChange_TurnToUP; +// } +// break; +// } +// case VerticalChange_TurnToUP: +// { +// if (abs(GV.Robot_Angle_Desire - CV.RobotUpAngleValue) +// >= CV.Allowable_Error_For_Angle_Tracking) +// { +// fsm_state_set(¤t_robot_move_state, +// &robot_move_head_to_up_enum_state); /* 移动至头朝上 */ +// } +// else +// { +// Current_Vertical_ChangeState = VerticalChange_End; +// } +// +// break; +// } +// case VerticalChange_End: +// { +// VerticalLaneChangeState = Lane_Change_Stop; +// break; +// } +// default: +// break; +// } +// +//} +// +///* 竖直从右往左作业 下端 向左换道 最终头朝上 +// * */ +//void Vertical_Lane_Change_From_Right_To_Left_Down_Control() +//{ +// +// GV.Robot_Move_Speed = speed_M_min_toE01_M_min( CV.Lane_Change_Speed_m_per_min);//转完 前进or后退得速度 +// switch (Current_Vertical_ChangeState) +// { +// case VerticalChange_StateZero: +// { +// Current_Vertical_ChangeState = VerticalChange_TurnToLeft; +// +// break; +// } +// case VerticalChange_TurnToLeft: +// { +// if (abs(GV.Robot_Angle_Desire - CV.RobotLeftAngleValue) +// >= CV.Allowable_Error_For_Angle_Tracking) +// { +// fsm_state_set(¤t_robot_move_state, +// &robot_move_head_to_left_enum_state); /* 移动至头朝左 */ +// } +// else +// { +// fsm_state_set(¤t_robot_move_state, +// &robot_move_horizontal_task_forwards_left_state);/* 水平纠偏前进 头朝左*/ +// //开启计时 +// timer_handler_1.start_timer = 1; +// Current_Vertical_ChangeState = VerticalChange_DelayMove; +// } +// break; +// } +// case VerticalChange_DelayMove: +// { +// LaneChangeWaittime = RunTime_DistanceCm_SpeedE_2MPMin(); +// if (CompareTimer(LaneChangeWaittime, &timer_handler_1)) +// { +// +// Current_Vertical_ChangeState = VerticalChange_TurnToUP; +// +// } +// break; +// } +// case VerticalChange_TurnToUP: +// { +// if (abs(GV.Robot_Angle_Desire - CV.RobotUpAngleValue) +// >= CV.Allowable_Error_For_Angle_Tracking) //误差在1度内 +// { +// fsm_state_set(¤t_robot_move_state, +// &robot_move_head_to_up_enum_state); /* 移动至头朝上 */ +// } +// else +// { +// Current_Vertical_ChangeState = VerticalChange_End; +// } +// break; +// } +// case VerticalChange_End: +// { +// VerticalLaneChangeState = Lane_Change_Stop; +// break; +// } +// default: +// break; +// } +// +//} +// +///* +// * return: ms +// */ +//int32_t RunTime_DistanceCm_SpeedE_2MPMin() +//{ +// +//// LaneChangeWaittime_ms = 600 * (GV.PV.LaneChangeDistance+CV.Vertical_ChangeLane_Compensation) +//// / CV.Lane_Change_Speed_m_per_min; +//// +//// return LaneChangeWaittime_ms; +// +//} + diff --git a/Bingoo/base/fsm_state.c b/Bingoo/base/fsm_state.c new file mode 100644 index 0000000..366c394 --- /dev/null +++ b/Bingoo/base/fsm_state.c @@ -0,0 +1,51 @@ +/* + * fsm.c + * + * Created on: 2025年7月14日 + * Author: akeguo + */ +#include "fsm_state.h" +#include "stdint.h" + + + + +void fsm_state_run(transition_t* p_this) +{ + // turnstile_pass(&turnstile) + if (p_this->p_state->robotRun!= NULL) + { + p_this->p_state->robotRun(p_this); + } + +} + + +//修改状态机状态,若状态机修改后,则查看是否有enter 和 exit命令进行运动 +void fsm_state_set(transition_t* p_this, transition_state_t* p_new_state) +{ + if(p_this==NULL){return;} + // turnstile_pass(&turnstile) + if (p_this->p_state!= p_new_state) /* 状态不等 */ + { + if (p_this->p_state->robotExit!=NULL) + { + p_this->p_state->robotExit(p_this); + } + + p_this->p_state = p_new_state; + if (p_this->p_state->robotEnter != NULL) + { + p_this->p_state->robotEnter(p_this); + } + //exit + + } + +} +//状态机初始化设定 +void fsm_state_init(transition_t* p_this,transition_state_t* inti_state) +{ + p_this->p_state =inti_state; +} + diff --git a/Bingoo/base/fsm_state_control.c b/Bingoo/base/fsm_state_control.c new file mode 100644 index 0000000..4832dd4 --- /dev/null +++ b/Bingoo/base/fsm_state_control.c @@ -0,0 +1,414 @@ +/* + * fsm_state_control.c + * + * Created on: Jan 13, 2026 + * Author: bm673 + */ + +/*=========================== 1. 头文件包含 ===========================*/ +#include "fsm_state_control.h" +#include "Handset_Status_Setting.h" +#include "robot_move_actions.h" +#include "paint_gun_action.h" +#include "swing_action.h" +#include "motors_power_action.h" +#include "BHBF_ROBOT.h" + +/*=========================== 2. 宏定义 ===========================*/ +/* 本文件无宏定义,预留 */ + +/*=========================== 3. 类型定义 ===========================*/ +/* 本文件无自定义类型,预留 */ + +/*=========================== 4. 全局变量 ===========================*/ +/* 调试变量(普通全局变量) */ +Robot_Mode g_debug_prev_mode = Halt_Mode; +InputEvent g_debug_curr_key = INPUT_NONE; +ActionFunc g_debug_current_action_func = NULL; +int error_detcet=0; //获取机器人错误 +uint32_t NVIC_Priority_Group; // 中断优先级分组 +uint32_t TIM8_PreemptPrio; // 定时器8 抢占优先级 +uint32_t TIM8_SubPrio; // 定时器8 子优先级 + +/*=========================== 5. 静态函数声明 ===========================*/ +/* 组函数(仅本文件使用) */ +static void manual_forward_group(void); +static void manual_backward_group(void); +static void manual_left_group(void); +static void manual_right_group(void); +static void manual_auto_group(void); +static void horizontal_forward_group(void); +static void horizontal_backward_group(void); +static void weld_auto_group(void); +static void change_Road_group(void); +static void vertical_forward_group(void); /* 虽未在表中使用,但保留 */ +static void vertical_backward_group(void); +static void horizontal_auto_group(void); +static void vertical_auto_group(void); +static void Emergency_Stop_group(void); +// 读取指定中断的抢占/子优先级,存入全局变量 +void Read_IRQ_Priority(IRQn_Type IRQn, uint32_t *preempt, uint32_t *sub); + +/*=========================== 6. 函数指针表 ===========================*/ +/* 动作映射表:模式 × 按键 -> 执行函数 */ +ActionFunc actionTable[MODE_COUNT][KEY_COUNT] = { + // Halt_Mode - 所有输入都无操作 + [Halt_Mode] = { [0 ... KEY_COUNT-1] = Robot_Stop }, + + // Manual_Mode - 手动模式 + [Manual_Mode] = { + [INPUT_ROCKER_STOP] = Robot_Stop, + [INPUT_ROCKER_FORWARD] = manual_forward_group, + [INPUT_ROCKER_BACKWARD] = manual_backward_group, + [INPUT_ROCKER_TURN_LEFT] = manual_left_group, + [INPUT_ROCKER_TURN_RIGHT] = manual_right_group, + [INPUT_KEY_FORWARD_CRUISE] = manual_forward_group, + [INPUT_KEY_BACKWARD_CRUISE] = manual_backward_group, + [INPUT_KEY_AUTO_WORK_UP] = manual_auto_group, + [INPUT_KEY_LANE_CHANGE_UP] = Robot_Stop, + [EMERGENCE_STOP] = Emergency_Stop_group, + + }, + + // Horizontal_Mode - 水平模式 + [Horizontal_Mode] = { + [INPUT_ROCKER_STOP] = Robot_Stop, + [INPUT_ROCKER_FORWARD] = horizontal_forward_group, + [INPUT_ROCKER_BACKWARD] = horizontal_backward_group, + [INPUT_ROCKER_TURN_LEFT] = manual_left_group, + [INPUT_ROCKER_TURN_RIGHT] = manual_right_group, //等待调整 INPUT_KEY_FORWARD_CRUISE + [INPUT_KEY_FORWARD_CRUISE] = horizontal_forward_group, + [INPUT_KEY_BACKWARD_CRUISE] = horizontal_backward_group, + [INPUT_KEY_AUTO_WORK_UP] = horizontal_auto_group, + [INPUT_KEY_LANE_CHANGE_UP] = change_Road_group, + [EMERGENCE_STOP] = Emergency_Stop_group, + // 其他按键暂未实现,留空(NULL) + }, + + // Flat_Mode - 暂时用于焊缝模式(预留) + [Flat_Mode] = { + [INPUT_ROCKER_STOP] = Robot_Stop, + [INPUT_ROCKER_FORWARD] = manual_forward_group, + [INPUT_ROCKER_BACKWARD] = manual_backward_group, + [INPUT_ROCKER_TURN_LEFT] = manual_left_group, + [INPUT_ROCKER_TURN_RIGHT] = manual_right_group, + [INPUT_KEY_AUTO_WORK_UP] = weld_auto_group, + [EMERGENCE_STOP] = Emergency_Stop_group, + // 暂时用于焊缝跟踪 + }, + + // Vertical_Mode_Left - 左侧垂直模式 + [Vertical_Mode_Left] = { + [INPUT_ROCKER_STOP] = Robot_Stop, + [INPUT_ROCKER_FORWARD] = vertical_forward_group, // 注意:水平前进,可能是复用 + [INPUT_ROCKER_BACKWARD] = vertical_backward_group, + [INPUT_ROCKER_TURN_LEFT] = manual_left_group, + [INPUT_ROCKER_TURN_RIGHT] = manual_right_group, //等待调整 + [INPUT_KEY_FORWARD_CRUISE] = vertical_forward_group, + [INPUT_KEY_BACKWARD_CRUISE] = vertical_backward_group, + [INPUT_KEY_LANE_CHANGE_UP] = change_Road_group, + [INPUT_KEY_AUTO_WORK_UP] = vertical_auto_group, + [EMERGENCE_STOP] = Emergency_Stop_group, + // 其他预留 + }, + + // Vertical_Mode_Right - 右侧垂直模式(预留) + [Vertical_Mode_Right] = { + [INPUT_ROCKER_STOP] = Robot_Stop, + [INPUT_ROCKER_FORWARD] = vertical_forward_group, // 注意:水平前进,可能是复用 + [INPUT_ROCKER_BACKWARD] = vertical_backward_group, + [INPUT_ROCKER_TURN_LEFT] = manual_left_group, + [INPUT_ROCKER_TURN_RIGHT] = manual_right_group, //等待调整 + [INPUT_KEY_FORWARD_CRUISE] = vertical_forward_group, + [INPUT_KEY_BACKWARD_CRUISE] = vertical_backward_group, + [INPUT_KEY_LANE_CHANGE_UP] = change_Road_group, + [INPUT_KEY_AUTO_WORK_UP] = vertical_auto_group, + [EMERGENCE_STOP] = Emergency_Stop_group, + // 未实现 + }, + + // Regional_Horizontal_Automatic_Task - 区域水平自动任务 + [Regional_Horizontal_Automatic_Task] = { + // 未实现 + }, + + // Regional_Flat_Automatic_Task - 区域平面自动任务 + [Regional_Flat_Automatic_Task] = { + // 未实现 + } + +}; + +/*=========================== 7. 静态函数实现 ===========================*/ +/*------------------------------------------------------------------- + * 组函数实现(静态) + *-------------------------------------------------------------------*/ +static void manual_forward_group(void) +{ + Manually_Forward(); + PaintGun_Contronl(); + Robot_Swing_Operation_Function(); + +} + +static void manual_backward_group(void) +{ + Manually_Backward(); + PaintGun_Contronl(); + Robot_Swing_Operation_Function(); + +} + +static void manual_left_group(void) +{ + Turn_Left(); + PaintGun_Contronl(); + Robot_Swing_Operation_Function(); + +} + +static void manual_right_group(void) +{ + Turn_Right(); + PaintGun_Contronl(); + Robot_Swing_Operation_Function(); + +} + +static void horizontal_forward_group(void) +{ + GV.Robot_Desired_Speed=GV.Robot_Move_Speed; + horizontal_forward(); + PaintGun_Contronl_Press(); + Robot_Swing_Operation_Function(); + + /* 若需喷枪控制,可在此添加 */ +} +static void horizontal_backward_group(void) +{ + GV.Robot_Desired_Speed=-GV.Robot_Move_Speed; + horizontal_forward(); + PaintGun_Contronl_Press(); + Robot_Swing_Operation_Function(); + /* 若需喷枪控制,可在此添加 */ +} + +static void manual_auto_group(void) +{ + Move_Manual_Auto_Sub_Func(); + PaintGun_Contronl_Press(); +} + +static void horizontal_auto_group(void) +{ +// horizontal_work(); + Move_Horizontal_Auto_Sub_Func(); + PaintGun_Contronl_Press(); + /* 若需喷枪控制,可在此添加 */ +} + +static void weld_auto_group(void) +{ + GV.Robot_Desired_Speed=-GV.Robot_Move_Speed; + Weld_Auto_Sub_Func(); + PaintGun_Contronl_Press(); + /* 若需喷枪控制,可在此添加 */ +} + +static void change_Road_group(void) +{ + Change_Road_Func(); + PaintGun_Contronl_Press(); + /* 若需喷枪控制,可在此添加 */ +} + + +static void vertical_forward_group(void) +{ + GV.Robot_Desired_Speed=GV.Robot_Move_Speed; + vertical_forward(); + PaintGun_Contronl_Press(); + Robot_Swing_Operation_Function(); +} + +static void vertical_backward_group(void) +{ + GV.Robot_Desired_Speed=-GV.Robot_Move_Speed; + vertical_forward(); + PaintGun_Contronl_Press(); + Robot_Swing_Operation_Function(); +} + +static void vertical_auto_group(void) +{ +// horizontal_work(); + Move_Vertical_Auto_Sub_Func(); + PaintGun_Contronl_Press(); + /* 若需喷枪控制,可在此添加 */ +} + +static void Emergency_Stop_group(void) +{ + Emergency_Stop_Action(); + Is_All_Button_Reset = 0; +} + +/*=========================== 8. 对外接口函数(需外部调用) ===========================*/ +int AbnormalDetect(void); +/*------------------------------------------------------------------- + * 初始化函数 + *-------------------------------------------------------------------*/ +void Fsm_Init(void) +{ + // 原注释掉的初始化代码 + // current_robot_move_state.p_state = &robot_halt_state; + // current_paintgun_state.p_state = &paintgun_off_state; + // current_motor_power_state.p_state = &motor_power_off_state; + + + GV.GroundManagementValue.MaualControlPower=0; + + GF_BSP_Interrupt_Add_CallBack(DF_BSP_InterCall_TIM8_2ms_PeriodElapsedCallback, GF_Dispatch); +} + +/*------------------------------------------------------------------- + * 主调度函数(2ms 周期调用) + *-------------------------------------------------------------------*/ +Robot_Mode g_debug_pre_mode = Halt_Mode; +int robot_start_flag=0; +int watch_dog=0; +void GF_Dispatch(void) +{ + Read_IRQ_Priority(TIM8_UP_TIM13_IRQn, &TIM8_PreemptPrio, &TIM8_SubPrio); + static int32_t start_time=0; //机器人上电启动时间约30s + if(start_time<20000) + { + start_time++; + //SystemErrorCode = 0; + } + else + { + error_detcet=AbnormalDetect(); + IV.robot_start=2; //表示机器人成功启动 + } + + + IV_control(); + + static Robot_Mode prev_mode = Halt_Mode; + static InputEvent prev_key = INPUT_ROCKER_STOP; + static ActionFunc prev_action_func = NULL; + g_debug_pre_mode=prev_mode; + + // 获取当前模式和按键 + InputEvent curr_key = RemoteControl_GetKeyIndex(prev_mode); + + // 仅按键变化时更新动作 + if (curr_key != prev_key) + { + robot_start_flag=1; + PV_control(); + prev_mode = RobotRockerState(); + prev_key = curr_key; + + //若有错误只保留手动模式 + if(error_detcet) + { + prev_mode=Manual_Mode; + } + + prev_action_func = actionTable[prev_mode][prev_key]; + + } + + // 执行动作 + if (prev_action_func != NULL) + { + prev_action_func(); + g_debug_current_action_func = prev_action_func; + } + + if(robot_start_flag==0) //保证上电之后摆臂就能动,不加这句的话,就要先动其它摇杆,摆臂才能动 + { + Robot_Swing_Operation_Function(); + } + + flag_reset(); + + // 更新调试变量 + g_debug_prev_mode = prev_mode; + g_debug_curr_key = curr_key; + Compensation_Update(); + get_weld_data(); +} + +/*------------------------------------------------------------------- + * 异常检测 + *-------------------------------------------------------------------*/ +int cnt=0; +int AbnormalDetect(void) +{ + + /* SBUS 出错 */ + if (Get_BIT(SystemErrorCode, ComError_Mk32_SBus) == DISCONNECTED + ||(Get_BIT(SystemErrorCode, ComError_ZQ_CAN_ID1_LeftMotor) == DISCONNECTED) + ||(Get_BIT(SystemErrorCode, ComError_ZQ_CAN_ID2_RightMotor) == DISCONNECTED) + ||(Get_BIT(SystemErrorCode, ComError_ZQ_CAN_ID3_SwingMotor) == DISCONNECTED) + ||(Get_BIT(SystemErrorCode, ComError_Ground_Management) == DISCONNECTED)) + { + cnt++; + if(cnt>250) + { + //触发软急停 + GV.GroundManagementValue.MaualControlPower=1; + GV.GroundManagementValue.MaualPowerState=0; + cnt=0; + return 1; + } + + } + + + + /* 串口出错 */ + if (Get_BIT(SystemErrorCode, ComError_MK32_Serial) == DISCONNECTED) + { + return 2; + } + + + + /* 陀螺仪无信号 */ + if (Get_BIT(SystemErrorCode, ComError_TL720D) == DISCONNECTED) + { + return 4; + } + + + /* 遥控器关机或失联 */ + if (P_MK32->IsOnline == 0) + { + GV.GroundManagementValue.MaualControlPower=1; + GV.GroundManagementValue.MaualPowerState=0; + Is_All_Button_Reset = 0; + return 6; + } + + + /* 按钮未复位 */ + if (Get_BIT(SystemErrorCode, ComError_MK32_InitialState) != Has_Reset) + { + return 3; + } + + + return 0; +} + + +// 读取指定中断的抢占/子优先级,存入全局变量 +void Read_IRQ_Priority(IRQn_Type IRQn, uint32_t *preempt, uint32_t *sub) +{ + // 调用你官方的4参数HAL函数 + HAL_NVIC_GetPriority(IRQn, NVIC_Priority_Group, preempt, sub); +} diff --git a/Bingoo/base/motor.c b/Bingoo/base/motor.c new file mode 100644 index 0000000..1838c7f --- /dev/null +++ b/Bingoo/base/motor.c @@ -0,0 +1,279 @@ +/* + * motor.c + * + * Created on: 2026年1月29日 + * Author: bm673 + */ +#include "motors.h" +#include "msp_TTMotor_ZQ.h" + + +FDCANHandler *Roughening_Motor_Controller; +FDCANHandler *Roughening_Motor_Controller_CAN2; +DispacherController *Roughening_DispacherController; +DispacherController *Roughening_DispacherController_CAN2; + + +char TT_Motor_Need_To_Activate = 1; +char TT_Motor_Need_To_Activate_1 = 1; + +float Move_Base_Speed_Count_m_Min=201.7*7.64;//天太电机1m/min +float Swing_Speed_Deg_Sencond_motor=201.7;//HJ32-121 +int middle_position_motor=-944334; +#define TT_One_Deg_Count_motor 11014///32768*121/360(减速比121)=11014 + +//MotorParameters *TT_Motor[7]; + + +void MotorCommandsLoop(); + +void MotorCommandsLoop_2(); +void MotorCommandsLoop_2_Position(); +void Roughening_MotorDecodeCAN(uint32_t canID, uint8_t *buffer, uint32_t length); +void Roughening_MotorDecodeCAN2(uint32_t canID, uint8_t *buffer, uint32_t length); +extern int32_t start_time; + +void Motor_Controller_intialize(FDCANHandler *Handler) +{ + //初始化 + Roughening_Motor_Controller = Handler; + Roughening_Motor_Controller->CAN_Decode = Roughening_MotorDecodeCAN; + HardWareErrorController->Add_PCOMHardWare(HardWareErrorController,"ZQ_CAN_ID1_LeftMotor", 1, ComError_ZQ_CAN_ID1_LeftMotor); + HardWareErrorController->Add_PCOMHardWare(HardWareErrorController,"ZQ_CAN_ID2_RightMotor", 1, ComError_ZQ_CAN_ID2_RightMotor); + Roughening_DispacherController = Handler->dispacherController; + Roughening_DispacherController->DispacherCallTime = 2; + Roughening_DispacherController->Add_Dispatcher_List(Roughening_DispacherController, MotorCommandsLoop); + + + + + //电机绑定 + TT_Motor[1]=&GV.LeftMotor; + TT_Motor[2]=&GV.RightMotor; + + TT_Motor[1]->MotorID=1; + TT_Motor[2]->MotorID=2; +} + + +void Motor_Controller_intialize_CAN2(FDCANHandler *Handler) +{ + //初始化 + Roughening_Motor_Controller_CAN2 = Handler; + Roughening_Motor_Controller_CAN2->CAN_Decode = Roughening_MotorDecodeCAN2; + HardWareErrorController->Add_PCOMHardWare(HardWareErrorController,"ZQ_CAN_ID3_SwingMotor", 1, ComError_ZQ_CAN_ID3_SwingMotor); + Roughening_DispacherController_CAN2 = Handler->dispacherController; + Roughening_DispacherController_CAN2->DispacherCallTime = 2; + Roughening_DispacherController_CAN2->Add_Dispatcher_List(Roughening_DispacherController_CAN2, MotorCommandsLoop_2_Position); + + + TT_Motor[3]=&GV.SwingMotor; + TT_Motor[3]->MotorID=3; +} + + +void MotorCommandsLoop() +{ +// +// if(start_time<15000) +// { +// HardWareErrorController->Set_PCOMHardWare(HardWareErrorController,"ZQ_CAN_ID1_LeftMotor", 1); +// HardWareErrorController->Set_PCOMHardWare(HardWareErrorController,"ZQ_CAN_ID2_RightMotor", 1); +// } + GV.LeftMotor.Target_Velcity=(int)(GV.Left_Speed_M_min*Move_Base_Speed_Count_m_Min); + GV.RightMotor.Target_Velcity=(int)(GV.Right_Speed_M_min*Move_Base_Speed_Count_m_Min); + + static int Heartbeat_Flag_01; + if (TT_Motor_Need_To_Activate == 1) + { + ActivateMotor(1, Roughening_Motor_Controller, 6000); + ActivateMotor(2, Roughening_Motor_Controller, 2000); + ActivateMotor(1, Roughening_Motor_Controller, 2000); + ActivateMotor(2, Roughening_Motor_Controller, 2000); + ActivateMotor(1, Roughening_Motor_Controller, 2000); + ActivateMotor(2, Roughening_Motor_Controller, 2000); + ActivateMotor(1, Roughening_Motor_Controller, 2000); + ActivateMotor(2, Roughening_Motor_Controller, 2000); + + + + + Enable_NMT(000,Roughening_Motor_Controller,01,1000); + Enable_NMT(000,Roughening_Motor_Controller,02,1000); + + Configure_Asynchronous_Mode(1, Roughening_Motor_Controller, 7,600); + Consumer_Or_microcontroller_Heartbeat(0x707, Roughening_Motor_Controller, 4); + Configure_Asynchronous_Mode(2, Roughening_Motor_Controller, 8,600); + Consumer_Or_microcontroller_Heartbeat(0x707, Roughening_Motor_Controller, 4); + SpeedModeSetup(1, Roughening_Motor_Controller, 6, 500, 500, 0); + Consumer_Or_microcontroller_Heartbeat(0x708, Roughening_Motor_Controller, 4); + SpeedModeSetup(2, Roughening_Motor_Controller, 6, 500, 500, 0); + Consumer_Or_microcontroller_Heartbeat(0x707, Roughening_Motor_Controller, 4); + Consumer_Or_microcontroller_Heartbeat(0x708, Roughening_Motor_Controller, 4); + TT_Motor_Need_To_Activate = 0; + } + else + { + for (int i = 1; i < 3; i++)//前两个电机 + { + TT_Request_Position(i, Roughening_Motor_Controller, 6); + TT_Request_Velocity(i, Roughening_Motor_Controller, 6); + TT_Request_Current(i, Roughening_Motor_Controller, 6); + TT_Request_Fault(i, Roughening_Motor_Controller, 6); + } + TT_SpeedMode_Set_TargetSpeed(1, Roughening_Motor_Controller, 6,GV.LeftMotor.Target_Velcity); + TT_SpeedMode_Set_TargetSpeed(2, Roughening_Motor_Controller, 6,GV.RightMotor.Target_Velcity); + } + + Heartbeat_Flag_01++; + if(Heartbeat_Flag_01%7==0) + { + Consumer_Or_microcontroller_Heartbeat(0x707, Roughening_Motor_Controller, 4); + Consumer_Or_microcontroller_Heartbeat(0x708, Roughening_Motor_Controller, 4); + Heartbeat_Flag_01=0; + } +} + + + +void MotorCommandsLoop_2_Position() +{ +// if(start_time<15000) +// { +// HardWareErrorController->Set_PCOMHardWare(HardWareErrorController, "ZQ_CAN_ID3_SwingMotor", 1); +// } + GV.SwingMotor.Tar_Position_count=(int32_t)(middle_position_motor-GV.Tar_Position_angle*TT_One_Deg_Count_motor); + GV.SwingMotor.Tar_Position_Velcity_RPM=GV.Tar_Position_Velcity_Degree_S*Swing_Speed_Deg_Sencond_motor; + + if (TT_Motor_Need_To_Activate_1 == 1) + { + ActivateMotor(3, Roughening_Motor_Controller_CAN2, 6000); + ActivateMotor(3, Roughening_Motor_Controller_CAN2, 2000); + ActivateMotor(3, Roughening_Motor_Controller_CAN2, 2000); + ActivateMotor(3, Roughening_Motor_Controller_CAN2, 2000); + ActivateMotor(3, Roughening_Motor_Controller_CAN2, 2000); + Postion_Velcocity_Run_SetParameter( 3, 0, 0, 500, 500, Roughening_Motor_Controller_CAN2, 100 ); + TT_Motor_Need_To_Activate_1 = 0; + } + else + { + for (int i = 3; i <4 ; i++)//前两个电机 + { + TT_Request_Position(3, Roughening_Motor_Controller_CAN2, 10); + + TT_Request_Fault(3, Roughening_Motor_Controller_CAN2, 10); + } + + switch(GV.SwingMotor.Position_immediately1_Lag2) + { + case 1: + Position_Immediately_Setting(3,Roughening_Motor_Controller_CAN2, GV.SwingMotor.Tar_Position_count,GV.SwingMotor.Tar_Position_Velcity_RPM,30); + break; + case 2: + Position_Lag_Setting(3,Roughening_Motor_Controller_CAN2, GV.SwingMotor.Tar_Position_count,GV.SwingMotor.Tar_Position_Velcity_RPM,30); + break; + } + } +} + + + +void MotorCommandsLoop_2() +{ + static int Heartbeat_Flag; + if (TT_Motor_Need_To_Activate_1 == 1) + { + + ActivateMotor(3, Roughening_Motor_Controller_CAN2, 6000); + ActivateMotor(3, Roughening_Motor_Controller_CAN2, 2000); + ActivateMotor(3, Roughening_Motor_Controller_CAN2, 2000); + Enable_NMT(000,Roughening_Motor_Controller_CAN2,03,1000); + Configure_Asynchronous_Mode(3, Roughening_Motor_Controller_CAN2, 9,1000); + SpeedModeSetup(3, Roughening_Motor_Controller_CAN2, 12, 500, 500, 0); + TT_Motor_Need_To_Activate_1 = 0; + } + else + { + for (int i = 3; i <4 ; i++)//前两个电机 + { + TT_Request_Position(3, Roughening_Motor_Controller_CAN2, 6); + TT_Request_Current(3, Roughening_Motor_Controller_CAN2, 6); + TT_Request_Fault(3, Roughening_Motor_Controller_CAN2, 6); + } +// TT_SpeedMode_Set_TargetSpeed(3, Roughening_Motor_Controller_CAN2, 6,GV.SwingMotor.Target_Velcity); + Heartbeat_Flag++; + if(Heartbeat_Flag%15==0) + { + Consumer_Or_microcontroller_Heartbeat(0x709, Roughening_Motor_Controller_CAN2, 4); + Heartbeat_Flag=0; + } + } +} + + + +char a[10]; +int32_t fluat_flag=0; + +void Roughening_MotorDecodeCAN(uint32_t canID, uint8_t *buffer, uint32_t length) +{ + + memcpy(a,buffer,8); + switch (canID - 0x580) + { + + case 1: + { + HardWareErrorController->Set_PCOMHardWare(HardWareErrorController,"ZQ_CAN_ID1_LeftMotor", 1); + TT_Analytic_Fun(1, buffer); + } + break; + case 2: + { + HardWareErrorController->Set_PCOMHardWare(HardWareErrorController,"ZQ_CAN_ID2_RightMotor", 1); + TT_Analytic_Fun(2, buffer); + } + break; + case 3: + { + fluat_flag=1; + } + break; + + + } + +} + + +void Roughening_MotorDecodeCAN2(uint32_t canID, uint8_t *buffer, uint32_t length) +{ + + memcpy(a,buffer,8); + switch (canID - 0x580) + { + + case 1: + { + fluat_flag=2; + } + break; + case 2: + { + fluat_flag=3; + } + break; + case 3: + { + HardWareErrorController->Set_PCOMHardWare(HardWareErrorController, "ZQ_CAN_ID3_SwingMotor", 1); + TT_Analytic_Fun(3, buffer); + } + break; + + + } + +} + + + diff --git a/Bingoo/base/motors_power_action.c b/Bingoo/base/motors_power_action.c new file mode 100644 index 0000000..a176abd --- /dev/null +++ b/Bingoo/base/motors_power_action.c @@ -0,0 +1,35 @@ +/* + * motors_power_action.c + * + * Created on: 2025年7月14日 + * Author: akeguo + */ +#include "motors_power_action.h" +#include "motors.h" + +transition_t current_motor_power_state; + +transition_state_t motor_power_on_state={Motors_Power_On_Enter,Motors_Power_On_Do,Motors_Power_On_Exit}; +transition_state_t motor_power_off_state={NULL,Motors_Power_Off_Do,NULL}; + + + +void Motors_Power_On_Do(transition_t *p_this) +{ + GF_BSP_GPIO_SetIO(Motor_Power_IO_CTL, K_ON_Motor); +} + +void Motors_Power_Off_Do(transition_t *p_this) +{ + GF_BSP_GPIO_SetIO(Motor_Power_IO_CTL, K_OFF_Motor); +} + +void Motors_Power_On_Enter(transition_t *p_this) +{ + +} +void Motors_Power_On_Exit(transition_t *p_this) +{ + +} + diff --git a/Bingoo/base/msp_DAM_Relay.c b/Bingoo/base/msp_DAM_Relay.c new file mode 100644 index 0000000..84f2a6a --- /dev/null +++ b/Bingoo/base/msp_DAM_Relay.c @@ -0,0 +1,102 @@ +/* + * msp_DAM_Relay.c + * + * Created on: Nov 5, 2024 + * Author: akeguo + */ + +#include "../../BASE/Inc/MSP/msp_DAM_Relay.h" +#include "../../BASE/Inc/BSP/BHBF_ROBOT.h" +#include "../../BASE/Inc/BSP/bsp_MB_host.h" + +//not modbus writcoil +uint8_t Dan1_open[8] = { 0xFE, 0x05, 0x00, 0x00, 0xFF, 0x00, 0x98, 0x35 }; +uint8_t Dan1_close[8] = { 0xFE, 0x05, 0x00, 0x00, 0x00, 0x00, 0xD9, 0xC5 }; +uint8_t Dan2_open[8] = { 0xFE, 0x05, 0x00, 0x01, 0xFF, 0x00, 0xC9, 0xF5 }; +uint8_t Dan2_close[8] = { 0xFE, 0x05, 0x00, 0x01, 0x00, 0x00, 0x88, 0x05 }; +uint8_t Dan3_open[8] = { 0xFE, 0x05, 0x00, 0x02, 0xFF, 0x00, 0x39, 0xF5 }; +uint8_t Dan3_close[8] = { 0xFE, 0x05, 0x00, 0x02, 0x00, 0x00, 0x78, 0x05 }; +uint8_t Dan4_open[8] = { 0xFE, 0x05, 0x00, 0x03, 0xFF, 0x00, 0x68, 0x35 }; +uint8_t Dan4_close[8] = { 0xFE, 0x05, 0x00, 0x03, 0x00, 0x00, 0x29, 0xC5 }; + +int32_t DMA_DO_Value_[4];//DAM模块 + +void decode_DAM(uint8_t *buffer, uint16_t length); +void DAM_0_Set(); +void DAM_1_Set(); +void DAM_2_Set(); +void DAM_3_Set(); + +struct UARTHandler *DAM_Relay; + +DispacherController *DAM_Relay_dispacherController; +void DAM_Relay_intialize(struct UARTHandler *Handler) { + //uartHandler_intialize(&Force_sensor,Handler,10); + DAM_Relay = Handler; + DAM_Relay->UART_Decode = decode_DAM; + DAM_Relay->Wait_time = 6; //等待10ms 最低不要低于4; + DAM_Relay_dispacherController = Handler->dispacherController; + DAM_Relay_dispacherController->DispacherCallTime = 200; //10 是100ms 难道这个2ms的定时器是10ms的? + LOG("DAM intialize"); + DAM_Relay_dispacherController->Dispacher_Enable = 1; + //log_info("angle_encoder_intialize"); + DAM_Relay_dispacherController->Add_Dispatcher_List( + DAM_Relay_dispacherController, DAM_0_Set); + DAM_Relay_dispacherController->Add_Dispatcher_List( + DAM_Relay_dispacherController, DAM_1_Set); + DAM_Relay_dispacherController->Add_Dispatcher_List( + DAM_Relay_dispacherController, DAM_2_Set); + DAM_Relay_dispacherController->Add_Dispatcher_List( + DAM_Relay_dispacherController, DAM_3_Set); +} + +void DAM_0_Set() { + if (DMA_DO_Value_[0] == 1) { + memcpy(&DAM_Relay->Tx_Buf, &Dan1_open, 8); + } else { + memcpy(&DAM_Relay->Tx_Buf, &Dan1_close, 8); + } + DAM_Relay->TxCount = 8; + DAM_Relay->UART_Tx(DAM_Relay); //send the data from the modbus command; +} +void DAM_1_Set() { + if (DMA_DO_Value_[1] == 1) { + memcpy(&DAM_Relay->Tx_Buf, &Dan2_open, 8); + } else { + memcpy(&DAM_Relay->Tx_Buf, &Dan2_close, 8); + } + DAM_Relay->TxCount = 8; + DAM_Relay->UART_Tx(DAM_Relay); //send the data from the modbus command; +} +void DAM_2_Set() { + if (DMA_DO_Value_[2] == 1) { + memcpy(&DAM_Relay->Tx_Buf, &Dan3_open, 8); + } else { + memcpy(&DAM_Relay->Tx_Buf, &Dan3_close, 8); + } + DAM_Relay->TxCount = 8; + DAM_Relay->UART_Tx(DAM_Relay); //send the data from the modbus command; +} +void DAM_3_Set() { + if (DMA_DO_Value_[3] == 1) { + memcpy(&DAM_Relay->Tx_Buf, &Dan4_open, 8); + } else { + memcpy(&DAM_Relay->Tx_Buf, &Dan4_close, 8); + } + DAM_Relay->TxCount = 8; + DAM_Relay->UART_Tx(DAM_Relay); //send the data from the modbus command; +} + +void decode_DAM(uint8_t *buffer, uint16_t length) { + + /* CRC 校验 */ + uint16_t crc_check = ((buffer[length - 1] << 8) | buffer[length - 2]); + /* CRC 校验正确 */ + if (crc_check == MB_CRC16(buffer, length - 2)) { + HardWareErrorController->Set_PCOMHardWare(HardWareErrorController, + "DAM", 1); + } else { + + } +} + diff --git a/Bingoo/base/msp_MK32.pb.c b/Bingoo/base/msp_MK32.pb.c new file mode 100644 index 0000000..4c16c0b --- /dev/null +++ b/Bingoo/base/msp_MK32.pb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "msp_MK32.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(SP_MSP_MK32_Button, SP_MSP_MK32_Button, AUTO) + + + diff --git a/Bingoo/base/msp_MK32_1.c b/Bingoo/base/msp_MK32_1.c new file mode 100644 index 0000000..40277fe --- /dev/null +++ b/Bingoo/base/msp_MK32_1.c @@ -0,0 +1,118 @@ +/* + * msp_MK32_1.c + * + * Created on: Oct 8, 2024 + * Author: akeguo + */ +#include "MSP/msp_MK32_1.h" +#include "BHBF_ROBOT.h" + +char Is_All_Button_Reset = 0; +SP_MSP_MK32_Button *P_MK32; + +struct UARTHandler *MK32_Sbus_Controller; + +void decode_MK32Data(uint8_t *buffer, uint16_t length) +{ + if (length != 25) + { + return; + } + if (buffer[0] == 0X0f && buffer[24] == 0X00) + { + Sbus_Data_Count(&buffer[1], (int32_t*) (P_MK32)); + } +// int32_t RxIndex; +// int32_t CH0_RY_H; /* 上1000,下-1000 */ +// int32_t CH1_RY_V; /* 上1000,下-1000 */ +// int32_t CH2_LY_V; /* 上1000,下-1000 */ +// int32_t CH3_LY_H; /* 上1000,下-1000 */ +// int32_t CH4_SA; /* 上-1000,下1000 */ +// int32_t CH5_SB; /* 上-1000,下1000 */ +// int32_t CH6_SC; /* 上-1000,下1000 */ +// int32_t CH7_SD; /* 上-1000,下1000 */ +// int32_t CH8_SE; /* 上-1000,下1000 */ +// int32_t CH9_SF; /* 上-1000,下1000 */ +// int32_t CH10_LD1; +// int32_t CH11_RD1; +// int32_t CH12_S1; +// int32_t CH13_S2; +// int32_t CH14_LT; +// int32_t CH15_RT; +// int32_t IsOnline; + + if (Is_All_Button_Reset == 0) + { + if (P_MK32->CH4_SA == 0 && P_MK32->CH5_SB == 0 && P_MK32->CH6_SC == 0 + && P_MK32->CH7_SD == 0 && P_MK32->IsOnline == 1) + { + HardWareErrorController->Set_PCOMHardWare(HardWareErrorController, + "Need_To_Reset", 1); + Is_All_Button_Reset = 1; + } + } + else if (Is_All_Button_Reset == 1) + { + HardWareErrorController->Set_PCOMHardWare(HardWareErrorController, + "Need_To_Reset", 1); + } + + HardWareErrorController->Set_PCOMHardWare(HardWareErrorController, + "mk32_sbus", 1); + +} + +void Sbus_Data_Count(uint8_t *buf, int32_t *But_Value) +{ + + int16_t CH[16]; + int Start_byte = -1; + + CH[0] = ((buf[Start_byte + 1] | buf[Start_byte + 2] << 8) & 0x07FF); + CH[1] = ((buf[Start_byte + 2] >> 3 | buf[Start_byte + 3] << 5) & 0x07FF); + CH[2] = ((buf[Start_byte + 3] >> 6 | buf[Start_byte + 4] << 2 + | buf[Start_byte + 5] << 10) & 0x07FF); + CH[3] = ((buf[Start_byte + 5] >> 1 | buf[Start_byte + 6] << 7) & 0x07FF); + CH[4] = ((buf[Start_byte + 6] >> 4 | buf[Start_byte + 7] << 4) & 0x07FF); + CH[5] = ((buf[Start_byte + 7] >> 7 | buf[Start_byte + 8] << 1 + | buf[Start_byte + 9] << 9) & 0x07FF); + CH[6] = ((buf[Start_byte + 9] >> 2 | buf[Start_byte + 10] << 6) & 0x07FF); + CH[7] = ((buf[Start_byte + 10] >> 5 | buf[Start_byte + 11] << 3) & 0x07FF); + CH[8] = ((buf[Start_byte + 12] | buf[Start_byte + 13] << 8) & 0x07FF); + CH[9] = ((buf[Start_byte + 13] >> 3 | buf[Start_byte + 14] << 5) & 0x07FF); + CH[10] = ((buf[Start_byte + 14] >> 6 | buf[Start_byte + 15] << 2 + | buf[Start_byte + 16] << 10) & 0x07FF); + CH[11] = ((buf[Start_byte + 16] >> 1 | buf[Start_byte + 17] << 7) & 0x07FF); + CH[12] = ((buf[Start_byte + 17] >> 4 | buf[Start_byte + 18] << 4) & 0x07FF); + CH[13] = ((buf[Start_byte + 18] >> 7 | buf[Start_byte + 19] << 1 + | buf[Start_byte + 20] << 9) & 0x07FF); + CH[14] = ((buf[Start_byte + 20] >> 2 | buf[Start_byte + 21] << 6) & 0x07FF); + CH[15] = ((buf[Start_byte + 21] >> 5 | buf[Start_byte + 22] << 3) & 0x07FF); + + //按键数值:1050为中间值,272-1712 + for (int i = 0; i < 16; i++) + { + But_Value[i + 1] = (int32_t) ((CH[i] - 992) * 1.388889); + } + + //遥控器地面站在线状态 + if (buf[22] == 0) But_Value[17] = 1; + else + But_Value[17] = 0; + + But_Value[0]++; +} + +void MK32_Sbus_UART_Handler_intialize(struct UARTHandler *Handler) +{ + MK32_Sbus_Controller = Handler; + MK32_Sbus_Controller->UART_Decode = decode_MK32Data; + MK32_Sbus_Controller->Wait_time = 4; + MK32_Sbus_Controller->dispacherController->Dispacher_Enable = 0; //不周期性发送 + + HardWareErrorController->Add_PCOMHardWare(HardWareErrorController, + "Need_To_Reset", 0, ComError_MK32_InitialState); + HardWareErrorController->Add_PCOMHardWare(HardWareErrorController, + "mk32_sbus", 0, ComError_Mk32_SBus); + LOG("MK32_Sbus_intialize"); +} diff --git a/Bingoo/base/msp_Motor.pb.c b/Bingoo/base/msp_Motor.pb.c new file mode 100644 index 0000000..b1c1176 --- /dev/null +++ b/Bingoo/base/msp_Motor.pb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "msp_Motor.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(MotorParameters, MotorParameters, AUTO) + + + diff --git a/Bingoo/base/msp_PID.c b/Bingoo/base/msp_PID.c new file mode 100644 index 0000000..bd38ed1 --- /dev/null +++ b/Bingoo/base/msp_PID.c @@ -0,0 +1,256 @@ +/* + * msp_PID.c - 两轮差速机器人角度追踪PID(内置参数,数组输出,float版本) + */ + +#include "msp_PID.h" +#include +#include + +// ========== 内置固定参数 ========== +#define CONTROL_DT 0.1f // 固定采样时间 0.1秒 +#define MAX_SPEED_FACTOR 1.6f // 最大速度 = 基础速度 * 1.6 + +// ========== 全局可调参数 ========== +float PID_KP = 0.5f; // 比例系数 +float PID_KD = 0.012f; // 微分系数 +float PID_KP_WELD = 0.1f; // 比例系数 +float PID_KD_WELD = 0.025f; // 微分系数 +float Kp1 = 1.0f; // 小角度增益因子 +float Kp2 = 0.95f; // 中小角度增益因子 +float Kp3 = 0.80f; // 中大角度增益因子 +float Kp4 = 0.50f; // 大角度增益因子 +double Desire_Angle = 0; //用于焊缝跟踪的期望角度 + +// 误差分段阈值(度) +static const float ANGLE_THRESHOLD1 = 2.0f; +static const float ANGLE_THRESHOLD2 = 5.0f; +static const float ANGLE_THRESHOLD3 = 10.0f; + +// ========== 内部静态变量 ========== +static float last_error = 0.0f; // 上一次误差(用于微分) + +// ========== 内部函数声明 ========== +static float normalize_angle(float angle); +static float compute_pd_output(float error,float KP,float KD); +static float get_gain_factor(float abs_error); +void Weld_PID(double CurrentValue, double TargetValue, double Sys_T, + double *Gain_speed); +void GF_MSP_PID_Now_Der_adj_Com_Weld(double Current_Angle, double Desire_Angle_Input, + double Auto_Speed, double Auto_Speed_Max, double System_time, double *W_Speed_1); + +// ========== 函数实现 ========== + +/* 将角度归一化到 [-180, 180) */ +static float normalize_angle(float angle) +{ + while (angle >= 180.0f) angle -= 360.0f; + while (angle < -180.0f) angle += 360.0f; + return angle; +} + +/* PD控制器:输入误差,输出控制增量(使用固定 dt = CONTROL_DT) */ +static float compute_pd_output(float error,float KP,float KD) +{ + float p_term = KP * error; + float d_term = KD * (error - last_error) / CONTROL_DT; + last_error = error; + return p_term + d_term; +} + +/* 根据误差绝对值选择增益因子 */ +static float get_gain_factor(float abs_error) +{ + if (abs_error <= ANGLE_THRESHOLD1) return Kp1; + if (abs_error <= ANGLE_THRESHOLD2) return Kp2; + if (abs_error <= ANGLE_THRESHOLD3) return Kp3; + return Kp4; +} + +/* 两轮差速角度控制(对外接口) */ +void TwoWheel_AngleControl(float current_angle, float desired_angle, + float base_speed,float zoom, float speeds[2]) +{ + // 1. 计算归一化误差 + float raw_error = desired_angle - current_angle; + float error = normalize_angle(raw_error); + float abs_error = fabsf(error); + + // 2. PD控制量 + float delta = zoom*compute_pd_output(error,PID_KP,PID_KD); + + // 3. 根据误差大小选择增益因子 + float factor = get_gain_factor(abs_error); + + // 4. 计算左右轮速度 + float left = base_speed + factor * delta; + float right = base_speed - factor * delta; + + // 5. 内置最大速度 = 1.6 * |base_speed| + float max_speed = fabsf(base_speed) * MAX_SPEED_FACTOR; + + // 6. 限幅:等比缩放至最大速度以内 + float max_abs = fmaxf(fabsf(left), fabsf(right)); + if (max_abs > max_speed && max_abs > FLT_MIN) { + float scale = max_speed / max_abs; + left *= scale; + right *= scale; + } + + speeds[0] = left; + speeds[1] = right; +} + +/* 两轮差速角度控制(对外接口) */ +void TwoWheel_AngleControl_Weld(float current_angle, float desired_angle, + float base_speed,float zoom, float speeds[2]) +{ + // 1. 计算归一化误差 + float raw_error = desired_angle - current_angle; + float error = normalize_angle(raw_error); + float abs_error = fabsf(error); + + // 2. PD控制量 + float delta = zoom*compute_pd_output(error,PID_KP_WELD,PID_KD_WELD); + + // 3. 根据误差大小选择增益因子 + float factor = get_gain_factor(abs_error); + + // 4. 计算左右轮速度 + float left = base_speed + factor * delta; + float right = base_speed - factor * delta; + + // 5. 内置最大速度 = 1.6 * |base_speed| + float max_speed = fabsf(base_speed) * MAX_SPEED_FACTOR; + + // 6. 限幅:等比缩放至最大速度以内 + float max_abs = fmaxf(fabsf(left), fabsf(right)); + if (max_abs > max_speed && max_abs > FLT_MIN) { + float scale = max_speed / max_abs; + left *= scale; + right *= scale; + } + + speeds[0] = left; + speeds[1] = right; +} + + + +void GF_MSP_PID_Now_Der_adj_Com_Weld(double Current_Angle, double Desire_Angle_Input, double Auto_Speed, double Auto_Speed_Max, double System_time, double *W_Speed_1) +{ + + Desire_Angle = Desire_Angle_Input; + //水平 前进抬车头 + double Detal_Angle = fabs(Current_Angle - Desire_Angle); + double Incre_Speed[1]; + Weld_PID(Current_Angle, Desire_Angle, System_time, Incre_Speed); + Incre_Speed[0] = 8 * Incre_Speed[0]; + double deltaAngle1 = 0.2; + double deltaAngle2 = 5; + double deltaAngle3 = 10; + //double deltaAngle4=25; + double LeftSpeed_Con_1; + double RightSpeed_Con_1; + double LeftSpeed_Con_2; + double RightSpeed_Con_2; + + LeftSpeed_Con_1 = (Auto_Speed + Kp1 * Incre_Speed[0]); + RightSpeed_Con_1 = (Auto_Speed - Kp1 * Incre_Speed[0]); + LeftSpeed_Con_2 = Auto_Speed + Kp1 * Incre_Speed[0]; + RightSpeed_Con_2 = Auto_Speed - Kp1 * Incre_Speed[0]; +// if (Detal_Angle >= deltaAngle1) +// { +// +////小角度时,两前轮调整 +// } +// else if (Detal_Angle > deltaAngle1 && Detal_Angle <= deltaAngle2) +// { +// LeftSpeed_Con_1 = (Auto_Speed + Kp2 * Incre_Speed[0]); +// RightSpeed_Con_1 = (Auto_Speed - Kp2 * Incre_Speed[0]); +// LeftSpeed_Con_2 = Auto_Speed + Kp2 * Incre_Speed[0]; +// RightSpeed_Con_2 = Auto_Speed - Kp2 * Incre_Speed[0]; +////中小角度时,两前轮差速,两后轮跟踪调整 +// } +// else if (Detal_Angle > deltaAngle2 && Detal_Angle <= deltaAngle3) +// { +// LeftSpeed_Con_1 = (Auto_Speed + Kp3 * Incre_Speed[0]); +// RightSpeed_Con_1 = (Auto_Speed - Kp3 * Incre_Speed[0]); +// LeftSpeed_Con_2 = Auto_Speed + Kp3 * Incre_Speed[0]; +// RightSpeed_Con_2 = Auto_Speed - Kp3 * Incre_Speed[0]; +// } +// else +// { +// LeftSpeed_Con_1 = (Auto_Speed + Kp4 * Incre_Speed[0]); +// RightSpeed_Con_1 = (Auto_Speed - Kp4 * Incre_Speed[0]); +// LeftSpeed_Con_2 = Auto_Speed + Kp4 * Incre_Speed[0]; +// RightSpeed_Con_2 = Auto_Speed - Kp4 * Incre_Speed[0]; +// } + + double Jud_value = fabs(LeftSpeed_Con_1) - fabs(RightSpeed_Con_1); + double factor = 0; + if (Jud_value >= 0) + { + if (LeftSpeed_Con_1 > Auto_Speed_Max) + { + factor = Auto_Speed_Max / LeftSpeed_Con_1; + LeftSpeed_Con_1 = Auto_Speed_Max; + LeftSpeed_Con_2 = LeftSpeed_Con_2 * factor; + RightSpeed_Con_1 = RightSpeed_Con_1 * factor; + RightSpeed_Con_2 = RightSpeed_Con_2 * factor; + } + else if (LeftSpeed_Con_1 < -Auto_Speed_Max) + { + factor = -Auto_Speed_Max / LeftSpeed_Con_1; + LeftSpeed_Con_1 = -Auto_Speed_Max; + LeftSpeed_Con_2 = LeftSpeed_Con_2 * factor; + RightSpeed_Con_1 = RightSpeed_Con_1 * factor; + RightSpeed_Con_2 = RightSpeed_Con_2 * factor; + } + } + else + { + if (RightSpeed_Con_1 > Auto_Speed_Max) + { + factor = Auto_Speed_Max / RightSpeed_Con_1; + RightSpeed_Con_1 = Auto_Speed_Max; + RightSpeed_Con_2 = RightSpeed_Con_2 * factor; + + LeftSpeed_Con_1 = LeftSpeed_Con_1 * factor; + LeftSpeed_Con_2 = LeftSpeed_Con_2 * factor; + } + else if (LeftSpeed_Con_2 < -Auto_Speed_Max) + { + factor = -Auto_Speed_Max / RightSpeed_Con_1; + RightSpeed_Con_1 = -Auto_Speed_Max; + RightSpeed_Con_2 = RightSpeed_Con_2 * factor; + + LeftSpeed_Con_1 = LeftSpeed_Con_1 * factor; + LeftSpeed_Con_2 = LeftSpeed_Con_2 * factor; + } + } + + W_Speed_1[0] = LeftSpeed_Con_1; + W_Speed_1[1] = RightSpeed_Con_1; + W_Speed_1[2] = LeftSpeed_Con_2; + W_Speed_1[3] = RightSpeed_Con_2; + +} + + +double Weld_KP = 10; +double Weld_KD = 10; +//double Sys_T=0.01;//System time +double Weld_1_error = 0; +void Weld_PID(double CurrentValue, double TargetValue, double Sys_T, + double *Gain_speed) +{ + double Error; + double P_Error; + double D_Error; + Error = TargetValue - CurrentValue; + + P_Error = Error; + D_Error = Error - Weld_1_error; + Weld_1_error = Error; + Gain_speed[0] = Weld_KP * P_Error + Weld_KD * D_Error / Sys_T; +} diff --git a/Bingoo/base/msp_TL720D.c b/Bingoo/base/msp_TL720D.c new file mode 100644 index 0000000..235fcf5 --- /dev/null +++ b/Bingoo/base/msp_TL720D.c @@ -0,0 +1,100 @@ +/* + * msp_TL720D.c + * + * Created on: Jul 19, 2024 + * Author: bihon + */ + +#include "MSP/msp_TL720D.h" +#include "BHBF_ROBOT.h" +#include "msp_TL720D.pb.h" + +//Roll:0.01° +int32_t *RobotAngle; + +struct UARTHandler *TL720D_UART_Handler; + +MSP_TL720DParameters* SP_MSP_RF_TL720D_Parameters_In; + + + +void decode_TL720D(uint8_t *buffer, uint16_t length); +int16_t getDeci(uint8_t *data); + +void TL720D_intialize(struct UARTHandler *Handler) +{ + + //TL720D_UART_Handler->UART_Decode = NULL; + TL720D_UART_Handler = Handler; + TL720D_UART_Handler->Wait_time=6; + TL720D_UART_Handler->dispacherController->Dispacher_Enable=0;//不周期性发送 + TL720D_UART_Handler->UART_Decode = decode_TL720D; + HardWareErrorController->Add_PCOMHardWare(HardWareErrorController,"TL720D",0,ComError_TL720D); + //log_info("TL720D_intialize"); + LOGFF(DL_ERROR,"TL720D_intialize"); +} +void decode_TL720D(uint8_t *buffer, uint16_t length) +{ + + if (buffer[0] == 0x68 && buffer[1] == 0x1F && buffer[2] == 0x00 + && buffer[3] == 0x84) + { + //SP_MSP_RF_TL720D_Parameters_In. + SP_MSP_RF_TL720D_Parameters_In->RF_Angle_Roll = getDeci(&buffer[4]); + SP_MSP_RF_TL720D_Parameters_In->RF_Angle_Pitch = getDeci(&buffer[7]); + SP_MSP_RF_TL720D_Parameters_In->RF_Angle_Yaw = getDeci(&buffer[10]); + SP_MSP_RF_TL720D_Parameters_In->RF_Acc_X = getDeci(&buffer[13]); + SP_MSP_RF_TL720D_Parameters_In->RF_Acc_Y = getDeci(&buffer[16]); + SP_MSP_RF_TL720D_Parameters_In->RF_Acc_Z = getDeci(&buffer[19]); + SP_MSP_RF_TL720D_Parameters_In->RF_Gro_X = getDeci(&buffer[22]); + SP_MSP_RF_TL720D_Parameters_In->RF_Gro_Y = getDeci(&buffer[25]); + SP_MSP_RF_TL720D_Parameters_In->RF_Gro_Z = getDeci(&buffer[28]); + LOG("TL720D decoding succeeded"); + + *RobotAngle=SP_MSP_RF_TL720D_Parameters_In->RF_Angle_Roll; + //Is_TL720_Updating_Flag=true; + HardWareErrorController->Set_PCOMHardWare(HardWareErrorController,"TL720D",1); + } else + { + //log_error("TL720D decoding failed"); + LOGFF(DL_ERROR,"TL720D decoding failed"); + + } + +} + +/* 数值计算 + * data: 数据地址 + * return: 单位: 0.01 + * */ +int16_t getDeci(uint8_t *data) +{ + char isNegative = 0; + + if (*data >> 4) + { + isNegative = 1; + } else + { + isNegative = 0; + } + + int16_t data_value = 0; + data_value = ((*data) & 0x0f) * 10000; + data++; + data_value += (*data >> 4) * 1000; + data_value += ((*data) & 0x0f) * 100; + data++; + + int16_t xiaoshu = 0; + xiaoshu = (*data >> 4) * 10; + xiaoshu += (*data) & 0x0f; + if (isNegative) + { + return -(data_value + xiaoshu); + } else + { + return (data_value + xiaoshu); + } + +} diff --git a/Bingoo/base/msp_TL720D.pb.c b/Bingoo/base/msp_TL720D.pb.c new file mode 100644 index 0000000..4681edd --- /dev/null +++ b/Bingoo/base/msp_TL720D.pb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "msp_TL720D.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(MSP_TL720DParameters, MSP_TL720DParameters, AUTO) + + + diff --git a/Bingoo/base/msp_TTMotor_ZQ.c b/Bingoo/base/msp_TTMotor_ZQ.c new file mode 100644 index 0000000..f97e959 --- /dev/null +++ b/Bingoo/base/msp_TTMotor_ZQ.c @@ -0,0 +1,426 @@ +/* + * msp_TTMotor_ZQ.c + * + * Created on: Oct 10, 2024 + * Author: akeguo + */ +#include "msp_TTMotor_ZQ.h" +#include "BHBF_ROBOT.h" + + +TT_MotorParameters *TT_Motor[7]; + + +void ActivateMotor(int32_t MotorID, FDCANHandler *ZQ_Motor_Controller, + int32_t WaitTime) +{ + ZQ_Motor_Controller->Tx_Buf[0] = 0x10; + ZQ_Motor_Controller->Tx_Buf[1] = 0x10; + ZQ_Motor_Controller->AddCANSendList(ZQ_Motor_Controller, MotorID, 2, + ZQ_Motor_Controller->Tx_Buf, WaitTime, NULL); //wait for 5 seconds to send + + //CANSendMessageSDO_ADD_To_SendList(MotorID, 0x23, 0x6083, 0x00, AccTime,ZQ_Motor_Controller,WaitTime); +} +void Enable_NMT(int32_t MotorID, FDCANHandler *ZQ_Motor_Controller, int32_t Node_Number, int32_t WaitTime) +{ + ZQ_Motor_Controller->Tx_Buf[0] = 0x01; + ZQ_Motor_Controller->Tx_Buf[1] = Node_Number; + ZQ_Motor_Controller->AddCANSendList(ZQ_Motor_Controller, MotorID, 2, ZQ_Motor_Controller->Tx_Buf, WaitTime, NULL); //wait for 5 seconds to send +} + +void Configure_Asynchronous_Mode(int32_t MotorID, FDCANHandler *ZQ_Motor_Controller, int32_t Node_Number, int32_t WaitTime) +{ + ZQ_Motor_Controller->Tx_Buf[0] = 0x23; + ZQ_Motor_Controller->Tx_Buf[1] = 0x16; + ZQ_Motor_Controller->Tx_Buf[2] = 0x10; + ZQ_Motor_Controller->Tx_Buf[3] = 0x01; + ZQ_Motor_Controller->Tx_Buf[4] = 0xe8; + ZQ_Motor_Controller->Tx_Buf[5] = 0x03; + ZQ_Motor_Controller->Tx_Buf[6] = Node_Number; + ZQ_Motor_Controller->Tx_Buf[7] = 0x00; + ZQ_Motor_Controller->AddCANSendList(ZQ_Motor_Controller, 0x600 + MotorID, 8, ZQ_Motor_Controller->Tx_Buf, WaitTime, NULL); +} + +void Consumer_Or_microcontroller_Heartbeat(int32_t MotorID, FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime) +{ + ZQ_Motor_Controller->Tx_Buf[0] = 0x05; + ZQ_Motor_Controller->AddCANSendList(ZQ_Motor_Controller, MotorID, 1, ZQ_Motor_Controller->Tx_Buf, WaitTime, NULL); //wait for 5 seconds to send +} + + +void CANSendMessageSDO_ADD_To_SendList(int32_t MotorID, uint8_t Function, + uint16_t ControlWord, uint8_t subWord, int32_t ControlWordValue, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime) +{ + //copy the corresponsiding data to the send Array + ZQ_Motor_Controller->Tx_Buf[0] = Function; + memcpy(&ZQ_Motor_Controller->Tx_Buf[1], &ControlWord, 2); + ZQ_Motor_Controller->Tx_Buf[3] = subWord; + memcpy(&ZQ_Motor_Controller->Tx_Buf[4], &ControlWordValue, 4); + //send 8 bytes data + + ZQ_Motor_Controller->AddCANSendList(ZQ_Motor_Controller, 0x600 + MotorID, 8, + ZQ_Motor_Controller->Tx_Buf, WaitTime, NULL); +} + +//位置速度模式 +void Postion_Velcocity_Run_SetParameter(int32_t MotorID, int32_t TargetPosition, + int32_t TargetSpeed, int32_t AccTime, int32_t DecTime, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime) +{ + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2f, 0x6060, 0x00, 1, + ZQ_Motor_Controller, WaitTime); // 1:设置操作模式,向索引0x6060:00写入0x01 + if (TargetSpeed >= 3500) //the highest is 3500 + { + TargetSpeed = 3500; + } + if (TargetSpeed < 0) + { + TargetSpeed = 0; + } + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x23, 0x6083, 0x00, AccTime, + ZQ_Motor_Controller, WaitTime); //2:设置加速时间,向索引0x6083:00写入4字节数值 + // Thread.Sleep(2); + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x23, 0x6084, 0x00, DecTime, + ZQ_Motor_Controller, WaitTime); //3:设置减速时间,向索引0x6084:00写入4字节数值 + //Thread.Sleep(2); + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x23, 0x607A, 0x00, + TargetPosition, ZQ_Motor_Controller, WaitTime); //4:设置目标位置,向索引 0x607A:00写入4字节数值 + // Thread.Sleep(2); + + //23:写4字节数据; + //816000:索引号为0x6081,子索引号为0x00; + //E80300 00:设置运行速度为1000(单位0.1rpm) + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x23, 0x6081, 0x00, + TargetSpeed * 10, ZQ_Motor_Controller, WaitTime); //5:设置运行速度,向索引 0x6081:00写入4字节数值 + + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x80, + ZQ_Motor_Controller, WaitTime); ///6:清除异常,向控制字0x6040:00写入0x80 + + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x06, + ZQ_Motor_Controller, WaitTime); //7:伺服准备,向控制字 0x6040:00写入0x06 + + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x07, + ZQ_Motor_Controller, WaitTime); //8:伺服等待使能,向控制字0x6040:00写入0x07 + + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x2f, + ZQ_Motor_Controller, WaitTime); //9:伺服使能,向控制字0x6040:00写入0x0F + + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x3f, + ZQ_Motor_Controller, WaitTime); //10:伺服启动,向控制字 0x6040:00写入0x1F ///: +} + +void Postion_Velcocity_Set_Position(int32_t MotorID, int32_t TargetPosition, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime) +{ +// 3、立即更新时,重复执行步骤4、步骤9(控制字(6040)写入2F)和步骤10(控制字(6040) +// 写入3F),驱动器还没到达当前目标位置时,支持接收新的目标位置,最终到达的目标位 +// 置是:新的目标位置。 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x23, 0x607a, 0x00, + TargetPosition, ZQ_Motor_Controller, WaitTime); //设置目标位置 + //Thread.Sleep(2); + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x2f, + ZQ_Motor_Controller, WaitTime); ///: + + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x3f, + ZQ_Motor_Controller, WaitTime); ///: +} + +void Driver_ReadError(int32_t MotorID, FDCANHandler *ZQ_Motor_Controller, + int32_t WaitTime) +{ + //CANSendMessageSDO_ADD_To_SendList(CAN_ID, new byte[8] { 0x40, 0x0A, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00 });//40 0A 30 00 00 00 00 00 + + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x40, 0x300a, 0x00, 0, + ZQ_Motor_Controller, WaitTime); //40 0A 30 00 00 00 00 00 +} +void SetMotorTargetPosition(int32_t MotorID, int32_t TargetPosition, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime) +{ + Postion_Velcocity_Set_Position(MotorID, TargetPosition, ZQ_Motor_Controller, + WaitTime); +} + +void Postion_Velcocity_Stop(int32_t MotorID, FDCANHandler *ZQ_Motor_Controller, + int32_t WaitTime) +{ + + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6085, 0x00, 200, + ZQ_Motor_Controller, WaitTime); // 6085 的减速时间100ms + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x605a, 0x00, 6, + ZQ_Motor_Controller, WaitTime); // 0x06:按索引 6085 的减速时间进行减速,停下时电机 轴处于锁轴状态。 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x02, + ZQ_Motor_Controller, WaitTime); //快速停机 +} + +//void SetCurrentPositionZero(int32_t MotorID,FDCANHandler *ZQ_Motor_Controller,int32_t WaitTime) +//{ +// CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2f, 0x6098, 0x00, 0x23,ZQ_Motor_Controller,WaitTime); //1:设置定位的方式,向索 引0x6098:00写入0X23 +// CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2f, 0x6060, 0x00, 6,ZQ_Motor_Controller,WaitTime); //2:设置操作模式,向索引0x6060:00写入0x06 +// CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x80,ZQ_Motor_Controller,WaitTime); //3:清除异常,向控制字 0x6040:00写入0x80 +// CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x06,ZQ_Motor_Controller,WaitTime); //4:伺服准备,向控制字 0x6040:00写入0x06 +// CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x07,ZQ_Motor_Controller,WaitTime); //5:伺服等待使能,向控制字0x6040:00写入0x07 +// CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x0F,ZQ_Motor_Controller,WaitTime); //6:伺服使能,向控制字0x6040:00写入0x0F +// CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2f, 0x6040, 0x00, 0x1F,ZQ_Motor_Controller,WaitTime); //7:启动原点定位,向控制字0x6040:00写入0x1F +//} + +void SpeedModeSetup(int32_t MotorID, FDCANHandler *ZQ_Motor_Controller, + int32_t WaitTime, int32_t Acc, int32_t Dec, int32_t TargetVelocity) //设定速度模式,并更改相关速度 +{ + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x02, + ZQ_Motor_Controller, 100); + //设置操作模式,向索引0x6060:00写入0x03 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2f, 0x6060, 0x00, 0x3, + ZQ_Motor_Controller, WaitTime); + //2:清除异常, 向控制字 0x6040:00 写入 0x80 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x80, + ZQ_Motor_Controller, WaitTime); + //3: 伺服准备, 向控制字 0x6040:00 写入 0x06 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x06, + ZQ_Motor_Controller, WaitTime); + //4: 伺服等待使能, 向控制字 0x6040:00 写入 0x07 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x07, + ZQ_Motor_Controller, WaitTime); + //5: 伺服使能,向控制字0x6040:00 写入 0x0F + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x0f, + ZQ_Motor_Controller, WaitTime); + //6:设置加速时间, 向索引 0x201C:00写入4字节数值 //不关心加速时间的模式下, 加减速时间建议设置为 1500(ms) 以上 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x23, 0x201c, 0x00, Acc, + ZQ_Motor_Controller, WaitTime); + //7: 设置减速时间, 向索引0x201D:00写入4字节数据 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x23, 0x201d, 0x00, Dec, + ZQ_Motor_Controller, WaitTime); + //8: 设定目标速度值, 向索引 0x60FF:00 写入 4 字节数值(有符号) + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x23, 0x60ff, 0x00, + TargetVelocity, ZQ_Motor_Controller, WaitTime); ///6:清除异常,向控制字 + + //修改步骤8 可以实现速度的改变 + // 23:写 4 字节数据;FF 60 00:索引号为 0x60FF, + // 子索引号为 0x00;E8 03 00 00: + // 设置目标速度 1000(单位 0.1rpm) +} +void TT_SpeedMode_Set_TargetSpeed(uint32_t MotorID, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime, + int32_t TargetSpeed) +{ + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x23, 0x60ff, 0x00, TargetSpeed, + ZQ_Motor_Controller, WaitTime); +} + +void Swing_Motor_Set_Target_Position() +{ + CANSendMessageSDO(SwingMotorID, 0x40, 0x6041, 0x00, 0x00); ///:是否到达目的位置 +} + +void Swing_Motor_Read_ReachedEnd() +{ + CANSendMessageSDO(SwingMotorID, 0x40, 0x6041, 0x00, 0x00); ///:是否到达目的位置 + +} + +void Set_Current_Positon_Zero(uint8_t MotorID, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime) // Home 设置当前位置为零点 +{ + +// CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x2f,ZQ_Motor_Controller,WaitTime); ///: +// CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x3f,ZQ_Motor_Controller,WaitTime); ///: + + //CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x2008, 0x00, 0x01,ZQ_Motor_Controller,1000); + //CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x02,ZQ_Motor_Controller,100); //1. 停止执行 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2f, 0x6098, 0x00, 0x23, + ZQ_Motor_Controller, WaitTime); //1. 设置定位的方式,向索引0x6098:00写入0X23 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2f, 0x6060, 0x00, 0x06, + ZQ_Motor_Controller, WaitTime); //2:设置操作模式,向索引0x6060:00写入0x06 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x80, + ZQ_Motor_Controller, WaitTime); //3:清除异常,向控制字0x6040:00写入0x80 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x06, + ZQ_Motor_Controller, WaitTime); //4.伺服准备,向控制字0x6040:00写入0x06 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x07, + ZQ_Motor_Controller, WaitTime); //5. 伺服等待使能,向控制字0x6040:00写入0x07 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x0f, + ZQ_Motor_Controller, WaitTime); //6. 伺服使能 向控制字 0x6040:00写入0x0F + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2f, 0x6040, 0x00, 0x1f, + ZQ_Motor_Controller, WaitTime); //7. :启动原点定位,向控制字0x6040:00写入0x1F + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x40, 0x6041, 0x00, 0x0, + ZQ_Motor_Controller, 100); //8. :启动原点定位,向控制字0x6040:00写入0x1F + +} + +void TT_Request_Position(uint32_t Motor_ID_1, FDCANHandler *ZQ_Motor_Controller, + int32_t WaitTime) // Home 设置当前位置为零点 +{ + CANSendMessageSDO_ADD_To_SendList(Motor_ID_1, 0x40, 0x6064, 0x00, 0x00, + ZQ_Motor_Controller, WaitTime); //用户实际速度反馈(0.1rpm) +} + + +void Position_Immediately_Setting(uint8_t MotorID, FDCANHandler *ZQ_Motor_Controller,int32_t Deri_Position,int32_t Deri_Speed, int32_t WaitTime) // Home 设置当前位置为零点 +{ + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x23, 0x607A, 0x00, Deri_Position, ZQ_Motor_Controller, WaitTime); //设置位置 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x23, 0x6081, 0x00, Deri_Speed, ZQ_Motor_Controller, WaitTime); //设置速度 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2B, 0x6040, 0x00, 0x2f, ZQ_Motor_Controller, WaitTime); + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2B, 0x6040, 0x00, 0x3f, ZQ_Motor_Controller, WaitTime); +} + +void Position_Lag_Setting(uint8_t MotorID, FDCANHandler *ZQ_Motor_Controller,int32_t Deri_Position,int32_t Deri_Speed, int32_t WaitTime) // Home 设置当前位置为零点 +{ + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x23, 0x607A, 0x00, Deri_Position, ZQ_Motor_Controller, WaitTime); //设置位置 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x23, 0x6081, 0x00, Deri_Speed, ZQ_Motor_Controller, WaitTime); //设置速度 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2B, 0x6040, 0x00, 0x0f, ZQ_Motor_Controller, WaitTime); + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2B, 0x6040, 0x00, 0x1f, ZQ_Motor_Controller, WaitTime); +} + + + + +void Position_Lay_Setting(uint8_t MotorID, FDCANHandler *ZQ_Motor_Controller,int32_t Deri_Position,int32_t Deri_Speed, int32_t WaitTime) // Home 设置当前位置为零点 +{ + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2f, 0x6098, 0x00, 0x23, + ZQ_Motor_Controller, WaitTime); //1. 设置定位的方式,向索引0x6098:00写入0X23 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2f, 0x6060, 0x00, 0x06, + ZQ_Motor_Controller, WaitTime); //2:设置操作模式,向索引0x6060:00写入0x06 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x80, + ZQ_Motor_Controller, WaitTime); //3:清除异常,向控制字0x6040:00写入0x80 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x06, + ZQ_Motor_Controller, WaitTime); //4.伺服准备,向控制字0x6040:00写入0x06 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x07, + ZQ_Motor_Controller, WaitTime); //5. 伺服等待使能,向控制字0x6040:00写入0x07 + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2b, 0x6040, 0x00, 0x0f, + ZQ_Motor_Controller, WaitTime); //6. 伺服使能 向控制字 0x6040:00写入0x0F + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x2f, 0x6040, 0x00, 0x1f, + ZQ_Motor_Controller, WaitTime); //7. :启动原点定位,向控制字0x6040:00写入0x1F + CANSendMessageSDO_ADD_To_SendList(MotorID, 0x40, 0x6041, 0x00, 0x0, + ZQ_Motor_Controller, 100); //8. :启动原点定位,向控制字0x6040:00写入0x1F +} + + + + + +void TT_Request_Velocity(uint32_t Motor_ID_1, FDCANHandler *ZQ_Motor_Controller, + int32_t WaitTime) +{ + CANSendMessageSDO_ADD_To_SendList(Motor_ID_1, 0x40, 0x606c, 0x00, 0x00, + ZQ_Motor_Controller, WaitTime); //用户实际速度反馈(0.1rpm) + +} +// +// +void TT_Request_Fault(uint32_t Motor_ID_1, FDCANHandler *ZQ_Motor_Controller, + int32_t WaitTime) +{ + CANSendMessageSDO_ADD_To_SendList(Motor_ID_1, 0x40, 0x300A, 0x00, 0x00, + ZQ_Motor_Controller, WaitTime); + +} + +void TT_Request_Current(uint32_t Motor_ID_1, FDCANHandler *ZQ_Motor_Controller, + int32_t WaitTime) +{ + CANSendMessageSDO_ADD_To_SendList(Motor_ID_1, 0x40, 0x6078, 0x00, 0x00, + ZQ_Motor_Controller, WaitTime); +} + +void TT_Analytic_Fun(int32_t ID_A_T_A, char *buffer) +{ + + int Function_code = (int) ((int16_t) (buffer[1] | buffer[2] << 8)); + switch (Function_code) + { + + case 24672: + TT_Motor[ID_A_T_A]->Cont_Posi_Suc = 1; + break; + case 24707: + TT_Motor[ID_A_T_A]->Acc_Suc = 1; + break; + case 24708: + TT_Motor[ID_A_T_A]->Dec_Suc = 1; + break; + case 24698: + TT_Motor[ID_A_T_A]->Target_Posi_Suc = 1; + break; + case 24705: + TT_Motor[ID_A_T_A]->Run_Speed_Suc = 1; + break; + case 24640: + TT_Motor[ID_A_T_A]->Clear_Suc = 1; + break; + case 8220: + TT_Motor[ID_A_T_A]->Acc_Suc_Speed = 1; + break; + case 24831: + TT_Motor[ID_A_T_A]->Suc_Speed_S = 1; + break; + case 8221: + TT_Motor[ID_A_T_A]->Dec_Suc_Speed = 1; + break; + case 24676: + { + TT_Motor[ID_A_T_A]->Real_Position = (int) (buffer[4] + | (buffer[5]) << 8 | (buffer[6]) << 16 | (buffer[7] << 24)); + if (TT_Motor[ID_A_T_A]->Start_Measuring == 1) + { + TT_Motor[ID_A_T_A]->Start_Measuring =0; + TT_Motor[ID_A_T_A]->Number_Of_Rounds=0; + + TT_Motor[ID_A_T_A]->Start_Measuring_Position=TT_Motor[ID_A_T_A]->Real_Position; + TT_Motor[ID_A_T_A]->Last_Real_Position=TT_Motor[ID_A_T_A]->Real_Position; + } + else + { + if (abs( + TT_Motor[ID_A_T_A]->Real_Position + - TT_Motor[ID_A_T_A]->Last_Real_Position) + >= 30000) + { + if (TT_Motor[ID_A_T_A]->Real_Position > 0) + { + TT_Motor[ID_A_T_A]->Number_Of_Rounds -= 1; + } + else + { + TT_Motor[ID_A_T_A]->Number_Of_Rounds += 1; + } + } + } + + TT_Motor[ID_A_T_A]->Last_Real_Position = + TT_Motor[ID_A_T_A]->Real_Position; + + double CircleLength = 3.14 * 280/1000 ; //pi*d //m + + double _tempDeltCounts = TT_Motor[ID_A_T_A]->Real_Position + - TT_Motor[ID_A_T_A]->Start_Measuring_Position; + TT_Motor[ID_A_T_A]->Real_Disatnce = (_tempDeltCounts/ 32768/101 + + (double) TT_Motor[ID_A_T_A]->Number_Of_Rounds + ) + * CircleLength; + + } + + break; + case 24684: + TT_Motor[ID_A_T_A]->Real_Velcity = (int) (buffer[4] + | (buffer[5]) << 8 | (buffer[6]) << 16 | (buffer[7] << 24)); + break; + + case 24696: + TT_Motor[ID_A_T_A]->Real_Current = (int) (buffer[4] + | (buffer[5]) << 8 | (buffer[6]) << 16 | (buffer[7] << 24)); //0.1A + break; + case 12298://0x3001 + TT_Motor[ID_A_T_A]->TT_Motor_Fault = (int) (buffer[4] + | (buffer[5]) << 8 | (buffer[6]) << 16 | (buffer[7] << 24)); + + break; + + default: + if ((buffer[0] == (0XAA)) | (buffer[1] == (0XBB))) + { + TT_Motor[ID_A_T_A]->Act_Suc = 1; + } + break; + } +} + diff --git a/Bingoo/base/msp_WH_LTE_7S0.c b/Bingoo/base/msp_WH_LTE_7S0.c new file mode 100644 index 0000000..5e8e5da --- /dev/null +++ b/Bingoo/base/msp_WH_LTE_7S0.c @@ -0,0 +1,98 @@ + +#include "BHBF_ROBOT.h" +#include "bsp_decode_command.h" +#include "gpio.h" + +#include "BSP/bsp_UART.h" + +#include + + +char NeedToFeedBackToComputer = 0; + +struct UARTHandler *wh_LTE_7S0_Handler; +DispacherController* wh_LTE_7S0_dispacher; + + +void Reset() +{ + HAL_GPIO_WritePin(S0_RESET_GPIO_Port, S0_RESET_Pin, GPIO_PIN_RESET); +} +void NormalState() +{ + HAL_GPIO_WritePin(S0_RESET_GPIO_Port, S0_RESET_Pin, GPIO_PIN_SET); +} +void WH_LTE_7S0_intialize(struct UARTHandler *Handler) +{ + //NormalState(); + HAL_GPIO_WritePin(S0_RESET_GPIO_Port, GPIO_PIN_10, GPIO_PIN_SET); + wh_LTE_7S0_Handler = Handler; + wh_LTE_7S0_Handler->Wait_time = 40; // 最低不要低于4; + wh_LTE_7S0_dispacher=Handler->dispacherController; + //不周期性发送 + wh_LTE_7S0_dispacher->Dispacher_Enable=1; + wh_LTE_7S0_dispacher->Add_Dispatcher_List(wh_LTE_7S0_dispacher,UpdateGV); + wh_LTE_7S0_dispacher->DispacherCallTime=1000; + //DispacherController* disp=wh_LTE_7S0_Handler->dispacherController; + + //disp->Add_Dispatcher_List(disp,UpdateGV);//周期性update GV数据 + + LOG("WH_LTE_7S0_intialize"); + + wh_LTE_7S0_Handler->UART_Decode = decode_received_data_from_computer; //indicate that there is no need to listen + +} + +void Send_WH_LTE_7S0_Data(uint8_t *data, int length) +{ + + char datass[100]; + memcpy(datass, data, length); + wh_LTE_7S0_Handler->UART_Decode = decode_received_data_from_computer; + memcpy(wh_LTE_7S0_Handler->Tx_Buf, data, length); + wh_LTE_7S0_Handler->TxCount = length; + wh_LTE_7S0_Handler->UART_Tx(wh_LTE_7S0_Handler); + +} +void UpdateGV() +{ + + //wh_LTE_7S0_Handler->UART_Decode = decode_received_data_from_computer; + pb_ostream_t GV_o_stream = + { 0 }; + char buf[1024]; + GV_o_stream = pb_ostream_from_buffer(buf, sizeof(buf)); + pb_encode(&GV_o_stream, GV_struct_define_fields, &GV); + + + memcpy(&wh_LTE_7S0_Handler->Tx_Buf[2], buf, GV_o_stream.bytes_written); + wh_LTE_7S0_Handler->Tx_Buf[0]='1'; + wh_LTE_7S0_Handler->Tx_Buf[1]=','; + //wh_LTE_7S0_Handler->Tx_Buf[2]='1'; + + wh_LTE_7S0_Handler->TxCount = GV_o_stream.bytes_written+2; + wh_LTE_7S0_Handler->UART_Tx(wh_LTE_7S0_Handler); +} + +void decode_received_data_from_computer(uint8_t *buffer, uint16_t length) +{ + char buf[1024]; + memcpy(buf, buffer, length); + if(buffer[0]=='2'&&buffer[1]==',') + { + //Decode protobuf + //decode_command_from_computer(buffer+2,length-2); + decode_command_and_feedback(buffer+2,length-2,1,wh_LTE_7S0_Handler); + + } + if(NeedToFeedBackToComputer==1) + { + send_received_data_to_upper_computer(buffer, length); + } + +} + + + + + diff --git a/Bingoo/base/msp_ZQ_MotorParameters.pb.c b/Bingoo/base/msp_ZQ_MotorParameters.pb.c new file mode 100644 index 0000000..e1d5aa5 --- /dev/null +++ b/Bingoo/base/msp_ZQ_MotorParameters.pb.c @@ -0,0 +1,20 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "msp_ZQ_MotorParameters.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(TT_MotorParameters, TT_MotorParameters, AUTO) + + + +#ifndef PB_CONVERT_DOUBLE_FLOAT +/* On some platforms (such as AVR), double is really float. + * To be able to encode/decode double on these platforms, you need. + * to define PB_CONVERT_DOUBLE_FLOAT in pb.h or compiler command line. + */ +PB_STATIC_ASSERT(sizeof(double) == 8, DOUBLE_MUST_BE_8_BYTES) +#endif + diff --git a/Bingoo/base/msp_ground_management.c b/Bingoo/base/msp_ground_management.c new file mode 100644 index 0000000..993cc8a --- /dev/null +++ b/Bingoo/base/msp_ground_management.c @@ -0,0 +1,135 @@ +/* + * msp_ground_management.c + * + * Created on: 2026年1月15日 + * Author: xsq + */ + +#include "msp_ground_management.h" +#include "msp_strain_gauge.h" +uint8_t ground_management_slave_id = 0x34; + +struct UARTHandler *ground_management_handler; +ground_management_struct *ground_management_value; +DispacherController *ground_management_dispacherController; + +void decode_ground_management(uint8_t *buffer, uint16_t length); + +void ground_management_intialize(struct UARTHandler *Handler) +{ + + ground_management_handler = Handler; + ground_management_handler->Wait_time = 10; //等待10ms 最低不要低于4; + ground_management_dispacherController = Handler->dispacherController; + ground_management_dispacherController->Dispacher_Enable = 1; + //不周期性发送 + ground_management_dispacherController->Add_Dispatcher_List( + ground_management_dispacherController, ground_management_inquiry); + + HardWareErrorController->Add_PCOMHardWare(HardWareErrorController, + "ground_management", 0, ComError_Ground_Management); + LOG("battery_intialize"); +} +void ground_management_intialize_with_slaveid(struct UARTHandler *Handler, + int slave_id) +{ + ground_management_intialize(Handler); + ground_management_slave_id = slave_id; +} +uint16_t dataToSend[10]; +uint16_t g_m_read_count= 10; +uint16_t decoded_ground_management_holdingReg_value[20]; +void ground_management_inquiry() +{ +// void MB_WriteNumHoldingReg(uint8_t *Tx_Buf, uint8_t *TxCount_t, uint8_t _addr, +// uint16_t _reg, uint16_t _num, uint8_t *_databuf) + dataToSend[0] = SWAP_ENDIAN_16((uint16_t ) ground_management_value->K1); + dataToSend[1] = SWAP_ENDIAN_16((uint16_t ) ground_management_value->K2); + dataToSend[2] = SWAP_ENDIAN_16((uint16_t ) ground_management_value->K3); + dataToSend[3] = SWAP_ENDIAN_16((uint16_t ) ground_management_value->K4); + dataToSend[4] = SWAP_ENDIAN_16((uint16_t ) ground_management_value->K5_Default); + dataToSend[5] = SWAP_ENDIAN_16( + (uint16_t ) ground_management_value->MaualControlPower); + dataToSend[6] = SWAP_ENDIAN_16( + (uint16_t ) ground_management_value->MaualPowerState); + + ground_management_value->Time_Out_Period=400; + dataToSend[7] = SWAP_ENDIAN_16( + (uint16_t ) ground_management_value->Time_Out_Period); + + MB_WriteNumHoldingReg(&ground_management_handler->Tx_Buf, + &ground_management_handler->TxCount, ground_management_slave_id, 0, + 8, dataToSend); + + ground_management_handler->AddSendList(ground_management_handler, + ground_management_handler->Tx_Buf, + ground_management_handler->TxCount, OneLineWaitTime, NULL); + + /***********寄存器8写德玛克电机速度*****************************/ + MB_WriteHoldingReg(&ground_management_handler->Tx_Buf, + &ground_management_handler->TxCount, ground_management_slave_id, + 8, GV.GroundManagementValue.DMK_Speed); + ground_management_handler->AddSendList(ground_management_handler, + ground_management_handler->Tx_Buf, + ground_management_handler->TxCount, OneLineWaitTime, NULL); + + /***********寄存器9写德玛克电机状态*****************************/ + MB_WriteHoldingReg(&ground_management_handler->Tx_Buf, + &ground_management_handler->TxCount, ground_management_slave_id, + 9, GV.GroundManagementValue.DMK_WorkState); + ground_management_handler->AddSendList(ground_management_handler, + ground_management_handler->Tx_Buf, + ground_management_handler->TxCount, OneLineWaitTime, NULL); +/********************************************************************/ + + if (ground_management_value->Save_To_Flash == 1) + { + /******************写寄存器7超时时间**************************/ + MB_WriteHoldingReg(&ground_management_handler->Tx_Buf, + &ground_management_handler->TxCount, ground_management_slave_id, + 7, (uint16_t)ground_management_value->Time_Out_Period); + ground_management_handler->AddSendList(ground_management_handler, + ground_management_handler->Tx_Buf, + ground_management_handler->TxCount, OneLineWaitTime, NULL); + + /***************************寄存器10 写入55保存数据*************************************/ + MB_WriteHoldingReg(&ground_management_handler->Tx_Buf, + &ground_management_handler->TxCount, ground_management_slave_id, + 10, 55); + ground_management_handler->AddSendList(ground_management_handler, + ground_management_handler->Tx_Buf, + ground_management_handler->TxCount, OneLineWaitTime, NULL); + /*****************************************************/ + ground_management_value->Save_To_Flash=0; + } + + + MB_ReadHoldingReg(&ground_management_handler->Tx_Buf, &ground_management_handler->TxCount, ground_management_slave_id, 0, + g_m_read_count); + ground_management_handler->AddSendList(ground_management_handler, ground_management_handler->Tx_Buf, + ground_management_handler->TxCount, OneLineWaitTime, decode_ground_management); + +} +void decode_ground_management(uint8_t *buffer, uint16_t length) +{ + // uint8_t data1[length]; + // memcpy(data1, buffer, length); + int decoded_result = MB_Decode_HoldingRegs(buffer, length, g_m_read_count, + &decoded_ground_management_holdingReg_value[0]); + if (decoded_result == 1) + { + + ground_management_value->Read_Time_Out_Period = decoded_ground_management_holdingReg_value[7]; + + + + HardWareErrorController->Set_PCOMHardWare(HardWareErrorController, + "ground_management", 1); + // LOG("Battery_sensor succeeded and the force is %d", *CMCU06_ForceValue); + } + else + { + LOGFF(DL_ERROR, "ground_management decoding failed"); + } +} + diff --git a/Bingoo/base/msp_strain_gauge.c b/Bingoo/base/msp_strain_gauge.c new file mode 100644 index 0000000..c6762d9 --- /dev/null +++ b/Bingoo/base/msp_strain_gauge.c @@ -0,0 +1,137 @@ +/* + * msp_strain_gauge.c + * + * Created on: 2025年11月25日 + * Author: akeguo + */ +#include "msp_strain_gauge.h" +//应变片采集模块 + +Strain_Gauge_Struct *strainGaugeValue; +uint8_t strain_gauge_slave_id = 0x32; //默认为1 +int SAVE_Register9=0; //设置55 保存KD +int SAVE_Register23=0; //设置KD +struct UARTHandler *strain_gauge_handler; + +DispacherController *strain_gauge_dispacherController; +void strain_gauge_loop(); +void decode_strain_gauge_01(uint8_t *buffer, uint16_t length); +void decode_strain_gauge_09(uint8_t *buffer, uint16_t length); +void strain_gauge_intialize(struct UARTHandler *Handler) +{ + //strain_gauge_slave_id=slave_id; + strain_gauge_handler = Handler; + strain_gauge_handler->Wait_time = 10; //等待10ms 最低不要低于4; + strain_gauge_dispacherController = Handler->dispacherController; + strain_gauge_dispacherController->Dispacher_Enable = 1; + //不周期性发送 + strain_gauge_dispacherController->Add_Dispatcher_List( + strain_gauge_dispacherController, strain_gauge_loop);//Dispatcher_List_Add_t bsp com helper.c + + HardWareErrorController->Add_PCOMHardWare(HardWareErrorController, + "strain_gauge", 0, ComError_Strain_Gauge); + + LOG("strain_gauge_intialize"); +} +void strain_gauge_intialize_with_slaveid(struct UARTHandler *Handler, + int slave_id) +{ + strain_gauge_intialize(Handler); + strain_gauge_slave_id = slave_id; +} + +void strain_gauge_loop() +{ + // 必须要初始化 strainGaugeValue + + //读取力 + MB_ReadHoldingReg(&strain_gauge_handler->Tx_Buf, + &strain_gauge_handler->TxCount, strain_gauge_slave_id, 1, 1); //03 command ; read 3 registers 从1 开始 读取1个 + strain_gauge_handler->AddSendList(strain_gauge_handler, + strain_gauge_handler->Tx_Buf, strain_gauge_handler->TxCount, OneLineWaitTime, + decode_strain_gauge_01); + + //推杆控制 + MB_WriteHoldingReg(&strain_gauge_handler->Tx_Buf, + &strain_gauge_handler->TxCount, strain_gauge_slave_id, 0, + strainGaugeValue->MotorControl);//strainGaugeValue->MotorControl 电机控制,=0 停止,=1 前进,=2 后退 + strain_gauge_handler->AddSendList(strain_gauge_handler, + strain_gauge_handler->Tx_Buf, strain_gauge_handler->TxCount, OneLineWaitTime, + NULL); + + /*写寄存器2 3 KD**/ + if(SAVE_Register23==1) + { + /*写寄存器2 K**/ + MB_WriteHoldingReg(&strain_gauge_handler->Tx_Buf, + &strain_gauge_handler->TxCount, strain_gauge_slave_id, 2, + strainGaugeValue->HX711_K); + strain_gauge_handler->AddSendList(strain_gauge_handler, + strain_gauge_handler->Tx_Buf, strain_gauge_handler->TxCount, OneLineWaitTime, + NULL); + /*写寄存器3 D**/ + MB_WriteHoldingReg(&strain_gauge_handler->Tx_Buf, + &strain_gauge_handler->TxCount, strain_gauge_slave_id, 3, + strainGaugeValue->HX711_D); + strain_gauge_handler->AddSendList(strain_gauge_handler, + strain_gauge_handler->Tx_Buf, strain_gauge_handler->TxCount, OneLineWaitTime, + NULL); + SAVE_Register23=0; + } + + /*写寄存器9 设置为55保存KD**/ + if(SAVE_Register9==1) + { + + MB_WriteHoldingReg(&strain_gauge_handler->Tx_Buf, + &strain_gauge_handler->TxCount, strain_gauge_slave_id, 9, + strainGaugeValue->Save); + strain_gauge_handler->AddSendList(strain_gauge_handler, + strain_gauge_handler->Tx_Buf, strain_gauge_handler->TxCount, OneLineWaitTime, + NULL); + SAVE_Register9=0; + } + +} +int16_t decoded_strain_gauge_holdingReg_value[20]; +//读取 00-02的寄存器 +void decode_strain_gauge_01(uint8_t *buffer, uint16_t length) +{ + +// uint8_t data1[length]; +// memcpy(data1, buffer, length); + + int decoded_result = MB_Decode_HoldingRegs(buffer, length, 1, + &decoded_strain_gauge_holdingReg_value[1]); + if (decoded_result == 1) + { + strainGaugeValue->Pressure = decoded_strain_gauge_holdingReg_value[1]; + HardWareErrorController->Set_PCOMHardWare(HardWareErrorController, + "strain_gauge", 1); + // LOG("Battery_sensor succeeded and the force is %d", *CMCU06_ForceValue); + } + else + { + LOGFF(DL_ERROR, "strain_gauge_decoding failed"); + } +} +//读取 09的寄存器 +void decode_strain_gauge_09(uint8_t *buffer, uint16_t length) +{ + +// uint8_t data1[100]; +// memcpy(data1, buffer, length); + int decoded_result = MB_Decode_HoldingRegs(buffer, length, 2, + &decoded_strain_gauge_holdingReg_value[9]); + if (decoded_result == 1) + { + strainGaugeValue->Save = decoded_strain_gauge_holdingReg_value[9]; + HardWareErrorController->Set_PCOMHardWare(HardWareErrorController, + "strain_gauge", 1); + // LOG("Battery_sensor succeeded and the force is %d", *CMCU06_ForceValue); + } + else + { + LOGFF(DL_ERROR, "strain_gauge_decoding failed"); + } +} diff --git a/Bingoo/base/paint_gun_action.c b/Bingoo/base/paint_gun_action.c new file mode 100644 index 0000000..e68d46f --- /dev/null +++ b/Bingoo/base/paint_gun_action.c @@ -0,0 +1,102 @@ +/* + * paint_gun_action.c + * + * Created on: 2025年8月7日 + * Author: xsq + */ +#include "paint_gun_action.h" +#include "Handset_Status_Setting.h" +#include "msp_strain_gauge.h" + +#include "fsm_state.h" +#include "BHBF_ROBOT.h" +transition_t current_paintgun_state; /*transition_t 成员是 指针的 transition_state_t */ + +transition_state_t paintgun_on_state={PaintGun_ON_Enter,PaintGun_ON_Do,NULL}; /* State 成员,它会被默认初始化为 0 */ +transition_state_t paintgun_off_state={PaintGun_OFF_Enter,PaintGun_OFF_Do,NULL}; + +char Paint_Gun_ButtonReset_Flag = 0; //喷枪开启 1yes + +/* 喷枪控制 */ +void PaintGun_ON_Do() +{ + GF_BSP_GPIO_SetIO(PaintGun_IO_CTL, K_ON_PaintGun);//0开 +} + +void PaintGun_OFF_Do() +{ + GF_BSP_GPIO_SetIO(PaintGun_IO_CTL, K_OFF_PaintGun);//1关 +} + +void PaintGun_ON_Enter() +{ + +} +void PaintGun_ON_Exit() +{ + +} +void PaintGun_OFF_Enter() +{ + + +} +void PaintGun_OFF_Exit() +{ + +} + +IO_State curr_io_state; +//无压力传感器数值下控制推杆函数 +void PaintGun_Contronl() +{ + GV.Now_press=strainGaugeValue->Pressure; + curr_io_state = GetIOState(); + if(curr_io_state==IO_STATE_RISE) + { + strainGaugeValue->MotorControl=1; + + } + else if(curr_io_state==IO_STATE_DESCEND) + { + strainGaugeValue->MotorControl=2; + + } + else + { + strainGaugeValue->MotorControl=0; + } +} + + +//有压力传感器数值下控制推杆函数 +void PaintGun_Contronl_Press() +{ + GV.Now_press=strainGaugeValue->Pressure; + curr_io_state = GetIOState(); + if(curr_io_state==IO_STATE_RISE) + { + +// if(strainGaugeValue->Pressure>(-GV.PV.Robot_Press_Set)) +// { +// strainGaugeValue->MotorControl=1; +// } + strainGaugeValue->MotorControl=1; + } + else if(curr_io_state==IO_STATE_DESCEND) + { + + if(strainGaugeValue->Pressure<=(GV.PV.Robot_Press_Set*10)) + { + strainGaugeValue->MotorControl=2; + } + else + { + strainGaugeValue->MotorControl=0; + } + } + else + { + strainGaugeValue->MotorControl=0; + } +} diff --git a/Bingoo/base/pb_common.c b/Bingoo/base/pb_common.c new file mode 100644 index 0000000..6aee76b --- /dev/null +++ b/Bingoo/base/pb_common.c @@ -0,0 +1,388 @@ +/* pb_common.c: Common support functions for pb_encode.c and pb_decode.c. + * + * 2014 Petteri Aimonen + */ + +#include "pb_common.h" + +static bool load_descriptor_values(pb_field_iter_t *iter) +{ + uint32_t word0; + uint32_t data_offset; + int_least8_t size_offset; + + if (iter->index >= iter->descriptor->field_count) + return false; + + word0 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); + iter->type = (pb_type_t)((word0 >> 8) & 0xFF); + + switch(word0 & 3) + { + case 0: { + /* 1-word format */ + iter->array_size = 1; + iter->tag = (pb_size_t)((word0 >> 2) & 0x3F); + size_offset = (int_least8_t)((word0 >> 24) & 0x0F); + data_offset = (word0 >> 16) & 0xFF; + iter->data_size = (pb_size_t)((word0 >> 28) & 0x0F); + break; + } + + case 1: { + /* 2-word format */ + uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); + + iter->array_size = (pb_size_t)((word0 >> 16) & 0x0FFF); + iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 28) << 6)); + size_offset = (int_least8_t)((word0 >> 28) & 0x0F); + data_offset = word1 & 0xFFFF; + iter->data_size = (pb_size_t)((word1 >> 16) & 0x0FFF); + break; + } + + case 2: { + /* 4-word format */ + uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); + uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]); + uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]); + + iter->array_size = (pb_size_t)(word0 >> 16); + iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 8) << 6)); + size_offset = (int_least8_t)(word1 & 0xFF); + data_offset = word2; + iter->data_size = (pb_size_t)word3; + break; + } + + default: { + /* 8-word format */ + uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); + uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]); + uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]); + uint32_t word4 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 4]); + + iter->array_size = (pb_size_t)word4; + iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 8) << 6)); + size_offset = (int_least8_t)(word1 & 0xFF); + data_offset = word2; + iter->data_size = (pb_size_t)word3; + break; + } + } + + if (!iter->message) + { + /* Avoid doing arithmetic on null pointers, it is undefined */ + iter->pField = NULL; + iter->pSize = NULL; + } + else + { + iter->pField = (char*)iter->message + data_offset; + + if (size_offset) + { + iter->pSize = (char*)iter->pField - size_offset; + } + else if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED && + (PB_ATYPE(iter->type) == PB_ATYPE_STATIC || + PB_ATYPE(iter->type) == PB_ATYPE_POINTER)) + { + /* Fixed count array */ + iter->pSize = &iter->array_size; + } + else + { + iter->pSize = NULL; + } + + if (PB_ATYPE(iter->type) == PB_ATYPE_POINTER && iter->pField != NULL) + { + iter->pData = *(void**)iter->pField; + } + else + { + iter->pData = iter->pField; + } + } + + if (PB_LTYPE_IS_SUBMSG(iter->type)) + { + iter->submsg_desc = iter->descriptor->submsg_info[iter->submessage_index]; + } + else + { + iter->submsg_desc = NULL; + } + + return true; +} + +static void advance_iterator(pb_field_iter_t *iter) +{ + iter->index++; + + if (iter->index >= iter->descriptor->field_count) + { + /* Restart */ + iter->index = 0; + iter->field_info_index = 0; + iter->submessage_index = 0; + iter->required_field_index = 0; + } + else + { + /* Increment indexes based on previous field type. + * All field info formats have the following fields: + * - lowest 2 bits tell the amount of words in the descriptor (2^n words) + * - bits 2..7 give the lowest bits of tag number. + * - bits 8..15 give the field type. + */ + uint32_t prev_descriptor = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); + pb_type_t prev_type = (prev_descriptor >> 8) & 0xFF; + pb_size_t descriptor_len = (pb_size_t)(1 << (prev_descriptor & 3)); + + /* Add to fields. + * The cast to pb_size_t is needed to avoid -Wconversion warning. + * Because the data is is constants from generator, there is no danger of overflow. + */ + iter->field_info_index = (pb_size_t)(iter->field_info_index + descriptor_len); + iter->required_field_index = (pb_size_t)(iter->required_field_index + (PB_HTYPE(prev_type) == PB_HTYPE_REQUIRED)); + iter->submessage_index = (pb_size_t)(iter->submessage_index + PB_LTYPE_IS_SUBMSG(prev_type)); + } +} + +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message) +{ + memset(iter, 0, sizeof(*iter)); + + iter->descriptor = desc; + iter->message = message; + + return load_descriptor_values(iter); +} + +bool pb_field_iter_begin_extension(pb_field_iter_t *iter, pb_extension_t *extension) +{ + const pb_msgdesc_t *msg = (const pb_msgdesc_t*)extension->type->arg; + bool status; + + uint32_t word0 = PB_PROGMEM_READU32(msg->field_info[0]); + if (PB_ATYPE(word0 >> 8) == PB_ATYPE_POINTER) + { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + status = pb_field_iter_begin(iter, msg, &extension->dest); + } + else + { + status = pb_field_iter_begin(iter, msg, extension->dest); + } + + iter->pSize = &extension->found; + return status; +} + +bool pb_field_iter_next(pb_field_iter_t *iter) +{ + advance_iterator(iter); + (void)load_descriptor_values(iter); + return iter->index != 0; +} + +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) +{ + if (iter->tag == tag) + { + return true; /* Nothing to do, correct field already. */ + } + else if (tag > iter->descriptor->largest_tag) + { + return false; + } + else + { + pb_size_t start = iter->index; + uint32_t fieldinfo; + + if (tag < iter->tag) + { + /* Fields are in tag number order, so we know that tag is between + * 0 and our start position. Setting index to end forces + * advance_iterator() call below to restart from beginning. */ + iter->index = iter->descriptor->field_count; + } + + do + { + /* Advance iterator but don't load values yet */ + advance_iterator(iter); + + /* Do fast check for tag number match */ + fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); + + if (((fieldinfo >> 2) & 0x3F) == (tag & 0x3F)) + { + /* Good candidate, check further */ + (void)load_descriptor_values(iter); + + if (iter->tag == tag && + PB_LTYPE(iter->type) != PB_LTYPE_EXTENSION) + { + /* Found it */ + return true; + } + } + } while (iter->index != start); + + /* Searched all the way back to start, and found nothing. */ + (void)load_descriptor_values(iter); + return false; + } +} + +bool pb_field_iter_find_extension(pb_field_iter_t *iter) +{ + if (PB_LTYPE(iter->type) == PB_LTYPE_EXTENSION) + { + return true; + } + else + { + pb_size_t start = iter->index; + uint32_t fieldinfo; + + do + { + /* Advance iterator but don't load values yet */ + advance_iterator(iter); + + /* Do fast check for field type */ + fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); + + if (PB_LTYPE((fieldinfo >> 8) & 0xFF) == PB_LTYPE_EXTENSION) + { + return load_descriptor_values(iter); + } + } while (iter->index != start); + + /* Searched all the way back to start, and found nothing. */ + (void)load_descriptor_values(iter); + return false; + } +} + +static void *pb_const_cast(const void *p) +{ + /* Note: this casts away const, in order to use the common field iterator + * logic for both encoding and decoding. The cast is done using union + * to avoid spurious compiler warnings. */ + union { + void *p1; + const void *p2; + } t; + t.p2 = p; + return t.p1; +} + +bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message) +{ + return pb_field_iter_begin(iter, desc, pb_const_cast(message)); +} + +bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension) +{ + return pb_field_iter_begin_extension(iter, (pb_extension_t*)pb_const_cast(extension)); +} + +bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field) +{ + if (field->data_size == sizeof(pb_callback_t)) + { + pb_callback_t *pCallback = (pb_callback_t*)field->pData; + + if (pCallback != NULL) + { + if (istream != NULL && pCallback->funcs.decode != NULL) + { + return pCallback->funcs.decode(istream, field, &pCallback->arg); + } + + if (ostream != NULL && pCallback->funcs.encode != NULL) + { + return pCallback->funcs.encode(ostream, field, &pCallback->arg); + } + } + } + + return true; /* Success, but didn't do anything */ + +} + +#ifdef PB_VALIDATE_UTF8 + +/* This function checks whether a string is valid UTF-8 text. + * + * Algorithm is adapted from https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c + * Original copyright: Markus Kuhn 2005-03-30 + * Licensed under "Short code license", which allows use under MIT license or + * any compatible with it. + */ + +bool pb_validate_utf8(const char *str) +{ + const pb_byte_t *s = (const pb_byte_t*)str; + while (*s) + { + if (*s < 0x80) + { + /* 0xxxxxxx */ + s++; + } + else if ((s[0] & 0xe0) == 0xc0) + { + /* 110XXXXx 10xxxxxx */ + if ((s[1] & 0xc0) != 0x80 || + (s[0] & 0xfe) == 0xc0) /* overlong? */ + return false; + else + s += 2; + } + else if ((s[0] & 0xf0) == 0xe0) + { + /* 1110XXXX 10Xxxxxx 10xxxxxx */ + if ((s[1] & 0xc0) != 0x80 || + (s[2] & 0xc0) != 0x80 || + (s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || /* overlong? */ + (s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || /* surrogate? */ + (s[0] == 0xef && s[1] == 0xbf && + (s[2] & 0xfe) == 0xbe)) /* U+FFFE or U+FFFF? */ + return false; + else + s += 3; + } + else if ((s[0] & 0xf8) == 0xf0) + { + /* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */ + if ((s[1] & 0xc0) != 0x80 || + (s[2] & 0xc0) != 0x80 || + (s[3] & 0xc0) != 0x80 || + (s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || /* overlong? */ + (s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) /* > U+10FFFF? */ + return false; + else + s += 4; + } + else + { + return false; + } + } + + return true; +} + +#endif + diff --git a/Bingoo/base/pb_decode.c b/Bingoo/base/pb_decode.c new file mode 100644 index 0000000..788998e --- /dev/null +++ b/Bingoo/base/pb_decode.c @@ -0,0 +1,1727 @@ +/* pb_decode.c -- decode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +#include "pb.h" +#include "pb_decode.h" +#include "pb_common.h" + +/************************************** + * Declarations internal to this file * + **************************************/ + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof); +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size); +static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field); +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field); +static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field); +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field); +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field); +static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type); +static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_extension_t *extension); +static bool pb_field_set_to_default(pb_field_iter_t *field); +static bool pb_message_set_to_defaults(pb_field_iter_t *iter); +static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_skip_varint(pb_istream_t *stream); +static bool checkreturn pb_skip_string(pb_istream_t *stream); + +#ifdef PB_ENABLE_MALLOC +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size); +static void initialize_pointer_field(void *pItem, pb_field_iter_t *field); +static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *field); +static void pb_release_single_field(pb_field_iter_t *field); +#endif + +#ifdef PB_WITHOUT_64BIT +#define pb_int64_t int32_t +#define pb_uint64_t uint32_t +#else +#define pb_int64_t int64_t +#define pb_uint64_t uint64_t +#endif + +typedef struct { + uint32_t bitfield[(PB_MAX_REQUIRED_FIELDS + 31) / 32]; +} pb_fields_seen_t; + +/******************************* + * pb_istream_t implementation * + *******************************/ + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ + const pb_byte_t *source = (const pb_byte_t*)stream->state; + stream->state = (pb_byte_t*)stream->state + count; + + if (buf != NULL) + { + memcpy(buf, source, count * sizeof(pb_byte_t)); + } + + return true; +} + +bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ + if (count == 0) + return true; + +#ifndef PB_BUFFER_ONLY + if (buf == NULL && stream->callback != buf_read) + { + /* Skip input bytes */ + pb_byte_t tmp[16]; + while (count > 16) + { + if (!pb_read(stream, tmp, 16)) + return false; + + count -= 16; + } + + return pb_read(stream, tmp, count); + } +#endif + + if (stream->bytes_left < count) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!buf_read(stream, buf, count)) + return false; +#endif + + if (stream->bytes_left < count) + stream->bytes_left = 0; + else + stream->bytes_left -= count; + + return true; +} + +/* Read a single byte from input stream. buf may not be NULL. + * This is an optimization for the varint decoding. */ +static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf) +{ + if (stream->bytes_left == 0) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, 1)) + PB_RETURN_ERROR(stream, "io error"); +#else + *buf = *(const pb_byte_t*)stream->state; + stream->state = (pb_byte_t*)stream->state + 1; +#endif + + stream->bytes_left--; + + return true; +} + +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t msglen) +{ + pb_istream_t stream; + /* Cast away the const from buf without a compiler error. We are + * careful to use it only in a const manner in the callbacks. + */ + union { + void *state; + const void *c_state; + } state; +#ifdef PB_BUFFER_ONLY + stream.callback = NULL; +#else + stream.callback = &buf_read; +#endif + state.c_state = buf; + stream.state = state.state; + stream.bytes_left = msglen; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +/******************** + * Helper functions * + ********************/ + +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof) +{ + pb_byte_t byte; + uint32_t result; + + if (!pb_readbyte(stream, &byte)) + { + if (stream->bytes_left == 0) + { + if (eof) + { + *eof = true; + } + } + + return false; + } + + if ((byte & 0x80) == 0) + { + /* Quick case, 1 byte value */ + result = byte; + } + else + { + /* Multibyte case */ + uint_fast8_t bitpos = 7; + result = byte & 0x7F; + + do + { + if (!pb_readbyte(stream, &byte)) + return false; + + if (bitpos >= 32) + { + /* Note: The varint could have trailing 0x80 bytes, or 0xFF for negative. */ + pb_byte_t sign_extension = (bitpos < 63) ? 0xFF : 0x01; + bool valid_extension = ((byte & 0x7F) == 0x00 || + ((result >> 31) != 0 && byte == sign_extension)); + + if (bitpos >= 64 || !valid_extension) + { + PB_RETURN_ERROR(stream, "varint overflow"); + } + } + else if (bitpos == 28) + { + if ((byte & 0x70) != 0 && (byte & 0x78) != 0x78) + { + PB_RETURN_ERROR(stream, "varint overflow"); + } + result |= (uint32_t)(byte & 0x0F) << bitpos; + } + else + { + result |= (uint32_t)(byte & 0x7F) << bitpos; + } + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + } + + *dest = result; + return true; +} + +bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) +{ + return pb_decode_varint32_eof(stream, dest, NULL); +} + +#ifndef PB_WITHOUT_64BIT +bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest) +{ + pb_byte_t byte; + uint_fast8_t bitpos = 0; + uint64_t result = 0; + + do + { + if (!pb_readbyte(stream, &byte)) + return false; + + if (bitpos >= 63 && (byte & 0xFE) != 0) + PB_RETURN_ERROR(stream, "varint overflow"); + + result |= (uint64_t)(byte & 0x7F) << bitpos; + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + *dest = result; + return true; +} +#endif + +bool checkreturn pb_skip_varint(pb_istream_t *stream) +{ + pb_byte_t byte; + do + { + if (!pb_read(stream, &byte, 1)) + return false; + } while (byte & 0x80); + return true; +} + +bool checkreturn pb_skip_string(pb_istream_t *stream) +{ + uint32_t length; + if (!pb_decode_varint32(stream, &length)) + return false; + + if ((size_t)length != length) + { + PB_RETURN_ERROR(stream, "size too large"); + } + + return pb_read(stream, NULL, (size_t)length); +} + +bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof) +{ + uint32_t temp; + *eof = false; + *wire_type = (pb_wire_type_t) 0; + *tag = 0; + + if (!pb_decode_varint32_eof(stream, &temp, eof)) + { + return false; + } + + *tag = temp >> 3; + *wire_type = (pb_wire_type_t)(temp & 7); + return true; +} + +bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type) +{ + switch (wire_type) + { + case PB_WT_VARINT: return pb_skip_varint(stream); + case PB_WT_64BIT: return pb_read(stream, NULL, 8); + case PB_WT_STRING: return pb_skip_string(stream); + case PB_WT_32BIT: return pb_read(stream, NULL, 4); + default: PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Read a raw value to buffer, for the purpose of passing it to callback as + * a substream. Size is maximum size on call, and actual size on return. + */ +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size) +{ + size_t max_size = *size; + switch (wire_type) + { + case PB_WT_VARINT: + *size = 0; + do + { + (*size)++; + if (*size > max_size) + PB_RETURN_ERROR(stream, "varint overflow"); + + if (!pb_read(stream, buf, 1)) + return false; + } while (*buf++ & 0x80); + return true; + + case PB_WT_64BIT: + *size = 8; + return pb_read(stream, buf, 8); + + case PB_WT_32BIT: + *size = 4; + return pb_read(stream, buf, 4); + + case PB_WT_STRING: + /* Calling read_raw_value with a PB_WT_STRING is an error. + * Explicitly handle this case and fallthrough to default to avoid + * compiler warnings. + */ + + default: PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Decode string length from stream and return a substream with limited length. + * Remember to close the substream using pb_close_string_substream(). + */ +bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + uint32_t size; + if (!pb_decode_varint32(stream, &size)) + return false; + + *substream = *stream; + if (substream->bytes_left < size) + PB_RETURN_ERROR(stream, "parent stream too short"); + + substream->bytes_left = (size_t)size; + stream->bytes_left -= (size_t)size; + return true; +} + +bool checkreturn pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + if (substream->bytes_left) { + if (!pb_read(substream, NULL, substream->bytes_left)) + return false; + } + + stream->state = substream->state; + +#ifndef PB_NO_ERRMSG + stream->errmsg = substream->errmsg; +#endif + return true; +} + +/************************* + * Decode a single field * + *************************/ + +static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field) +{ + switch (PB_LTYPE(field->type)) + { + case PB_LTYPE_BOOL: + if (wire_type != PB_WT_VARINT && wire_type != PB_WT_PACKED) + PB_RETURN_ERROR(stream, "wrong wire type"); + + return pb_dec_bool(stream, field); + + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + if (wire_type != PB_WT_VARINT && wire_type != PB_WT_PACKED) + PB_RETURN_ERROR(stream, "wrong wire type"); + + return pb_dec_varint(stream, field); + + case PB_LTYPE_FIXED32: + if (wire_type != PB_WT_32BIT && wire_type != PB_WT_PACKED) + PB_RETURN_ERROR(stream, "wrong wire type"); + + return pb_decode_fixed32(stream, field->pData); + + case PB_LTYPE_FIXED64: + if (wire_type != PB_WT_64BIT && wire_type != PB_WT_PACKED) + PB_RETURN_ERROR(stream, "wrong wire type"); + +#ifdef PB_CONVERT_DOUBLE_FLOAT + if (field->data_size == sizeof(float)) + { + return pb_decode_double_as_float(stream, (float*)field->pData); + } +#endif + +#ifdef PB_WITHOUT_64BIT + PB_RETURN_ERROR(stream, "invalid data_size"); +#else + return pb_decode_fixed64(stream, field->pData); +#endif + + case PB_LTYPE_BYTES: + if (wire_type != PB_WT_STRING) + PB_RETURN_ERROR(stream, "wrong wire type"); + + return pb_dec_bytes(stream, field); + + case PB_LTYPE_STRING: + if (wire_type != PB_WT_STRING) + PB_RETURN_ERROR(stream, "wrong wire type"); + + return pb_dec_string(stream, field); + + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_SUBMSG_W_CB: + if (wire_type != PB_WT_STRING) + PB_RETURN_ERROR(stream, "wrong wire type"); + + return pb_dec_submessage(stream, field); + + case PB_LTYPE_FIXED_LENGTH_BYTES: + if (wire_type != PB_WT_STRING) + PB_RETURN_ERROR(stream, "wrong wire type"); + + return pb_dec_fixed_length_bytes(stream, field); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field) +{ + switch (PB_HTYPE(field->type)) + { + case PB_HTYPE_REQUIRED: + return decode_basic_field(stream, wire_type, field); + + case PB_HTYPE_OPTIONAL: + if (field->pSize != NULL) + *(bool*)field->pSize = true; + return decode_basic_field(stream, wire_type, field); + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Packed array */ + bool status = true; + pb_istream_t substream; + pb_size_t *size = (pb_size_t*)field->pSize; + field->pData = (char*)field->pField + field->data_size * (*size); + + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left > 0 && *size < field->array_size) + { + if (!decode_basic_field(&substream, PB_WT_PACKED, field)) + { + status = false; + break; + } + (*size)++; + field->pData = (char*)field->pData + field->data_size; + } + + if (substream.bytes_left != 0) + PB_RETURN_ERROR(stream, "array overflow"); + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } + else + { + /* Repeated field */ + pb_size_t *size = (pb_size_t*)field->pSize; + field->pData = (char*)field->pField + field->data_size * (*size); + + if ((*size)++ >= field->array_size) + PB_RETURN_ERROR(stream, "array overflow"); + + return decode_basic_field(stream, wire_type, field); + } + + case PB_HTYPE_ONEOF: + if (PB_LTYPE_IS_SUBMSG(field->type) && + *(pb_size_t*)field->pSize != field->tag) + { + /* We memset to zero so that any callbacks are set to NULL. + * This is because the callbacks might otherwise have values + * from some other union field. + * If callbacks are needed inside oneof field, use .proto + * option submsg_callback to have a separate callback function + * that can set the fields before submessage is decoded. + * pb_dec_submessage() will set any default values. */ + memset(field->pData, 0, (size_t)field->data_size); + + /* Set default values for the submessage fields. */ + if (field->submsg_desc->default_value != NULL || + field->submsg_desc->field_callback != NULL || + field->submsg_desc->submsg_info[0] != NULL) + { + pb_field_iter_t submsg_iter; + if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, field->pData)) + { + if (!pb_message_set_to_defaults(&submsg_iter)) + PB_RETURN_ERROR(stream, "failed to set defaults"); + } + } + } + *(pb_size_t*)field->pSize = field->tag; + + return decode_basic_field(stream, wire_type, field); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +#ifdef PB_ENABLE_MALLOC +/* Allocate storage for the field and store the pointer at iter->pData. + * array_size is the number of entries to reserve in an array. + * Zero size is not allowed, use pb_free() for releasing. + */ +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size) +{ + void *ptr = *(void**)pData; + + if (data_size == 0 || array_size == 0) + PB_RETURN_ERROR(stream, "invalid size"); + +#ifdef __AVR__ + /* Workaround for AVR libc bug 53284: http://savannah.nongnu.org/bugs/?53284 + * Realloc to size of 1 byte can cause corruption of the malloc structures. + */ + if (data_size == 1 && array_size == 1) + { + data_size = 2; + } +#endif + + /* Check for multiplication overflows. + * This code avoids the costly division if the sizes are small enough. + * Multiplication is safe as long as only half of bits are set + * in either multiplicand. + */ + { + const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4); + if (data_size >= check_limit || array_size >= check_limit) + { + const size_t size_max = (size_t)-1; + if (size_max / array_size < data_size) + { + PB_RETURN_ERROR(stream, "size too large"); + } + } + } + + /* Allocate new or expand previous allocation */ + /* Note: on failure the old pointer will remain in the structure, + * the message must be freed by caller also on error return. */ + ptr = pb_realloc(ptr, array_size * data_size); + if (ptr == NULL) + PB_RETURN_ERROR(stream, "realloc failed"); + + *(void**)pData = ptr; + return true; +} + +/* Clear a newly allocated item in case it contains a pointer, or is a submessage. */ +static void initialize_pointer_field(void *pItem, pb_field_iter_t *field) +{ + if (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES) + { + *(void**)pItem = NULL; + } + else if (PB_LTYPE_IS_SUBMSG(field->type)) + { + /* We memset to zero so that any callbacks are set to NULL. + * Default values will be set by pb_dec_submessage(). */ + memset(pItem, 0, field->data_size); + } +} +#endif + +static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field) +{ +#ifndef PB_ENABLE_MALLOC + PB_UNUSED(wire_type); + PB_UNUSED(field); + PB_RETURN_ERROR(stream, "no malloc support"); +#else + switch (PB_HTYPE(field->type)) + { + case PB_HTYPE_REQUIRED: + case PB_HTYPE_OPTIONAL: + case PB_HTYPE_ONEOF: + if (PB_LTYPE_IS_SUBMSG(field->type) && *(void**)field->pField != NULL) + { + /* Duplicate field, have to release the old allocation first. */ + /* FIXME: Does this work correctly for oneofs? */ + pb_release_single_field(field); + } + + if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF) + { + *(pb_size_t*)field->pSize = field->tag; + } + + if (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES) + { + /* pb_dec_string and pb_dec_bytes handle allocation themselves */ + field->pData = field->pField; + return decode_basic_field(stream, wire_type, field); + } + else + { + if (!allocate_field(stream, field->pField, field->data_size, 1)) + return false; + + field->pData = *(void**)field->pField; + initialize_pointer_field(field->pData, field); + return decode_basic_field(stream, wire_type, field); + } + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Packed array, multiple items come in at once. */ + bool status = true; + pb_size_t *size = (pb_size_t*)field->pSize; + size_t allocated_size = *size; + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left) + { + if (*size == PB_SIZE_MAX) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = "too many array entries"; +#endif + status = false; + break; + } + + if ((size_t)*size + 1 > allocated_size) + { + /* Allocate more storage. This tries to guess the + * number of remaining entries. Round the division + * upwards. */ + size_t remain = (substream.bytes_left - 1) / field->data_size + 1; + if (remain < PB_SIZE_MAX - allocated_size) + allocated_size += remain; + else + allocated_size += 1; + + if (!allocate_field(&substream, field->pField, field->data_size, allocated_size)) + { + status = false; + break; + } + } + + /* Decode the array entry */ + field->pData = *(char**)field->pField + field->data_size * (*size); + if (field->pData == NULL) + { + /* Shouldn't happen, but satisfies static analyzers */ + status = false; + break; + } + initialize_pointer_field(field->pData, field); + if (!decode_basic_field(&substream, PB_WT_PACKED, field)) + { + status = false; + break; + } + + (*size)++; + } + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } + else + { + /* Normal repeated field, i.e. only one item at a time. */ + pb_size_t *size = (pb_size_t*)field->pSize; + + if (*size == PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "too many array entries"); + + if (!allocate_field(stream, field->pField, field->data_size, (size_t)(*size + 1))) + return false; + + field->pData = *(char**)field->pField + field->data_size * (*size); + (*size)++; + initialize_pointer_field(field->pData, field); + return decode_basic_field(stream, wire_type, field); + } + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +#endif +} + +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field) +{ + if (!field->descriptor->field_callback) + return pb_skip_field(stream, wire_type); + + if (wire_type == PB_WT_STRING) + { + pb_istream_t substream; + size_t prev_bytes_left; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + do + { + prev_bytes_left = substream.bytes_left; + if (!field->descriptor->field_callback(&substream, NULL, field)) + { + PB_SET_ERROR(stream, substream.errmsg ? substream.errmsg : "callback failed"); + return false; + } + } while (substream.bytes_left > 0 && substream.bytes_left < prev_bytes_left); + + if (!pb_close_string_substream(stream, &substream)) + return false; + + return true; + } + else + { + /* Copy the single scalar value to stack. + * This is required so that we can limit the stream length, + * which in turn allows to use same callback for packed and + * not-packed fields. */ + pb_istream_t substream; + pb_byte_t buffer[10]; + size_t size = sizeof(buffer); + + if (!read_raw_value(stream, wire_type, buffer, &size)) + return false; + substream = pb_istream_from_buffer(buffer, size); + + return field->descriptor->field_callback(&substream, NULL, field); + } +} + +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field) +{ +#ifdef PB_ENABLE_MALLOC + /* When decoding an oneof field, check if there is old data that must be + * released first. */ + if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF) + { + if (!pb_release_union_field(stream, field)) + return false; + } +#endif + + switch (PB_ATYPE(field->type)) + { + case PB_ATYPE_STATIC: + return decode_static_field(stream, wire_type, field); + + case PB_ATYPE_POINTER: + return decode_pointer_field(stream, wire_type, field); + + case PB_ATYPE_CALLBACK: + return decode_callback_field(stream, wire_type, field); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +/* Default handler for extension fields. Expects to have a pb_msgdesc_t + * pointer in the extension->type->arg field, pointing to a message with + * only one field in it. */ +static bool checkreturn default_extension_decoder(pb_istream_t *stream, + pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type) +{ + pb_field_iter_t iter; + + if (!pb_field_iter_begin_extension(&iter, extension)) + PB_RETURN_ERROR(stream, "invalid extension"); + + if (iter.tag != tag || !iter.message) + return true; + + extension->found = true; + return decode_field(stream, wire_type, &iter); +} + +/* Try to decode an unknown field as an extension field. Tries each extension + * decoder in turn, until one of them handles the field or loop ends. */ +static bool checkreturn decode_extension(pb_istream_t *stream, + uint32_t tag, pb_wire_type_t wire_type, pb_extension_t *extension) +{ + size_t pos = stream->bytes_left; + + while (extension != NULL && pos == stream->bytes_left) + { + bool status; + if (extension->type->decode) + status = extension->type->decode(stream, extension, tag, wire_type); + else + status = default_extension_decoder(stream, extension, tag, wire_type); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/* Initialize message fields to default values, recursively */ +static bool pb_field_set_to_default(pb_field_iter_t *field) +{ + pb_type_t type; + type = field->type; + + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + pb_extension_t *ext = *(pb_extension_t* const *)field->pData; + while (ext != NULL) + { + pb_field_iter_t ext_iter; + if (pb_field_iter_begin_extension(&ext_iter, ext)) + { + ext->found = false; + if (!pb_message_set_to_defaults(&ext_iter)) + return false; + } + ext = ext->next; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { + bool init_data = true; + if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->pSize != NULL) + { + /* Set has_field to false. Still initialize the optional field + * itself also. */ + *(bool*)field->pSize = false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + /* REPEATED: Set array count to 0, no need to initialize contents. + ONEOF: Set which_field to 0. */ + *(pb_size_t*)field->pSize = 0; + init_data = false; + } + + if (init_data) + { + if (PB_LTYPE_IS_SUBMSG(field->type) && + (field->submsg_desc->default_value != NULL || + field->submsg_desc->field_callback != NULL || + field->submsg_desc->submsg_info[0] != NULL)) + { + /* Initialize submessage to defaults. + * Only needed if it has default values + * or callback/submessage fields. */ + pb_field_iter_t submsg_iter; + if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, field->pData)) + { + if (!pb_message_set_to_defaults(&submsg_iter)) + return false; + } + } + else + { + /* Initialize to zeros */ + memset(field->pData, 0, (size_t)field->data_size); + } + } + } + else if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + /* Initialize the pointer to NULL. */ + *(void**)field->pField = NULL; + + /* Initialize array count to 0. */ + if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + *(pb_size_t*)field->pSize = 0; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK) + { + /* Don't overwrite callback */ + } + + return true; +} + +static bool pb_message_set_to_defaults(pb_field_iter_t *iter) +{ + pb_istream_t defstream = PB_ISTREAM_EMPTY; + uint32_t tag = 0; + pb_wire_type_t wire_type = PB_WT_VARINT; + bool eof; + + if (iter->descriptor->default_value) + { + defstream = pb_istream_from_buffer(iter->descriptor->default_value, (size_t)-1); + if (!pb_decode_tag(&defstream, &wire_type, &tag, &eof)) + return false; + } + + do + { + if (!pb_field_set_to_default(iter)) + return false; + + if (tag != 0 && iter->tag == tag) + { + /* We have a default value for this field in the defstream */ + if (!decode_field(&defstream, wire_type, iter)) + return false; + if (!pb_decode_tag(&defstream, &wire_type, &tag, &eof)) + return false; + + if (iter->pSize) + *(bool*)iter->pSize = false; + } + } while (pb_field_iter_next(iter)); + + return true; +} + +/********************* + * Decode all fields * + *********************/ + +static bool checkreturn pb_decode_inner(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags) +{ + uint32_t extension_range_start = 0; + pb_extension_t *extensions = NULL; + + /* 'fixed_count_field' and 'fixed_count_size' track position of a repeated fixed + * count field. This can only handle _one_ repeated fixed count field that + * is unpacked and unordered among other (non repeated fixed count) fields. + */ + pb_size_t fixed_count_field = PB_SIZE_MAX; + pb_size_t fixed_count_size = 0; + pb_size_t fixed_count_total_size = 0; + + pb_fields_seen_t fields_seen = {{0, 0}}; + const uint32_t allbits = ~(uint32_t)0; + pb_field_iter_t iter; + + if (pb_field_iter_begin(&iter, fields, dest_struct)) + { + if ((flags & PB_DECODE_NOINIT) == 0) + { + if (!pb_message_set_to_defaults(&iter)) + PB_RETURN_ERROR(stream, "failed to set defaults"); + } + } + + while (stream->bytes_left) + { + uint32_t tag; + pb_wire_type_t wire_type; + bool eof; + + if (!pb_decode_tag(stream, &wire_type, &tag, &eof)) + { + if (eof) + break; + else + return false; + } + + if (tag == 0) + { + if (flags & PB_DECODE_NULLTERMINATED) + { + break; + } + else + { + PB_RETURN_ERROR(stream, "zero tag"); + } + } + + if (!pb_field_iter_find(&iter, tag) || PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION) + { + /* No match found, check if it matches an extension. */ + if (extension_range_start == 0) + { + if (pb_field_iter_find_extension(&iter)) + { + extensions = *(pb_extension_t* const *)iter.pData; + extension_range_start = iter.tag; + } + + if (!extensions) + { + extension_range_start = (uint32_t)-1; + } + } + + if (tag >= extension_range_start) + { + size_t pos = stream->bytes_left; + + if (!decode_extension(stream, tag, wire_type, extensions)) + return false; + + if (pos != stream->bytes_left) + { + /* The field was handled */ + continue; + } + } + + /* No match found, skip data */ + if (!pb_skip_field(stream, wire_type)) + return false; + continue; + } + + /* If a repeated fixed count field was found, get size from + * 'fixed_count_field' as there is no counter contained in the struct. + */ + if (PB_HTYPE(iter.type) == PB_HTYPE_REPEATED && iter.pSize == &iter.array_size) + { + if (fixed_count_field != iter.index) { + /* If the new fixed count field does not match the previous one, + * check that the previous one is NULL or that it finished + * receiving all the expected data. + */ + if (fixed_count_field != PB_SIZE_MAX && + fixed_count_size != fixed_count_total_size) + { + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + } + + fixed_count_field = iter.index; + fixed_count_size = 0; + fixed_count_total_size = iter.array_size; + } + + iter.pSize = &fixed_count_size; + } + + if (PB_HTYPE(iter.type) == PB_HTYPE_REQUIRED + && iter.required_field_index < PB_MAX_REQUIRED_FIELDS) + { + uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31)); + fields_seen.bitfield[iter.required_field_index >> 5] |= tmp; + } + + if (!decode_field(stream, wire_type, &iter)) + return false; + } + + /* Check that all elements of the last decoded fixed count field were present. */ + if (fixed_count_field != PB_SIZE_MAX && + fixed_count_size != fixed_count_total_size) + { + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + } + + /* Check that all required fields were present. */ + { + pb_size_t req_field_count = iter.descriptor->required_field_count; + + if (req_field_count > 0) + { + pb_size_t i; + + if (req_field_count > PB_MAX_REQUIRED_FIELDS) + req_field_count = PB_MAX_REQUIRED_FIELDS; + + /* Check the whole words */ + for (i = 0; i < (req_field_count >> 5); i++) + { + if (fields_seen.bitfield[i] != allbits) + PB_RETURN_ERROR(stream, "missing required field"); + } + + /* Check the remaining bits (if any) */ + if ((req_field_count & 31) != 0) + { + if (fields_seen.bitfield[req_field_count >> 5] != + (allbits >> (uint_least8_t)(32 - (req_field_count & 31)))) + { + PB_RETURN_ERROR(stream, "missing required field"); + } + } + } + } + + return true; +} + +bool checkreturn pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags) +{ + bool status; + + if ((flags & PB_DECODE_DELIMITED) == 0) + { + status = pb_decode_inner(stream, fields, dest_struct, flags); + } + else + { + pb_istream_t substream; + if (!pb_make_string_substream(stream, &substream)) + return false; + + status = pb_decode_inner(&substream, fields, dest_struct, flags); + + if (!pb_close_string_substream(stream, &substream)) + return false; + } + +#ifdef PB_ENABLE_MALLOC + if (!status) + pb_release(fields, dest_struct); +#endif + + return status; +} + +bool checkreturn pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct) +{ + bool status; + + status = pb_decode_inner(stream, fields, dest_struct, 0); + +#ifdef PB_ENABLE_MALLOC + if (!status) + pb_release(fields, dest_struct); +#endif + + return status; +} + +#ifdef PB_ENABLE_MALLOC +/* Given an oneof field, if there has already been a field inside this oneof, + * release it before overwriting with a different one. */ +static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *field) +{ + pb_field_iter_t old_field = *field; + pb_size_t old_tag = *(pb_size_t*)field->pSize; /* Previous which_ value */ + pb_size_t new_tag = field->tag; /* New which_ value */ + + if (old_tag == 0) + return true; /* Ok, no old data in union */ + + if (old_tag == new_tag) + return true; /* Ok, old data is of same type => merge */ + + /* Release old data. The find can fail if the message struct contains + * invalid data. */ + if (!pb_field_iter_find(&old_field, old_tag)) + PB_RETURN_ERROR(stream, "invalid union tag"); + + pb_release_single_field(&old_field); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* Initialize the pointer to NULL to make sure it is valid + * even in case of error return. */ + *(void**)field->pField = NULL; + field->pData = NULL; + } + + return true; +} + +static void pb_release_single_field(pb_field_iter_t *field) +{ + pb_type_t type; + type = field->type; + + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + if (*(pb_size_t*)field->pSize != field->tag) + return; /* This is not the current field in the union */ + } + + /* Release anything contained inside an extension or submsg. + * This has to be done even if the submsg itself is statically + * allocated. */ + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + /* Release fields from all extensions in the linked list */ + pb_extension_t *ext = *(pb_extension_t**)field->pData; + while (ext != NULL) + { + pb_field_iter_t ext_iter; + if (pb_field_iter_begin_extension(&ext_iter, ext)) + { + pb_release_single_field(&ext_iter); + } + ext = ext->next; + } + } + else if (PB_LTYPE_IS_SUBMSG(type) && PB_ATYPE(type) != PB_ATYPE_CALLBACK) + { + /* Release fields in submessage or submsg array */ + pb_size_t count = 1; + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + field->pData = *(void**)field->pField; + } + else + { + field->pData = field->pField; + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + count = *(pb_size_t*)field->pSize; + + if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > field->array_size) + { + /* Protect against corrupted _count fields */ + count = field->array_size; + } + } + + if (field->pData) + { + for (; count > 0; count--) + { + pb_release(field->submsg_desc, field->pData); + field->pData = (char*)field->pData + field->data_size; + } + } + } + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + if (PB_HTYPE(type) == PB_HTYPE_REPEATED && + (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES)) + { + /* Release entries in repeated string or bytes array */ + void **pItem = *(void***)field->pField; + pb_size_t count = *(pb_size_t*)field->pSize; + for (; count > 0; count--) + { + pb_free(*pItem); + *pItem++ = NULL; + } + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + /* We are going to release the array, so set the size to 0 */ + *(pb_size_t*)field->pSize = 0; + } + + /* Release main pointer */ + pb_free(*(void**)field->pField); + *(void**)field->pField = NULL; + } +} + +void pb_release(const pb_msgdesc_t *fields, void *dest_struct) +{ + pb_field_iter_t iter; + + if (!dest_struct) + return; /* Ignore NULL pointers, similar to free() */ + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do + { + pb_release_single_field(&iter); + } while (pb_field_iter_next(&iter)); +} +#else +void pb_release(const pb_msgdesc_t *fields, void *dest_struct) +{ + /* Nothing to release without PB_ENABLE_MALLOC. */ + PB_UNUSED(fields); + PB_UNUSED(dest_struct); +} +#endif + +/* Field decoders */ + +bool pb_decode_bool(pb_istream_t *stream, bool *dest) +{ + uint32_t value; + if (!pb_decode_varint32(stream, &value)) + return false; + + *(bool*)dest = (value != 0); + return true; +} + +bool pb_decode_svarint(pb_istream_t *stream, pb_int64_t *dest) +{ + pb_uint64_t value; + if (!pb_decode_varint(stream, &value)) + return false; + + if (value & 1) + *dest = (pb_int64_t)(~(value >> 1)); + else + *dest = (pb_int64_t)(value >> 1); + + return true; +} + +bool pb_decode_fixed32(pb_istream_t *stream, void *dest) +{ + union { + uint32_t fixed32; + pb_byte_t bytes[4]; + } u; + + if (!pb_read(stream, u.bytes, 4)) + return false; + +#if defined(PB_LITTLE_ENDIAN_8BIT) && PB_LITTLE_ENDIAN_8BIT == 1 + /* fast path - if we know that we're on little endian, assign directly */ + *(uint32_t*)dest = u.fixed32; +#else + *(uint32_t*)dest = ((uint32_t)u.bytes[0] << 0) | + ((uint32_t)u.bytes[1] << 8) | + ((uint32_t)u.bytes[2] << 16) | + ((uint32_t)u.bytes[3] << 24); +#endif + return true; +} + +#ifndef PB_WITHOUT_64BIT +bool pb_decode_fixed64(pb_istream_t *stream, void *dest) +{ + union { + uint64_t fixed64; + pb_byte_t bytes[8]; + } u; + + if (!pb_read(stream, u.bytes, 8)) + return false; + +#if defined(PB_LITTLE_ENDIAN_8BIT) && PB_LITTLE_ENDIAN_8BIT == 1 + /* fast path - if we know that we're on little endian, assign directly */ + *(uint64_t*)dest = u.fixed64; +#else + *(uint64_t*)dest = ((uint64_t)u.bytes[0] << 0) | + ((uint64_t)u.bytes[1] << 8) | + ((uint64_t)u.bytes[2] << 16) | + ((uint64_t)u.bytes[3] << 24) | + ((uint64_t)u.bytes[4] << 32) | + ((uint64_t)u.bytes[5] << 40) | + ((uint64_t)u.bytes[6] << 48) | + ((uint64_t)u.bytes[7] << 56); +#endif + return true; +} +#endif + +static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_iter_t *field) +{ + return pb_decode_bool(stream, (bool*)field->pData); +} + +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_t *field) +{ + if (PB_LTYPE(field->type) == PB_LTYPE_UVARINT) + { + pb_uint64_t value, clamped; + if (!pb_decode_varint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_uint64_t)) + clamped = *(pb_uint64_t*)field->pData = value; + else if (field->data_size == sizeof(uint32_t)) + clamped = *(uint32_t*)field->pData = (uint32_t)value; + else if (field->data_size == sizeof(uint_least16_t)) + clamped = *(uint_least16_t*)field->pData = (uint_least16_t)value; + else if (field->data_size == sizeof(uint_least8_t)) + clamped = *(uint_least8_t*)field->pData = (uint_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; + } + else + { + pb_uint64_t value; + pb_int64_t svalue; + pb_int64_t clamped; + + if (PB_LTYPE(field->type) == PB_LTYPE_SVARINT) + { + if (!pb_decode_svarint(stream, &svalue)) + return false; + } + else + { + if (!pb_decode_varint(stream, &value)) + return false; + + /* See issue 97: Google's C++ protobuf allows negative varint values to + * be cast as int32_t, instead of the int64_t that should be used when + * encoding. Nanopb versions before 0.2.5 had a bug in encoding. In order to + * not break decoding of such messages, we cast <=32 bit fields to + * int32_t first to get the sign correct. + */ + if (field->data_size == sizeof(pb_int64_t)) + svalue = (pb_int64_t)value; + else + svalue = (int32_t)value; + } + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_int64_t)) + clamped = *(pb_int64_t*)field->pData = svalue; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)field->pData = (int32_t)svalue; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)field->pData = (int_least16_t)svalue; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)field->pData = (int_least8_t)svalue; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != svalue) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; + } +} + +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_iter_t *field) +{ + uint32_t size; + size_t alloc_size; + pb_bytes_array_t *dest; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + alloc_size = PB_BYTES_ARRAY_T_ALLOCSIZE(size); + if (size > alloc_size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (stream->bytes_left < size) + PB_RETURN_ERROR(stream, "end-of-stream"); + + if (!allocate_field(stream, field->pData, alloc_size, 1)) + return false; + dest = *(pb_bytes_array_t**)field->pData; +#endif + } + else + { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "bytes overflow"); + dest = (pb_bytes_array_t*)field->pData; + } + + dest->size = (pb_size_t)size; + return pb_read(stream, dest->bytes, (size_t)size); +} + +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_t *field) +{ + uint32_t size; + size_t alloc_size; + pb_byte_t *dest = (pb_byte_t*)field->pData; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size == (uint32_t)-1) + PB_RETURN_ERROR(stream, "size too large"); + + /* Space for null terminator */ + alloc_size = (size_t)(size + 1); + + if (alloc_size < size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (stream->bytes_left < size) + PB_RETURN_ERROR(stream, "end-of-stream"); + + if (!allocate_field(stream, field->pData, alloc_size, 1)) + return false; + dest = *(pb_byte_t**)field->pData; +#endif + } + else + { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "string overflow"); + } + + dest[size] = 0; + + if (!pb_read(stream, dest, (size_t)size)) + return false; + +#ifdef PB_VALIDATE_UTF8 + if (!pb_validate_utf8((const char*)dest)) + PB_RETURN_ERROR(stream, "invalid utf8"); +#endif + + return true; +} + +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_iter_t *field) +{ + bool status = true; + bool submsg_consumed = false; + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + if (field->submsg_desc == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + /* Submessages can have a separate message-level callback that is called + * before decoding the message. Typically it is used to set callback fields + * inside oneofs. */ + if (PB_LTYPE(field->type) == PB_LTYPE_SUBMSG_W_CB && field->pSize != NULL) + { + /* Message callback is stored right before pSize. */ + pb_callback_t *callback = (pb_callback_t*)field->pSize - 1; + if (callback->funcs.decode) + { + status = callback->funcs.decode(&substream, field, &callback->arg); + + if (substream.bytes_left == 0) + { + submsg_consumed = true; + } + } + } + + /* Now decode the submessage contents */ + if (status && !submsg_consumed) + { + unsigned int flags = 0; + + /* Static required/optional fields are already initialized by top-level + * pb_decode(), no need to initialize them again. */ + if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && + PB_HTYPE(field->type) != PB_HTYPE_REPEATED) + { + flags = PB_DECODE_NOINIT; + } + + status = pb_decode_inner(&substream, field->submsg_desc, field->pData, flags); + } + + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; +} + +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_iter_t *field) +{ + uint32_t size; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + if (size == 0) + { + /* As a special case, treat empty bytes string as all zeros for fixed_length_bytes. */ + memset(field->pData, 0, (size_t)field->data_size); + return true; + } + + if (size != field->data_size) + PB_RETURN_ERROR(stream, "incorrect fixed length bytes size"); + + return pb_read(stream, (pb_byte_t*)field->pData, (size_t)field->data_size); +} + +#ifdef PB_CONVERT_DOUBLE_FLOAT +bool pb_decode_double_as_float(pb_istream_t *stream, float *dest) +{ + uint_least8_t sign; + int exponent; + uint32_t mantissa; + uint64_t value; + union { float f; uint32_t i; } out; + + if (!pb_decode_fixed64(stream, &value)) + return false; + + /* Decompose input value */ + sign = (uint_least8_t)((value >> 63) & 1); + exponent = (int)((value >> 52) & 0x7FF) - 1023; + mantissa = (value >> 28) & 0xFFFFFF; /* Highest 24 bits */ + + /* Figure if value is in range representable by floats. */ + if (exponent == 1024) + { + /* Special value */ + exponent = 128; + mantissa >>= 1; + } + else + { + if (exponent > 127) + { + /* Too large, convert to infinity */ + exponent = 128; + mantissa = 0; + } + else if (exponent < -150) + { + /* Too small, convert to zero */ + exponent = -127; + mantissa = 0; + } + else if (exponent < -126) + { + /* Denormalized */ + mantissa |= 0x1000000; + mantissa >>= (-126 - exponent); + exponent = -127; + } + + /* Round off mantissa */ + mantissa = (mantissa + 1) >> 1; + + /* Check if mantissa went over 2.0 */ + if (mantissa & 0x800000) + { + exponent += 1; + mantissa &= 0x7FFFFF; + mantissa >>= 1; + } + } + + /* Combine fields */ + out.i = mantissa; + out.i |= (uint32_t)(exponent + 127) << 23; + out.i |= (uint32_t)sign << 31; + + *dest = out.f; + return true; +} +#endif diff --git a/Bingoo/base/pb_encode.c b/Bingoo/base/pb_encode.c new file mode 100644 index 0000000..7f56201 --- /dev/null +++ b/Bingoo/base/pb_encode.c @@ -0,0 +1,1000 @@ +/* pb_encode.c -- encode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +#include "pb.h" +#include "pb_encode.h" +#include "pb_common.h" + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +/************************************** + * Declarations internal to this file * + **************************************/ +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *field); +static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *field); +static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn encode_callback_field(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn encode_field(pb_ostream_t *stream, pb_field_iter_t *field); +static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension); +static bool checkreturn pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, uint32_t high); +static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_enc_fixed(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_iter_t *field); + +#ifdef PB_WITHOUT_64BIT +#define pb_int64_t int32_t +#define pb_uint64_t uint32_t +#else +#define pb_int64_t int64_t +#define pb_uint64_t uint64_t +#endif + +/******************************* + * pb_ostream_t implementation * + *******************************/ + +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + pb_byte_t *dest = (pb_byte_t*)stream->state; + stream->state = dest + count; + + memcpy(dest, buf, count * sizeof(pb_byte_t)); + + return true; +} + +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize) +{ + pb_ostream_t stream; +#ifdef PB_BUFFER_ONLY + /* In PB_BUFFER_ONLY configuration the callback pointer is just int*. + * NULL pointer marks a sizing field, so put a non-NULL value to mark a buffer stream. + */ + static const int marker = 0; + stream.callback = ▮ +#else + stream.callback = &buf_write; +#endif + stream.state = buf; + stream.max_size = bufsize; + stream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + if (count > 0 && stream->callback != NULL) + { + if (stream->bytes_written + count < stream->bytes_written || + stream->bytes_written + count > stream->max_size) + { + PB_RETURN_ERROR(stream, "stream full"); + } + +#ifdef PB_BUFFER_ONLY + if (!buf_write(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#endif + } + + stream->bytes_written += count; + return true; +} + +/************************* + * Encode a single field * + *************************/ + +/* Read a bool value without causing undefined behavior even if the value + * is invalid. See issue #434 and + * https://stackoverflow.com/questions/27661768/weird-results-for-conditional + */ +static bool safe_read_bool(const void *pSize) +{ + const char *p = (const char *)pSize; + size_t i; + for (i = 0; i < sizeof(bool); i++) + { + if (p[i] != 0) + return true; + } + return false; +} + +/* Encode a static array. Handles the size calculations and possible packing. */ +static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *field) +{ + pb_size_t i; + pb_size_t count; +#ifndef PB_ENCODE_ARRAYS_UNPACKED + size_t size; +#endif + + count = *(pb_size_t*)field->pSize; + + if (count == 0) + return true; + + if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) + PB_RETURN_ERROR(stream, "array max size exceeded"); + +#ifndef PB_ENCODE_ARRAYS_UNPACKED + /* We always pack arrays if the datatype allows it. */ + if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) + { + if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) + return false; + + /* Determine the total size of packed array. */ + if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) + { + size = 4 * (size_t)count; + } + else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) + { + size = 8 * (size_t)count; + } + else + { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + void *pData_orig = field->pData; + for (i = 0; i < count; i++) + { + if (!pb_enc_varint(&sizestream, field)) + PB_RETURN_ERROR(stream, PB_GET_ERROR(&sizestream)); + field->pData = (char*)field->pData + field->data_size; + } + field->pData = pData_orig; + size = sizestream.bytes_written; + } + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing.. */ + + /* Write the data */ + for (i = 0; i < count; i++) + { + if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32 || PB_LTYPE(field->type) == PB_LTYPE_FIXED64) + { + if (!pb_enc_fixed(stream, field)) + return false; + } + else + { + if (!pb_enc_varint(stream, field)) + return false; + } + + field->pData = (char*)field->pData + field->data_size; + } + } + else /* Unpacked fields */ +#endif + { + for (i = 0; i < count; i++) + { + /* Normally the data is stored directly in the array entries, but + * for pointer-type string and bytes fields, the array entries are + * actually pointers themselves also. So we have to dereference once + * more to get to the actual data. */ + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER && + (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES)) + { + bool status; + void *pData_orig = field->pData; + field->pData = *(void* const*)field->pData; + + if (!field->pData) + { + /* Null pointer in array is treated as empty string / bytes */ + status = pb_encode_tag_for_field(stream, field) && + pb_encode_varint(stream, 0); + } + else + { + status = encode_basic_field(stream, field); + } + + field->pData = pData_orig; + + if (!status) + return false; + } + else + { + if (!encode_basic_field(stream, field)) + return false; + } + field->pData = (char*)field->pData + field->data_size; + } + } + + return true; +} + +/* In proto3, all fields are optional and are only encoded if their value is "non-zero". + * This function implements the check for the zero value. */ +static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *field) +{ + pb_type_t type = field->type; + + if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { + if (PB_HTYPE(type) == PB_HTYPE_REQUIRED) + { + /* Required proto2 fields inside proto3 submessage, pretty rare case */ + return false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + /* Repeated fields inside proto3 submessage: present if count != 0 */ + return *(const pb_size_t*)field->pSize == 0; + } + else if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + /* Oneof fields */ + return *(const pb_size_t*)field->pSize == 0; + } + else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->pSize != NULL) + { + /* Proto2 optional fields inside proto3 message, or proto3 + * submessage fields. */ + return safe_read_bool(field->pSize) == false; + } + else if (field->descriptor->default_value) + { + /* Proto3 messages do not have default values, but proto2 messages + * can contain optional fields without has_fields (generator option 'proto3'). + * In this case they must always be encoded, to make sure that the + * non-zero default value is overwritten. + */ + return false; + } + + /* Rest is proto3 singular fields */ + if (PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Simple integer / float fields */ + pb_size_t i; + const char *p = (const char*)field->pData; + for (i = 0; i < field->data_size; i++) + { + if (p[i] != 0) + { + return false; + } + } + + return true; + } + else if (PB_LTYPE(type) == PB_LTYPE_BYTES) + { + const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)field->pData; + return bytes->size == 0; + } + else if (PB_LTYPE(type) == PB_LTYPE_STRING) + { + return *(const char*)field->pData == '\0'; + } + else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES) + { + /* Fixed length bytes is only empty if its length is fixed + * as 0. Which would be pretty strange, but we can check + * it anyway. */ + return field->data_size == 0; + } + else if (PB_LTYPE_IS_SUBMSG(type)) + { + /* Check all fields in the submessage to find if any of them + * are non-zero. The comparison cannot be done byte-per-byte + * because the C struct may contain padding bytes that must + * be skipped. Note that usually proto3 submessages have + * a separate has_field that is checked earlier in this if. + */ + pb_field_iter_t iter; + if (pb_field_iter_begin(&iter, field->submsg_desc, field->pData)) + { + do + { + if (!pb_check_proto3_default_value(&iter)) + { + return false; + } + } while (pb_field_iter_next(&iter)); + } + return true; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + return field->pData == NULL; + } + else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK) + { + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + const pb_extension_t *extension = *(const pb_extension_t* const *)field->pData; + return extension == NULL; + } + else if (field->descriptor->field_callback == pb_default_field_callback) + { + pb_callback_t *pCallback = (pb_callback_t*)field->pData; + return pCallback->funcs.encode == NULL; + } + else + { + return field->descriptor->field_callback == NULL; + } + } + + return false; /* Not typically reached, safe default for weird special cases. */ +} + +/* Encode a field with static or pointer allocation, i.e. one whose data + * is available to the encoder directly. */ +static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + if (!field->pData) + { + /* Missing pointer field */ + return true; + } + + if (!pb_encode_tag_for_field(stream, field)) + return false; + + switch (PB_LTYPE(field->type)) + { + case PB_LTYPE_BOOL: + return pb_enc_bool(stream, field); + + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + return pb_enc_varint(stream, field); + + case PB_LTYPE_FIXED32: + case PB_LTYPE_FIXED64: + return pb_enc_fixed(stream, field); + + case PB_LTYPE_BYTES: + return pb_enc_bytes(stream, field); + + case PB_LTYPE_STRING: + return pb_enc_string(stream, field); + + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_SUBMSG_W_CB: + return pb_enc_submessage(stream, field); + + case PB_LTYPE_FIXED_LENGTH_BYTES: + return pb_enc_fixed_length_bytes(stream, field); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +/* Encode a field with callback semantics. This means that a user function is + * called to provide and encode the actual data. */ +static bool checkreturn encode_callback_field(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + if (field->descriptor->field_callback != NULL) + { + if (!field->descriptor->field_callback(NULL, stream, field)) + PB_RETURN_ERROR(stream, "callback error"); + } + return true; +} + +/* Encode a single field of any callback, pointer or static type. */ +static bool checkreturn encode_field(pb_ostream_t *stream, pb_field_iter_t *field) +{ + /* Check field presence */ + if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF) + { + if (*(const pb_size_t*)field->pSize != field->tag) + { + /* Different type oneof field */ + return true; + } + } + else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL) + { + if (field->pSize) + { + if (safe_read_bool(field->pSize) == false) + { + /* Missing optional field */ + return true; + } + } + else if (PB_ATYPE(field->type) == PB_ATYPE_STATIC) + { + /* Proto3 singular field */ + if (pb_check_proto3_default_value(field)) + return true; + } + } + + if (!field->pData) + { + if (PB_HTYPE(field->type) == PB_HTYPE_REQUIRED) + PB_RETURN_ERROR(stream, "missing required field"); + + /* Pointer field set to NULL */ + return true; + } + + /* Then encode field contents */ + if (PB_ATYPE(field->type) == PB_ATYPE_CALLBACK) + { + return encode_callback_field(stream, field); + } + else if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED) + { + return encode_array(stream, field); + } + else + { + return encode_basic_field(stream, field); + } +} + +/* Default handler for extension fields. Expects to have a pb_msgdesc_t + * pointer in the extension->type->arg field, pointing to a message with + * only one field in it. */ +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension) +{ + pb_field_iter_t iter; + + if (!pb_field_iter_begin_extension_const(&iter, extension)) + PB_RETURN_ERROR(stream, "invalid extension"); + + return encode_field(stream, &iter); +} + + +/* Walk through all the registered extensions and give them a chance + * to encode themselves. */ +static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + const pb_extension_t *extension = *(const pb_extension_t* const *)field->pData; + + while (extension) + { + bool status; + if (extension->type->encode) + status = extension->type->encode(stream, extension); + else + status = default_extension_encoder(stream, extension); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/********************* + * Encode all fields * + *********************/ + +bool checkreturn pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct) +{ + pb_field_iter_t iter; + if (!pb_field_iter_begin_const(&iter, fields, src_struct)) + return true; /* Empty message type */ + + do { + if (PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION) + { + /* Special case for the extension field placeholder */ + if (!encode_extension_field(stream, &iter)) + return false; + } + else + { + /* Regular field */ + if (!encode_field(stream, &iter)) + return false; + } + } while (pb_field_iter_next(&iter)); + + return true; +} + +bool checkreturn pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags) +{ + if ((flags & PB_ENCODE_DELIMITED) != 0) + { + return pb_encode_submessage(stream, fields, src_struct); + } + else if ((flags & PB_ENCODE_NULLTERMINATED) != 0) + { + const pb_byte_t zero = 0; + + if (!pb_encode(stream, fields, src_struct)) + return false; + + return pb_write(stream, &zero, 1); + } + else + { + return pb_encode(stream, fields, src_struct); + } +} + +bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct) +{ + pb_ostream_t stream = PB_OSTREAM_SIZING; + + if (!pb_encode(&stream, fields, src_struct)) + return false; + + *size = stream.bytes_written; + return true; +} + +/******************** + * Helper functions * + ********************/ + +/* This function avoids 64-bit shifts as they are quite slow on many platforms. */ +static bool checkreturn pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, uint32_t high) +{ + size_t i = 0; + pb_byte_t buffer[10]; + pb_byte_t byte = (pb_byte_t)(low & 0x7F); + low >>= 7; + + while (i < 4 && (low != 0 || high != 0)) + { + byte |= 0x80; + buffer[i++] = byte; + byte = (pb_byte_t)(low & 0x7F); + low >>= 7; + } + + if (high) + { + byte = (pb_byte_t)(byte | ((high & 0x07) << 4)); + high >>= 3; + + while (high) + { + byte |= 0x80; + buffer[i++] = byte; + byte = (pb_byte_t)(high & 0x7F); + high >>= 7; + } + } + + buffer[i++] = byte; + + return pb_write(stream, buffer, i); +} + +bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value) +{ + if (value <= 0x7F) + { + /* Fast path: single byte */ + pb_byte_t byte = (pb_byte_t)value; + return pb_write(stream, &byte, 1); + } + else + { +#ifdef PB_WITHOUT_64BIT + return pb_encode_varint_32(stream, value, 0); +#else + return pb_encode_varint_32(stream, (uint32_t)value, (uint32_t)(value >> 32)); +#endif + } +} + +bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value) +{ + pb_uint64_t zigzagged; + pb_uint64_t mask = ((pb_uint64_t)-1) >> 1; /* Satisfy clang -fsanitize=integer */ + if (value < 0) + zigzagged = ~(((pb_uint64_t)value & mask) << 1); + else + zigzagged = (pb_uint64_t)value << 1; + + return pb_encode_varint(stream, zigzagged); +} + +bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) +{ +#if defined(PB_LITTLE_ENDIAN_8BIT) && PB_LITTLE_ENDIAN_8BIT == 1 + /* Fast path if we know that we're on little endian */ + return pb_write(stream, (const pb_byte_t*)value, 4); +#else + uint32_t val = *(const uint32_t*)value; + pb_byte_t bytes[4]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + return pb_write(stream, bytes, 4); +#endif +} + +#ifndef PB_WITHOUT_64BIT +bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) +{ +#if defined(PB_LITTLE_ENDIAN_8BIT) && PB_LITTLE_ENDIAN_8BIT == 1 + /* Fast path if we know that we're on little endian */ + return pb_write(stream, (const pb_byte_t*)value, 8); +#else + uint64_t val = *(const uint64_t*)value; + pb_byte_t bytes[8]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + bytes[4] = (pb_byte_t)((val >> 32) & 0xFF); + bytes[5] = (pb_byte_t)((val >> 40) & 0xFF); + bytes[6] = (pb_byte_t)((val >> 48) & 0xFF); + bytes[7] = (pb_byte_t)((val >> 56) & 0xFF); + return pb_write(stream, bytes, 8); +#endif +} +#endif + +bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number) +{ + pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype; + return pb_encode_varint(stream, tag); +} + +bool pb_encode_tag_for_field ( pb_ostream_t* stream, const pb_field_iter_t* field ) +{ + pb_wire_type_t wiretype; + switch (PB_LTYPE(field->type)) + { + case PB_LTYPE_BOOL: + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + wiretype = PB_WT_VARINT; + break; + + case PB_LTYPE_FIXED32: + wiretype = PB_WT_32BIT; + break; + + case PB_LTYPE_FIXED64: + wiretype = PB_WT_64BIT; + break; + + case PB_LTYPE_BYTES: + case PB_LTYPE_STRING: + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_SUBMSG_W_CB: + case PB_LTYPE_FIXED_LENGTH_BYTES: + wiretype = PB_WT_STRING; + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return pb_encode_tag(stream, wiretype, field->tag); +} + +bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size) +{ + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + return pb_write(stream, buffer, size); +} + +bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct) +{ + /* First calculate the message size using a non-writing substream. */ + pb_ostream_t substream = PB_OSTREAM_SIZING; + size_t size; + bool status; + + if (!pb_encode(&substream, fields, src_struct)) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + return false; + } + + size = substream.bytes_written; + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing */ + + if (stream->bytes_written + size > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + + /* Use a substream to verify that a callback doesn't write more than + * what it did the first time. */ + substream.callback = stream->callback; + substream.state = stream->state; + substream.max_size = size; + substream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + substream.errmsg = NULL; +#endif + + status = pb_encode(&substream, fields, src_struct); + + stream->bytes_written += substream.bytes_written; + stream->state = substream.state; +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + + if (substream.bytes_written != size) + PB_RETURN_ERROR(stream, "submsg size changed"); + + return status; +} + +/* Field encoders */ + +static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + uint32_t value = safe_read_bool(field->pData) ? 1 : 0; + PB_UNUSED(field); + return pb_encode_varint(stream, value); +} + +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + if (PB_LTYPE(field->type) == PB_LTYPE_UVARINT) + { + /* Perform unsigned integer extension */ + pb_uint64_t value = 0; + + if (field->data_size == sizeof(uint_least8_t)) + value = *(const uint_least8_t*)field->pData; + else if (field->data_size == sizeof(uint_least16_t)) + value = *(const uint_least16_t*)field->pData; + else if (field->data_size == sizeof(uint32_t)) + value = *(const uint32_t*)field->pData; + else if (field->data_size == sizeof(pb_uint64_t)) + value = *(const pb_uint64_t*)field->pData; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_varint(stream, value); + } + else + { + /* Perform signed integer extension */ + pb_int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t*)field->pData; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t*)field->pData; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t*)field->pData; + else if (field->data_size == sizeof(pb_int64_t)) + value = *(const pb_int64_t*)field->pData; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (PB_LTYPE(field->type) == PB_LTYPE_SVARINT) + return pb_encode_svarint(stream, value); +#ifdef PB_WITHOUT_64BIT + else if (value < 0) + return pb_encode_varint_32(stream, (uint32_t)value, (uint32_t)-1); +#endif + else + return pb_encode_varint(stream, (pb_uint64_t)value); + + } +} + +static bool checkreturn pb_enc_fixed(pb_ostream_t *stream, const pb_field_iter_t *field) +{ +#ifdef PB_CONVERT_DOUBLE_FLOAT + if (field->data_size == sizeof(float) && PB_LTYPE(field->type) == PB_LTYPE_FIXED64) + { + return pb_encode_float_as_double(stream, *(float*)field->pData); + } +#endif + + if (field->data_size == sizeof(uint32_t)) + { + return pb_encode_fixed32(stream, field->pData); + } +#ifndef PB_WITHOUT_64BIT + else if (field->data_size == sizeof(uint64_t)) + { + return pb_encode_fixed64(stream, field->pData); + } +#endif + else + { + PB_RETURN_ERROR(stream, "invalid data_size"); + } +} + +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + const pb_bytes_array_t *bytes = NULL; + + bytes = (const pb_bytes_array_t*)field->pData; + + if (bytes == NULL) + { + /* Treat null pointer as an empty bytes field */ + return pb_encode_string(stream, NULL, 0); + } + + if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && + bytes->size > field->data_size - offsetof(pb_bytes_array_t, bytes)) + { + PB_RETURN_ERROR(stream, "bytes size exceeded"); + } + + return pb_encode_string(stream, bytes->bytes, (size_t)bytes->size); +} + +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + size_t size = 0; + size_t max_size = (size_t)field->data_size; + const char *str = (const char*)field->pData; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + max_size = (size_t)-1; + } + else + { + /* pb_dec_string() assumes string fields end with a null + * terminator when the type isn't PB_ATYPE_POINTER, so we + * shouldn't allow more than max-1 bytes to be written to + * allow space for the null terminator. + */ + if (max_size == 0) + PB_RETURN_ERROR(stream, "zero-length string"); + + max_size -= 1; + } + + + if (str == NULL) + { + size = 0; /* Treat null pointer as an empty string */ + } + else + { + const char *p = str; + + /* strnlen() is not always available, so just use a loop */ + while (size < max_size && *p != '\0') + { + size++; + p++; + } + + if (*p != '\0') + { + PB_RETURN_ERROR(stream, "unterminated string"); + } + } + +#ifdef PB_VALIDATE_UTF8 + if (!pb_validate_utf8(str)) + PB_RETURN_ERROR(stream, "invalid utf8"); +#endif + + return pb_encode_string(stream, (const pb_byte_t*)str, size); +} + +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + if (field->submsg_desc == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + if (PB_LTYPE(field->type) == PB_LTYPE_SUBMSG_W_CB && field->pSize != NULL) + { + /* Message callback is stored right before pSize. */ + pb_callback_t *callback = (pb_callback_t*)field->pSize - 1; + if (callback->funcs.encode) + { + if (!callback->funcs.encode(stream, field, &callback->arg)) + return false; + } + } + + return pb_encode_submessage(stream, field->submsg_desc, field->pData); +} + +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + return pb_encode_string(stream, (const pb_byte_t*)field->pData, (size_t)field->data_size); +} + +#ifdef PB_CONVERT_DOUBLE_FLOAT +bool pb_encode_float_as_double(pb_ostream_t *stream, float value) +{ + union { float f; uint32_t i; } in; + uint_least8_t sign; + int exponent; + uint64_t mantissa; + + in.f = value; + + /* Decompose input value */ + sign = (uint_least8_t)((in.i >> 31) & 1); + exponent = (int)((in.i >> 23) & 0xFF) - 127; + mantissa = in.i & 0x7FFFFF; + + if (exponent == 128) + { + /* Special value (NaN etc.) */ + exponent = 1024; + } + else if (exponent == -127) + { + if (!mantissa) + { + /* Zero */ + exponent = -1023; + } + else + { + /* Denormalized */ + mantissa <<= 1; + while (!(mantissa & 0x800000)) + { + mantissa <<= 1; + exponent--; + } + mantissa &= 0x7FFFFF; + } + } + + /* Combine fields */ + mantissa <<= 29; + mantissa |= (uint64_t)(exponent + 1023) << 52; + mantissa |= (uint64_t)sign << 63; + + return pb_encode_fixed64(stream, &mantissa); +} +#endif diff --git a/Bingoo/base/robot_move_actions.c b/Bingoo/base/robot_move_actions.c new file mode 100644 index 0000000..4cfd326 --- /dev/null +++ b/Bingoo/base/robot_move_actions.c @@ -0,0 +1,1074 @@ +/* + * robot_move_actions.c + * + * Created on: 2025年7月14日 + * Author: akeguo + * + * @note 本文件包含机器人水平/垂直方向自动移动的状态机实现, + * 以及换道状态机。所有状态机均通过函数指针表驱动。 + */ + +/*=========================== 1.头文件包含 ===========================*/ +#include "robot_move_actions.h" +#include "swing_action.h" +#include "fsm_state.h" +#include "fsm_state_control.h" +#include "paint_gun_action.h" +#include "MSP/msp_PID.h" +#include "bsp_slide_averager.h" +#include + + +/*=========================== 2.宏定义 ===========================*/ +/* 姿态控制常量(用于 Robot_Posture_Adjus_Gravity) */ +#define TT_One_Deg_Count2 11014 +#define POSTURE_ERROR_THRESHOLD 10.0f /* 姿态调整误差阈值(度) */ +#define ANGLE_NORMALIZE_BOUNDARY 180.0f /* 角度归一化边界 */ +#define SPEED_FACTOR_LARGE 1.0f /* 大误差速度系数 */ +#define SPEED_FACTOR_SMALL 0.15f /* 小误差速度系数 */ +#define SPEED_BASE 4.0f /* 电机速度基准 (m/min) */ +#define K_OF_DIS_VER 1.011189f /* 最小二乘拟合的k */ +#define B_OF_DIS_VER 0.387616f /* 最小二乘拟合的b */ +#define K_OF_DIS_HOR 1.013714f /* 最小二乘拟合的k */ +#define B_OF_DIS_HOR 3.226667f /* 最小二乘拟合的b */ + +/* 换道相关常量 */ +#define LANE_CHANGE_SPEED 3.0f /* 换道后退速度 (单位需与PID匹配) */ + +/* 状态机跳转阈值 */ +static const float ANGLE_ERROR_THRESHOLD = 0.5f; /* 姿态到位误差阈值 */ + +/*=========================== 3.类型定义(枚举) ===========================*/ +/** + * 水平单道自动运行状态枚举 + */ +enum single_lane_auto_state { + STATE_ATTITUDE_JUDGE = 0, /* 姿态误差判断 */ + STATE_ATTITUDE_ADJUST, /* 姿态调整 */ + STATE_WORK_WAY_OR_DIRECT_MOVE, /* 工作模式选择 */ + STATE_FIGHT_ALTERNATELY, /* 交替后退 */ + STATE_FIGHT_RETREATING, /* 连续后退 */ + STATE_HALT, /* 停机状态 */ + STATE_COUNT /* 状态总数 */ +}; + + +/** + * 打退交替状态枚举 + */ +enum alternately_state{ + STATE_ROBOT_STOP = 0, /* 打的时候机器人静止 */ + STATE_ROBOT_BACK, /* 打到最后5°机器人后退 */ +}; + +/** + * 换道自动执行状态枚举 + */ +enum lane_change_auto_state { + LANE_CHANGE_STATE_ATTITUDE_JUDGE = 0, /* 姿态误差判断 */ + LANE_CHANGE_STATE_ATTITUDE_ADJUST, /* 姿态调整 */ + LANE_CHANGE_STATE_CALC_RETREAT_TIME, /* 计算后退时间 */ + LANE_CHANGE_STATE_CONTINUOUS_RETREAT, /* 连续后退 */ + LANE_CHANGE_STATE_RETREAT_DONE_SWITCH, /* 后退完成,切换期望姿态 */ + LANE_CHANGE_STATE_COUNT /* 状态总数 */ +}; + +/** + * 摆臂状态枚举 + */ +enum swing_state { + SWING_START_STATE = 0, /* 起始状态 */ + SWING_LEFT_MOVE, /* 向左运动姿态调整 */ + SWING_RIGHT_MOVE, /* 向右运动 */ +}; + +/** + * 焊缝状态枚举 + */ +enum weld_auto_state { + //STATE_ATTITUDE_JUDGE = 0, /* 姿态误差判断 */ + WELD_STATE_AVG_INT = 0, /* 初始化滑动均值 */ + WELD_STATE_FIGHT_RETREATING , /* 连续后退 */ + WELD_STATE_HALT, /* 停机状态 */ + WELD_STATE_COUNT /* 状态总数 */ +}; + +/** + * 状态机类型枚举(用于多状态机管理) + */ +typedef enum { + FSM_init_state = 0, // 默认初始化的值(占位,不使用) + FSM_HORIZONTAL_AUTO_Flag, // 水平单道自动 + FSM_HORIZONTAL_FORWARD_Flag, // 水平前进(简化版) + FSM_VERTICAL_FORWARD_Flag, // 垂直前进 + FSM_VERTICAL_CHANGE_ROAD_Flag, // 垂直左换道 + FSM_VERTICAL_AUTO_Flag, // 垂直单道自动 + FSM_SWING, //摆臂 + REGION_STATE_AUTO_CONTINUOUS_Flag, //区域自动作业 + WELD_AUTO_Flag, //区域自动作业 + FSM_COUNT // 状态机总数 +} FsmType; + +/*=========================== 4.全局变量 ===========================*/ + +////局部静态变量 +/* 状态机当前状态(多个状态机共用,可能存在潜在冲突,但是现在还不知道咋搞呢) */ +static FsmType s_activeFsm; +static FsmType s_lastActiveFsm=FSM_init_state; +static int s_fsmState[FSM_COUNT] = {0}; +int s_currentState = STATE_ATTITUDE_JUDGE; +int horizontal_s_currentState = STATE_ATTITUDE_JUDGE; +int vertical_s_currentState = STATE_ATTITUDE_JUDGE; +int ChangeRoad_currentState = LANE_CHANGE_STATE_ATTITUDE_JUDGE; +int swing_currentState = SWING_START_STATE; +int alternately_flag = STATE_ROBOT_STOP; + +/* 换道计时变量 */ +static uint32_t s_retreatStartTick = 0; /* 后退起始系统节拍 */ +static uint32_t s_retreatDurationTicks = 0; /* 后退持续节拍数 */ + +/* 期望角度数组(上下左右换道) */ +static float LEFT_TARGET_ANGLES[2]; + +int Change_stop_flag=0; + +static int S1_Last_Value; +static int S2_Last_Value; +float center_angle=0; +int offset_angle; +int center_position; //中间位置-944334 +int present_angle; //摆臂电机当前角度 +int alternately_times=0; //后退时间 +int alternately_times_total=0; //后退总时间 + +//滑动均值所用变量 +float avg_buffer[5]; // 窗口缓冲区 +uint8_t avg_index; // 当前索引 +uint8_t avg_count; // 有效计数 +int32_t weld_cnt=0; + +/*===========================5. 静态函数声明 ===========================*/ +/* 水平/垂直状态机函数 */ +static void handleAttitudeJudge_horizontal(void); +static void handleAttitudeJudge_vertical(void); +static void handleAttitudeAdjustHorizontal(void); +static void handleAttitudeAdjustVertical(void); +static void handleAttitudeAdjustChangeRoad(void); +static void handleWorkWay(void); +void horizontal_work(void); +void Move_Horizontal_Auto_Sub_Func(void); +static void auto_drive_pid_weld(void); +void avg_init(void); + + +/* 换道状态机函数 */ +void get_ChangeAngle(void); +static void handleLaneChangeAttitudeJudgeLeft(void); +static void handleLaneChangeCalcRetreatTime(void); +static void handleLaneChangeContinuousRetreat(void); + +/* 打退连续函数 */ +void Fight_Countinus_Function_Horizontal(); +void Fight_Countinus_Function_Vertical(); +void Move_Horizontal_Vertical_Task_Backwards_Do_Backward(void); +static void Move_Weld_Task_Backwards_Do_Backward(void); +void Fight_Countinus_Function_Weld(); +void Update_Angle_compensation_hor(void); +void Update_Angle_compensation_ver(void); +void Auto_Forward_Function_Horizontal_group(void); +void Auto_Forward_Function_Vertical_group(void); +void Fight_Alternately_Function_Horizontal(void); + +/* 打退交替函数 */ +void alternately_stop_func(void); +void alternately_back_func(void); + +/* 辅助函数 */ +static void auto_drive_pid_horizontal(void); +static void auto_drive_pid_vertical(void); +static void handleHalt(void); + +/* 摆臂运动函数 */ +void swing_work(void); +static void swing_start_move(void); +static void swing_left_move(void); +static void swing_right_move(void); +static void get_swing_mode(void); +void updata_swing_angle(void); + +/* 急停函数 */ +void Emergency_Stop_Action(void); +/* PID系数 */ +int factor_1= 1; +int factor_2= -1; + +/*===========================6.函数指针表 ===========================*/ +/** + * 水平单道自动运行状态函数表 + * 注意:STATE_FIGHT_ALTERNATELY 和 STATE_FIGHT_RETREATING 暂未实现,用 NULL 占位 + */ +static const void (*const horizontal_single_lane_auto_operation[])(void) = { + [STATE_ATTITUDE_JUDGE] = handleAttitudeJudge_horizontal, + [STATE_ATTITUDE_ADJUST] = handleAttitudeAdjustHorizontal, + [STATE_WORK_WAY_OR_DIRECT_MOVE] = handleWorkWay, + [STATE_FIGHT_ALTERNATELY] = Fight_Alternately_Function_Horizontal, /* 打退交替 */ + [STATE_FIGHT_RETREATING] = Fight_Countinus_Function_Horizontal, /*打退连续 */ + [STATE_HALT] = handleHalt, +}; + + + + +/** + * 打退交替状态函数表 + * 注意:STATE_FIGHT_ALTERNATELY 和 STATE_FIGHT_RETREATING 暂未实现,用 NULL 占位 + */ +static const void (*const alternately_work[])(void) = { + [STATE_ROBOT_STOP] = alternately_stop_func, + [STATE_ROBOT_BACK] = alternately_back_func, + [STATE_HALT] = handleHalt, +}; + +/** + * 水平前进简化状态表(用于 horizontal_forward) + */ +static const void (*const robot_horizontal_drive[])(void) = { + [STATE_ATTITUDE_JUDGE] = handleAttitudeJudge_horizontal, + [STATE_ATTITUDE_ADJUST] = handleAttitudeAdjustHorizontal, + [STATE_WORK_WAY_OR_DIRECT_MOVE] = Auto_Forward_Function_Horizontal_group, + [STATE_HALT] = handleHalt, +}; + + + +/** + * 垂直前进简化状态表(用于 vertical_forward) + */ +static const void (*const robot_vertical_drive[])(void) = { + [STATE_ATTITUDE_JUDGE] = handleAttitudeJudge_vertical, + [STATE_ATTITUDE_ADJUST] = handleAttitudeAdjustVertical, + [STATE_WORK_WAY_OR_DIRECT_MOVE] = Auto_Forward_Function_Vertical_group, + [STATE_HALT] = handleHalt, +}; + + +/** + * 垂直单道自动运行状态函数表 + * 注意:STATE_FIGHT_ALTERNATELY 和 STATE_FIGHT_RETREATING 暂未实现,用 NULL 占位 + */ +static const void (*const vertical_single_lane_auto_operation[])(void) = { + [STATE_ATTITUDE_JUDGE] = handleAttitudeJudge_vertical, + [STATE_ATTITUDE_ADJUST] = handleAttitudeAdjustHorizontal, + [STATE_WORK_WAY_OR_DIRECT_MOVE] = handleWorkWay, + [STATE_FIGHT_ALTERNATELY] = NULL, /* 待实现 */ + [STATE_FIGHT_RETREATING] = Fight_Countinus_Function_Vertical, /* 待实现 */ + [STATE_HALT] = handleHalt, +}; + + +/** + * 换道状态函数表 + */ +static const void (*const vertical_lane_change_left[])(void) = { + [LANE_CHANGE_STATE_ATTITUDE_JUDGE] = handleLaneChangeAttitudeJudgeLeft, + [LANE_CHANGE_STATE_ATTITUDE_ADJUST] = handleAttitudeAdjustChangeRoad, + [LANE_CHANGE_STATE_CALC_RETREAT_TIME] = handleLaneChangeCalcRetreatTime, + [LANE_CHANGE_STATE_CONTINUOUS_RETREAT] = handleLaneChangeContinuousRetreat, + [LANE_CHANGE_STATE_RETREAT_DONE_SWITCH] = handleAttitudeAdjustChangeRoad, + [STATE_HALT] = handleHalt, +}; + + +/** + * 摆臂运动函数表 + */ +static const void (*const swing_move_control[])(void) = { + [SWING_START_STATE] = swing_start_move, + [SWING_LEFT_MOVE] = swing_left_move, + [SWING_RIGHT_MOVE] = swing_right_move, + [STATE_HALT] = handleHalt, +}; + + +/** + * 焊缝跟踪运动函数表 + */ +static const void (*const weld_auto_operation[])(void) = { + [WELD_STATE_AVG_INT] = avg_init, + [WELD_STATE_FIGHT_RETREATING] = Fight_Countinus_Function_Weld, + [WELD_STATE_HALT] = handleHalt, +}; + +/*=========================== 7.静态函数实现 ===========================*/ +/*----------------------------------------------------------------- + * 状态机切换管理 + *-----------------------------------------------------------------*/ +static void check_and_reset_fsm(FsmType current) { + if (s_lastActiveFsm != current) { + // 发生了状态机切换,重置其他所有状态机 + for (int i = 0; i < FSM_COUNT; i++) { + if (i != current) { + s_fsmState[i] = 0; // 重置为初始状态 + } + } + s_lastActiveFsm = current; // 更新上次类型 + } + // 如果相同,不做任何操作 +} + + + + +/*----------------------------------------------------------------- + * 基础运动控制(手动模式) + *-----------------------------------------------------------------*/ +void Manually_Forward(void) +{ + GV.Left_Speed_M_min = GV.Robot_Move_Speed; + GV.Right_Speed_M_min = -GV.Robot_Move_Speed; +} + +void Manually_Backward(void) +{ + GV.Left_Speed_M_min = -GV.Robot_Move_Speed; + GV.Right_Speed_M_min = GV.Robot_Move_Speed; +} + +void Turn_Left(void) +{ + GV.Left_Speed_M_min = -GV.Robot_Move_Speed/8; + GV.Right_Speed_M_min = -GV.Robot_Move_Speed/8; +} + +void Turn_Right(void) +{ + GV.Left_Speed_M_min = GV.Robot_Move_Speed/8; + GV.Right_Speed_M_min = GV.Robot_Move_Speed/8; +} + +void Robot_Stop(void) +{ + check_and_reset_fsm(FSM_init_state); + swing_currentState = 0; + alternately_times =0; + alternately_flag=0; + + get_swing_mode(); //仅在机器人停的时候允许更新摆臂模式 + Robot_Swing_Operation_Function(); //机器人停的时候允许摆臂 + GV.Left_Speed_M_min = 0; + GV.Right_Speed_M_min = 0; + GV.turn_center_difference=0; + Change_stop_flag=1; + PaintGun_Contronl(); //机器人停的时候允许动推杆 + //GV.GroundManagementValue.MaualControlPower=0; //恢复急停断电 +} + + + + +/*----------------------------------------------------------------- + * 姿态调整辅助函数(重力方向) + *-----------------------------------------------------------------*/ +void Robot_Posture_Adjus_Gravity(float *pError) +{ + float actualAngle = (float)GV.TL720DParameters.RF_Angle_Roll / 100.0f; + float error = GV.Robot_Angle_Desire - actualAngle; + + /* 归一化到 [-180, 180) */ + if (error >= ANGLE_NORMALIZE_BOUNDARY) { + error -= 2.0f * ANGLE_NORMALIZE_BOUNDARY; + } else if (error < -ANGLE_NORMALIZE_BOUNDARY) { + error += 2.0f * ANGLE_NORMALIZE_BOUNDARY; + } + + float absError = fabsf(error); + *pError = absError; + + float speedFactor = (absError > POSTURE_ERROR_THRESHOLD) ? SPEED_FACTOR_LARGE : SPEED_FACTOR_SMALL; + float direction = (error >= 0.0f) ? 1.0f : -1.0f; + + float motorSpeed = (float)(speedFactor * direction * SPEED_BASE); + GV.Left_Speed_M_min = motorSpeed; + GV.Right_Speed_M_min = motorSpeed; +} + + +static void handleAttitudeAdjustHorizontal(void) +{ + float errorAbs; + Robot_Posture_Adjus_Gravity(&errorAbs); + if (errorAbs < ANGLE_ERROR_THRESHOLD) { + s_fsmState[s_activeFsm]++; + } +} + +static void handleAttitudeAdjustVertical(void) +{ + float errorAbs; + Robot_Posture_Adjus_Gravity(&errorAbs); + if (errorAbs < ANGLE_ERROR_THRESHOLD) { + s_fsmState[s_activeFsm]++; + } +} + + +static void handleAttitudeAdjustChangeRoad(void) +{ + float errorAbs; + Robot_Posture_Adjus_Gravity(&errorAbs); + if (errorAbs < ANGLE_ERROR_THRESHOLD) { + s_fsmState[s_activeFsm]++; + } +} +/*----------------------------------------------------------------- + * 水平/垂直/焊缝状态机核心函数 + *-----------------------------------------------------------------*/ +static void handleAttitudeJudge_horizontal(void) +{ + float robotRoll = (float)GV.TL720DParameters.RF_Angle_Roll / 100.0f; + + if (robotRoll > -180.0f && robotRoll < 0.0f) { + GV.Robot_Angle_Desire = -90.0f + (float)GV.Right_Compensation / 100.0f; + } else { + GV.Robot_Angle_Desire = 90.0f + (float)GV.Left_Compensation / 100.0f; + } + s_fsmState[s_activeFsm]=STATE_ATTITUDE_ADJUST; +} + +static void handleAttitudeJudge_vertical(void) +{ + float robotRoll = (float)GV.TL720DParameters.RF_Angle_Roll / 100.0f; + + if (robotRoll > -90.0f && robotRoll <= 90.0f) { + GV.Robot_Angle_Desire = -GV.Vertical_Adjust; + } +// else +// { +// GV.Robot_Angle_Desire = 180.0f + GV.Vertical_Adjust; +// if (GV.Robot_Angle_Desire > 180.0f) { +// GV.Robot_Angle_Desire -= 360.0f; +// } +// } + s_fsmState[s_activeFsm] = STATE_ATTITUDE_ADJUST; +} + + +//打退交替状态下机器人停止状态 +void alternately_stop_func(void) +{ + GV.Left_Speed_M_min = 0; + GV.Right_Speed_M_min = 0; + if((present_angleright_compare_value-5)) //进入最后5°范围 + { + alternately_flag=STATE_ROBOT_BACK; + } +} + + +//打退交替状态下机器人后退状态 +void alternately_back_func(void) +{ + GV.Robot_Desired_Speed=-GV.Robot_Move_Speed; + alternately_times_total=-300*GV.robot_back_distance/GV.Robot_Desired_Speed; //计算出后退总时间 + if(alternately_times<=alternately_times_total) + { + auto_drive_pid_horizontal(); + alternately_times++; + } + else + { + alternately_times=0; + alternately_flag=STATE_ROBOT_STOP; + } +} + +static void handleWorkWay(void) +{ +// int mode = 1;//GV.Robot_backMode; +// if (mode == 1) { +// s_fsmState[s_activeFsm]= STATE_FIGHT_ALTERNATELY; +// } else if (mode == 2) { +// s_fsmState[s_activeFsm]= STATE_FIGHT_RETREATING; +// } + /* 其他模式保持当前状态?目前没有 else,可能默认留在该状态 */ + s_fsmState[s_activeFsm]= STATE_FIGHT_RETREATING; +} + +/*----------------------------------------------------------------- + * 换道状态机函数 + *-----------------------------------------------------------------*/ +static void handleLaneChangeAttitudeJudgeLeft(void) +{ + if(Change_stop_flag==1) + { + Change_stop_flag=0; + get_ChangeAngle(); + GV.Robot_Angle_Desire = LEFT_TARGET_ANGLES[0]; + s_fsmState[s_activeFsm] = LANE_CHANGE_STATE_ATTITUDE_ADJUST; + } + +} + +/*----------------------------------------------------------------- + * 确定换道状态函数 + *-----------------------------------------------------------------*/ +void get_ChangeAngle(void) +{ + if(GV.PV.Robot_Operation_Mode==2) //需要水平下换道 + { + if(GV.TL720DParameters.RF_Angle_Roll<0) + { + LEFT_TARGET_ANGLES[0]=0; + LEFT_TARGET_ANGLES[1]=90; + } + else if(GV.TL720DParameters.RF_Angle_Roll>0) + { + LEFT_TARGET_ANGLES[0]=0; + LEFT_TARGET_ANGLES[1]=-90; + } + } + else if(GV.PV.Robot_Operation_Mode==4) //需要竖直左换道 + { + LEFT_TARGET_ANGLES[0]=90; + LEFT_TARGET_ANGLES[1]=0; + } + else if(GV.PV.Robot_Operation_Mode==5) //需要竖直右换道 + { + LEFT_TARGET_ANGLES[0]=-90; + LEFT_TARGET_ANGLES[1]=0; + } +} + + +static void handleLaneChangeCalcRetreatTime(void) +{ + float distanceM; + if(GV.PV.Robot_Operation_Mode==2)//水平 + { + distanceM = ((float)GV.LaneChangeDistance-B_OF_DIS_HOR)/K_OF_DIS_HOR; /* 厘米 → 米 */ + distanceM=distanceM * 0.01f; + } + else if(GV.PV.Robot_Operation_Mode==4||GV.PV.Robot_Operation_Mode==5) //竖直 + { + distanceM = ((float)GV.LaneChangeDistance-B_OF_DIS_VER)/K_OF_DIS_VER; /* 厘米 → 米 */ + distanceM=distanceM * 0.01f; + } + float timeSec = distanceM / LANE_CHANGE_SPEED; /* 秒 */ + float timeMs = timeSec * 60.0f * 1000.0f; /* 毫秒 */ + s_retreatDurationTicks = (uint32_t)timeMs; + + uint32_t tickNow = HAL_GetTick(); + s_retreatStartTick = tickNow; + + s_fsmState[s_activeFsm] = LANE_CHANGE_STATE_CONTINUOUS_RETREAT; + + if(P_MK32->CH4_SA == -1000&&Change_stop_flag==1) + { + s_fsmState[s_activeFsm] = LANE_CHANGE_STATE_ATTITUDE_JUDGE; + } +} + +static void handleLaneChangeContinuousRetreat(void) +{ + uint32_t tickNow = HAL_GetTick(); + GV.Robot_Desired_Speed = -LANE_CHANGE_SPEED; + auto_drive_pid_vertical(); + + if ((tickNow - s_retreatStartTick) >= s_retreatDurationTicks) { + s_fsmState[s_activeFsm]++; + GV.Robot_Angle_Desire = LEFT_TARGET_ANGLES[1]; + } +} + + + +/*----------------------------------------------------------------- + * 打退连续函数 + *-----------------------------------------------------------------*/ +void Fight_Countinus_Function_Manual() +{ + swing_work(); + GV.Robot_Desired_Speed=-GV.Robot_Move_Speed; + GV.Left_Speed_M_min = GV.Robot_Desired_Speed; + GV.Right_Speed_M_min = -GV.Robot_Desired_Speed; +} + +void Fight_Countinus_Function_Horizontal() +{ + Update_Angle_compensation_hor(); + swing_work(); + Move_Horizontal_Vertical_Task_Backwards_Do_Backward(); +} + +void Fight_Countinus_Function_Vertical() +{ + Update_Angle_compensation_ver(); + swing_work(); + Move_Horizontal_Vertical_Task_Backwards_Do_Backward(); +} + + +void Move_Horizontal_Vertical_Task_Backwards_Do_Backward(void) +{ + GV.Robot_Desired_Speed=-GV.Robot_Move_Speed; + auto_drive_pid_horizontal(); + +} + +void Fight_Countinus_Function_Weld() +{ + updata_swing_angle(); + swing_work(); + auto_drive_pid_weld(); +} + +void Update_Angle_compensation_hor(void) +{ + float robotRoll = (float)GV.TL720DParameters.RF_Angle_Roll / 100.0f; + + if (robotRoll > -180.0f && robotRoll < 0.0f) { + GV.Robot_Angle_Desire = -90.0f + (float)GV.Right_Compensation / 100.0f; + } else { + GV.Robot_Angle_Desire = 90.0f + (float)GV.Left_Compensation / 100.0f; + } +} + + +void Update_Angle_compensation_ver(void) +{ + float robotRoll = (float)GV.TL720DParameters.RF_Angle_Roll / 100.0f; + + if (robotRoll > -90.0f && robotRoll <= 90.0f) { + GV.Robot_Angle_Desire = -GV.Vertical_Adjust; + } +// else +// { +// GV.Robot_Angle_Desire = 180.0f + GV.Vertical_Adjust; +// if (GV.Robot_Angle_Desire > 180.0f) { +// GV.Robot_Angle_Desire -= 360.0f; +// } +// } +} + +void Auto_Forward_Function_Horizontal_group(void) +{ + Update_Angle_compensation_hor(); + auto_drive_pid_horizontal(); +} + +void Auto_Forward_Function_Vertical_group(void) +{ + Update_Angle_compensation_ver(); + auto_drive_pid_vertical(); +} + + +/*----------------------------------------------------------------- + *打一道退一道函数 + *-----------------------------------------------------------------*/ +void Fight_Alternately_Function_Horizontal(void) +{ + swing_work(); + + if (alternately_flag >= 0 && alternately_flag < STATE_COUNT) { + if (alternately_work[alternately_flag] != NULL) { + alternately_work[alternately_flag](); + } else { + /* 遇到未实现的状态,停机处理 */ + handleHalt(); + } + } else { + handleHalt(); + } +} + + + +/*----------------------------------------------------------------- + * 摆臂运动函数 + *-----------------------------------------------------------------*/ +float first_center; +static void swing_start_move(void) +{ + left_compare_updata=left_compare_value; + right_compare_updata=right_compare_value; + first_center=center_angle; + present_angle=-(GV.SwingMotor.Real_Position+944334)/11014; + if(present_angle>=left_compare_value+2) + { + swing_currentState=SWING_LEFT_MOVE; + Move_Swing_Left_Func_Do_imm(); + } + else + { + swing_currentState=SWING_RIGHT_MOVE; + Move_Swing_Right_Func_Do_imm(); + } +} + + +static void swing_left_move(void) +{ + present_angle=-(GV.SwingMotor.Real_Position+944334)/11014; + if(present_angle<=left_compare_value+1) + { + + //焊缝跟踪时允许改变摆臂中心位置,若检测到中心位置变化,则更新偏距 + if(right_compare_updata!=right_compare_value) + { + GV.turn_center_difference=center_angle-first_center; + right_compare_value=right_compare_updata; + center_angle=(right_compare_updata+left_compare_updata)/2; + } + + + Move_Swing_Right_Func_Do_lay(); + swing_currentState=SWING_RIGHT_MOVE; + + + } +} + +static void swing_right_move(void) +{ + present_angle=-(GV.SwingMotor.Real_Position+944334)/11014; + if(present_angle>right_compare_value-1) + { + + //焊缝跟踪时允许改变摆臂中心位置,若检测到中心位置变化,则更新偏距 + if(left_compare_updata!=left_compare_value) + { + GV.turn_center_difference=center_angle-first_center; + left_compare_value=left_compare_updata; + center_angle=(right_compare_updata+left_compare_updata)/2; + } + + + Move_Swing_Left_Func_Do_lay(); + swing_currentState=SWING_LEFT_MOVE; + } +} + + +static void get_swing_mode(void) +{ + if(GV.symmetricalOrNot==1) + { + if(GV.PV.Robot_Swing_Range_Angle!=offset_angle && GV.SwingMotor.Real_Position!=0) + { + offset_angle=GV.PV.Robot_Swing_Range_Angle; + center_angle=-((float)GV.SwingMotor.Real_Position+944334)/TT_One_Deg_Count2; + } + + + left_compare_value=center_angle-offset_angle/2; + right_compare_value=center_angle+offset_angle/2; + + } + else if(GV.symmetricalOrNot==2) //非对称式 + { + if(GV.SwingMotor.Real_Position!=0) + { + if(P_MK32->CH12_S1!=S1_Last_Value) + { + left_compare_value=-(GV.SwingMotor.Real_Position+944334)/11014; + } + else if(P_MK32->CH13_S2!=S2_Last_Value) + { + right_compare_value=-(GV.SwingMotor.Real_Position+944334)/11014; + } + } + S1_Last_Value=P_MK32->CH12_S1; + S2_Last_Value=P_MK32->CH13_S2; + } +} + +int32_t updata_cnt=0; +void updata_swing_angle(void) //焊缝跟踪模式下允许更新摆臂中心位置 +{ + + + if(P_MK32->CH0_RY_H<-300) + { + updata_cnt++; + if(updata_cnt>200) + { + left_compare_updata=left_compare_value-2; + right_compare_updata=right_compare_value-2; + updata_cnt=0; + } + + } + else if(P_MK32->CH0_RY_H>300) + { + updata_cnt++; + if(updata_cnt>200) + { + left_compare_updata=left_compare_value+2; + right_compare_updata=right_compare_value+2; + updata_cnt=0; + } + } + + +} + +/*----------------------------------------------------------------- + * PID驱动及停机处理 + *-----------------------------------------------------------------*/ +static void auto_drive_pid_horizontal(void) +{ + float robotRoll = (float)GV.TL720DParameters.RF_Angle_Roll / 100.0f; + float speeds[2]; + TwoWheel_AngleControl(robotRoll, GV.Robot_Angle_Desire, GV.Robot_Desired_Speed,1, speeds); + + GV.Left_Speed_M_min = factor_1*speeds[0]; + GV.Right_Speed_M_min = factor_2*speeds[1]; /* 根据电机方向可能需要调整符号 */ +} + +void avg_init(void) //初始化滑动均值所需要的参数 +{ + slide_averager_init(avg_buffer, &avg_index, &avg_count); + weld_cnt=0; + s_fsmState[s_activeFsm] = WELD_STATE_FIGHT_RETREATING; +} + +float avg; +static void auto_drive_pid_weld(void) +{ + float robotRoll = (float)(ReadLazorData->Feature_X); + avg = slide_averager_calc(avg_buffer, &avg_index, &avg_count, -robotRoll); + float speeds[2]; + + TwoWheel_AngleControl_Weld(avg, 0, GV.Robot_Desired_Speed,0.5, speeds); + + GV.Left_Speed_M_min = factor_1*speeds[0]; + GV.Right_Speed_M_min = factor_2*speeds[1]; /* 根据电机方向可能需要调整符号 */ + + //未检测到则焊缝速度为0 + if((*Weld_Out_Flag)==16) + { + weld_cnt++; + if(weld_cnt>1500) + { + s_fsmState[s_activeFsm] = WELD_STATE_HALT; + GV.Left_Speed_M_min = 0; + GV.Right_Speed_M_min = 0; + GV.Tar_Position_Velcity_Degree_S=0; + } + } + else + { + weld_cnt=0; + } + +} + +float PID_factor=1; +static void auto_drive_pid_vertical(void) +{ + float robotRoll = (float)GV.TL720DParameters.RF_Angle_Roll / 100.0f; + float speeds[2]; + + TwoWheel_AngleControl(robotRoll, GV.Robot_Angle_Desire, GV.Robot_Desired_Speed,PID_factor, speeds); + + GV.Left_Speed_M_min = factor_1*speeds[0]; + GV.Right_Speed_M_min = factor_2*speeds[1]; /* 根据电机方向可能需要调整符号 */ +} + +static void Move_Weld_Task_Backwards_Do_Backward(void) +{ + double Deri_Speed_Robot_MAX = GV.Robot_Move_Speed * 1.5; + double Robot_Speed[4] = {0, 0, 0, 0}; + double robotDeriAngleDegGrity=0; + //GV.weld_data_X = ReadLazorData->Feature_X; + float Robot_Weld_Real = GV.weld_data_X; + GF_MSP_PID_Now_Der_adj_Com_Weld(Robot_Weld_Real, robotDeriAngleDegGrity, GV.Robot_Move_Speed, Deri_Speed_Robot_MAX, 0.1, Robot_Speed); + + GV.Left_Speed_M_min = Robot_Speed[1]; + GV.Right_Speed_M_min = Robot_Speed[0]; +} + +static void handleHalt(void) +{ + GV.Left_Speed_M_min = 0; + GV.Right_Speed_M_min = 0; + GV.SwingMotor.Position_immediately1_Lag2=1; + GV.SwingMotor.Target_Velcity=0; + horizontal_s_currentState = 0; + vertical_s_currentState = 0; + ChangeRoad_currentState = 0; + s_currentState = 0; +} +/*=========================== 8.对外接口函数(需外部调用) ===========================*/ +void Move_Manual_Auto_Sub_Func(void) +{ + Fight_Countinus_Function_Manual(); +} + + +void Move_Horizontal_Auto_Sub_Func(void) +{ + s_activeFsm = FSM_HORIZONTAL_AUTO_Flag; + check_and_reset_fsm(FSM_HORIZONTAL_AUTO_Flag); + int state = s_fsmState[FSM_HORIZONTAL_AUTO_Flag]; + + if (state >= 0 && state < STATE_COUNT) { + if (horizontal_single_lane_auto_operation[state] != NULL) { + horizontal_single_lane_auto_operation[state](); + } else { + /* 遇到未实现的状态,停机处理 */ + handleHalt(); + } + } else { + handleHalt(); + } +} + +void Move_Vertical_Auto_Sub_Func(void) +{ + s_activeFsm = FSM_VERTICAL_AUTO_Flag; + check_and_reset_fsm(FSM_VERTICAL_AUTO_Flag); + int state = s_fsmState[FSM_VERTICAL_AUTO_Flag]; + + if (state >= 0 && state < STATE_COUNT) { + if (vertical_single_lane_auto_operation[state] != NULL) { + vertical_single_lane_auto_operation[state](); + } else { + /* 遇到未实现的状态,停机处理 */ + handleHalt(); + } + } else { + handleHalt(); + } +} + +void Weld_Auto_Sub_Func(void) +{ + s_activeFsm = WELD_AUTO_Flag; + check_and_reset_fsm(WELD_AUTO_Flag); + int state = s_fsmState[WELD_AUTO_Flag]; + + if (state >= 0 && state < STATE_COUNT) { + if (weld_auto_operation[state] != NULL) { + weld_auto_operation[state](); + } else { + /* 遇到未实现的状态,停机处理 */ + handleHalt(); + } + } else { + handleHalt(); + } +} + +void Change_Road_Func(void) +{ + s_activeFsm = FSM_VERTICAL_CHANGE_ROAD_Flag; + check_and_reset_fsm(FSM_VERTICAL_CHANGE_ROAD_Flag); + int state = s_fsmState[FSM_VERTICAL_CHANGE_ROAD_Flag]; + + if (state >= 0 && state < STATE_COUNT) { + if (vertical_lane_change_left[state] != NULL) { + vertical_lane_change_left[state](); + } else { + /* 遇到未实现的状态,停机处理 */ + handleHalt(); + } + } else { + handleHalt(); + } + +} + + + +void vertical_forward(void) +{ + s_activeFsm = FSM_VERTICAL_FORWARD_Flag; + check_and_reset_fsm(FSM_VERTICAL_FORWARD_Flag); + int state = s_fsmState[FSM_VERTICAL_FORWARD_Flag]; + + if (state >= 0 && state < STATE_COUNT) { + if (robot_vertical_drive[state] != NULL) { + robot_vertical_drive[state](); + } else { + /* 遇到未实现的状态,停机处理 */ + handleHalt(); + } + } else { + handleHalt(); + } + +} + +void horizontal_forward(void) +{ + s_activeFsm = FSM_HORIZONTAL_AUTO_Flag; + check_and_reset_fsm(FSM_HORIZONTAL_AUTO_Flag); + int state = s_fsmState[FSM_HORIZONTAL_AUTO_Flag]; + + if (state >= 0 && state < STATE_COUNT) { + if (robot_horizontal_drive[state] != NULL) { + robot_horizontal_drive[state](); + } else { + /* 遇到未实现的状态,停机处理 */ + handleHalt(); + } + } else { + handleHalt(); + } +} + +void horizontal_work(void) +{ + if (horizontal_s_currentState >= 0 && horizontal_s_currentState < STATE_COUNT) { + horizontal_single_lane_auto_operation[horizontal_s_currentState](); + } else { + handleHalt(); + } +} + +void swing_work(void) +{ + + if (swing_currentState >= 0 && swing_currentState < STATE_COUNT) { + if (swing_move_control[swing_currentState] != NULL) { + swing_move_control[swing_currentState](); + } else { + /* 遇到未实现的状态,停机处理 */ + handleHalt(); + } + } else { + handleHalt(); + } +} + + +/* 重置标志位,任何标志位都可以放到这里面重置*/ +void flag_reset(void) +{ + if(P_MK32->CH4_SA==0&&P_MK32->CH5_SB==0&&P_MK32->CH6_SC==0&&P_MK32->CH7_SD==0 + &&P_MK32->CH0_RY_H==0&&P_MK32->CH1_RY_V==0&&P_MK32->CH2_LY_V==0 + &&P_MK32->CH3_LY_H==0) + { + s_currentState = 0; + horizontal_s_currentState = 0; + vertical_s_currentState = 0; + ChangeRoad_currentState = 0; + swing_currentState = 0; + } + +} + +void Emergency_Stop_Action(void) +{ + GV.GroundManagementValue.MaualControlPower=1; + GV.GroundManagementValue.MaualPowerState=0; + + GV.SwingMotor.Position_immediately1_Lag2=1; + GV.Tar_Position_Velcity_Degree_S=0; + GV.Left_Speed_M_min=0; + GV.Right_Speed_M_min=0; + flag_reset(); +} + diff --git a/Bingoo/base/swing_action.c b/Bingoo/base/swing_action.c new file mode 100644 index 0000000..9cc7b61 --- /dev/null +++ b/Bingoo/base/swing_action.c @@ -0,0 +1,100 @@ +/* + * swing_action.c + * + * Created on: Mar 4, 2026 + * Author: 42961 + */ +#include "swing_action.h" +#include "Handset_Status_Setting.h" + +#include "fsm_state.h" +#include "BHBF_ROBOT.h" + + +#define TT_One_Deg_Count 11014///32768*121/360(减速比121)=11014 +#define LEFT_LIMIT 1 +#define RIGHT_LIMIT 2 +float Swing_Speed_Deg_Sencond=201.7;//HJ32-121 +int middle_position=-944334; +//int center_angle; +//int offset_angle; +//int center_position; //中间位置-944334 +int limit_record=0; +float left_compare_value=0; +float right_compare_value=0; +float left_compare_updata; +float right_compare_updata; + +int lef_positon=-569580; +int Right_positon=-1230420; + +//手动摆臂函数 +void Robot_Swing_Operation_Function() +{ + if(P_MK32->CH0_RY_H>500) + { + GV.SwingMotor.Position_immediately1_Lag2=1; + GV.Tar_Position_angle=90; + GV.Tar_Position_Velcity_Degree_S=GV.Robot_Swing_Speed; + + } + else if(P_MK32->CH0_RY_H<-500) + { + GV.SwingMotor.Position_immediately1_Lag2=1; + GV.Tar_Position_angle=-90; + GV.Tar_Position_Velcity_Degree_S=GV.Robot_Swing_Speed; + } + else + { + Move_Swing_Halt_Func_Do(); + } +} + + + +//摆臂电机左转延时生效 +void Move_Swing_Left_Func_Do_lay(void) +{ + GV.SwingMotor.Position_immediately1_Lag2=2; + GV.Tar_Position_angle=left_compare_value; + GV.Tar_Position_Velcity_Degree_S=GV.Robot_Swing_Speed; +} + +//摆臂电机右转延时生效 +void Move_Swing_Right_Func_Do_lay(void) +{ + + GV.SwingMotor.Position_immediately1_Lag2=2; + GV.Tar_Position_angle=right_compare_value; + GV.Tar_Position_Velcity_Degree_S=GV.Robot_Swing_Speed; +} + +//摆臂电机左转立即执行 +void Move_Swing_Left_Func_Do_imm(void) +{ + + GV.SwingMotor.Position_immediately1_Lag2=1; + + GV.Tar_Position_angle=left_compare_value; + GV.Tar_Position_Velcity_Degree_S=GV.Robot_Swing_Speed; + + +} + +//摆臂电机右转立即执行 +void Move_Swing_Right_Func_Do_imm(void) +{ + + GV.SwingMotor.Position_immediately1_Lag2=1; + GV.Tar_Position_angle=right_compare_value; + GV.Tar_Position_Velcity_Degree_S=GV.Robot_Swing_Speed; + +} + +void Move_Swing_Halt_Func_Do(void) +{ + GV.SwingMotor.Position_immediately1_Lag2=1; + GV.SwingMotor.Tar_Position_count=0; + GV.Tar_Position_Velcity_Degree_S=0; + +} diff --git a/Bingoo/base/tcp_server.c b/Bingoo/base/tcp_server.c new file mode 100644 index 0000000..5d17443 --- /dev/null +++ b/Bingoo/base/tcp_server.c @@ -0,0 +1,251 @@ +#include "tcp_server.h" +#include "lwip/tcp.h" +#include "lwip/memp.h" +#include +#include "lwip.h" + +#include "string.h" +#include "bsp_UDP.h" +#include "bsp_DLT_Log.h" +#include +#include "BSP/bsp_GPIO.h" +static client_conn_t clients[MAX_CLIENTS]; +static struct tcp_pcb *server_pcb = NULL; +void send_tcp(SendDataNode **head); +// 回调函数声明 +static err_t tcp_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err); +static err_t tcp_recv_cb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, + err_t err); +static void tcp_err_cb(void *arg, err_t err); +static void tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len); +SendDataNode *pTcpHead = NULL; /*初始化链表头指针,使其为空*/ +void tcp_server_timer_callback(); +char listIndex = 0; +SendDataNode* CreateSendDataNode(uint8_t *tx_Buf, uint8_t tx_count) +{ + SendDataNode *newNode = (SendDataNode*) malloc(sizeof(SendDataNode)); + if (newNode == NULL) + { + return NULL; + } + memcpy(newNode->Tx_Buf, tx_Buf, tx_count); + newNode->Tx_Count = tx_count; + newNode->next = NULL; + return newNode; +} + +void insertAtTail(SendDataNode **head, uint8_t *tx_Buf, uint8_t tx_count) +{ + SendDataNode *newNode = CreateSendDataNode(tx_Buf, tx_count); + // 如果链表为空 + if (*head == NULL) + { + + *head = newNode; + return; + } + listIndex = 0; + // 遍历到链表尾部 + SendDataNode *current = *head; + while (current->next != NULL) + { +// listIndex++; +// if (listIndex >= 50) +// { +// free(current); +// return; +// } + current = current->next; + } + //SendDataNode *newNode = CreateSendDataNode(tx_Buf, tx_count); + current->next = newNode; // 尾部节点指向新节点 + +} + +void tcp_add_sendList(uint8_t *tx_Buf, uint8_t tx_count) +{ + + for (int i = 0; i < MAX_CLIENTS; i++) + { + if (clients[i].active) + { + insertAtTail(&pTcpHead, tx_Buf, tx_count); + return; + } + } +} + +void send_tcp(SendDataNode **head) +{ + if (*head == NULL) + { + return; + } + tcp_send_to_all_clients((*head)->Tx_Buf, (*head)->Tx_Count); + SendDataNode *temp = *head; + *head = (*head)->next; + free(temp); + +} + +// 初始化TCP服务器 +void tcp_server_init(uint16_t port) +{ + GF_BSP_Interrupt_Add_CallBack( + DF_BSP_InterCall_TIM8_2ms_PeriodElapsedCallback, + tcp_server_timer_callback); + err_t err; + + // 创建TCP控制块 + server_pcb = tcp_new_ip_type(IPADDR_TYPE_ANY); + if (!server_pcb) return; + + // 绑定到指定端口 + err = tcp_bind(server_pcb, IP_ANY_TYPE, port); + if (err != ERR_OK) + { + memp_free(MEMP_TCP_PCB, server_pcb); + server_pcb = NULL; + return; + } + + // 开始监听 + server_pcb = tcp_listen(server_pcb); + if (!server_pcb) return; + + // 设置接受连接回调 + tcp_accept(server_pcb, tcp_accept_cb); + + // 初始化客户端数组 + memset(clients, 0, sizeof(clients)); + +} + +// 接受新连接回调 +static err_t tcp_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(err); + + // 查找空闲的客户端槽位 + int free_index = -1; + for (int i = 0; i < MAX_CLIENTS; i++) + { + if (!clients[i].active) + { + free_index = i; + break; + } + } + + if (free_index == -1) + { + // 没有可用槽位,拒绝连接 + tcp_abort(newpcb); + return ERR_ABRT; + } + + // 配置新连接 + tcp_setprio(newpcb, TCP_PRIO_MIN); + tcp_recv(newpcb, tcp_recv_cb); + tcp_err(newpcb, tcp_err_cb); + tcp_sent(newpcb, tcp_sent_cb); + + // 保存客户端信息 + clients[free_index].pcb = newpcb; + clients[free_index].active = 1; + + return ERR_OK; +} + +// 接收数据回调 +static err_t tcp_recv_cb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, + err_t err) +{ + LWIP_UNUSED_ARG(arg); + + if (!p) + { + // 连接关闭 + for (int i = 0; i < MAX_CLIENTS; i++) + { + if (clients[i].pcb == tpcb) + { + clients[i].active = 0; + break; + } + } + tcp_close(tpcb); + return ERR_OK; + } + + // 处理接收到的数据(这里简单释放) + tcp_recved(tpcb, p->tot_len); + pbuf_free(p); + + return ERR_OK; +} + +// 错误回调 +static void tcp_err_cb(void *arg, err_t err) +{ + LWIP_UNUSED_ARG(err); + + for (int i = 0; i < MAX_CLIENTS; i++) + { + if (clients[i].pcb == arg) + { + clients[i].active = 0; + break; + } + } +} + +// 数据发送完成回调 +static void tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len) +{ + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(tpcb); + LWIP_UNUSED_ARG(len); + // 可在此实现流量控制 +} + +// 向所有活跃客户端发送数据 +void tcp_send_to_all_clients(const char *data, uint16_t len) +{ + for (int i = 0; i < MAX_CLIENTS; i++) + { + if (clients[i].active) + { + //clients[i].pcb->flags= +// err_t err = tcp_write(clients[i].pcb, data, len, +// TCP_WRITE_FLAG_COPY); + err_t err = tcp_write(clients[i].pcb, data, len, + TCP_WRITE_FLAG_COPY); + if (err == ERR_OK) + { + tcp_output(clients[i].pcb); + } + else + { + // 发送失败,关闭连接 + //clients[i].active = 0; + //tcp_close(clients[i].pcb); + } + } + } +} +int32_t counter = 0; +// 定时器回调(从主定时器中断调用) +void tcp_server_timer_callback() +{ + + counter++; + if (counter > 5) + { + counter = 0; + send_tcp(&pTcpHead); + }; + +} + diff --git a/Bingoo/include/base/BHBF_ROBOT.h b/Bingoo/include/base/BHBF_ROBOT.h new file mode 100644 index 0000000..28ed1ef --- /dev/null +++ b/Bingoo/include/base/BHBF_ROBOT.h @@ -0,0 +1,125 @@ +/* + * BHBF_ROBOT.h + * + * Created on: Oct 26, 2023 + * Author: shiya + */ + +#ifndef INC_BHBF_ROBOT_H_ +#define INC_BHBF_ROBOT_H_ + +#include +#include +#include +#include +#include +#include + + + +#include "BHBF_ROBOT.h" +#include "bsp_PV.pb.h" +#include "bsp_IV.pb.h" +#include "BSP/bsp_TCPClient.h" +#include "BSP/pb.h" +#include "BSP/pb_decode.h" +#include "BSP/pb_encode.h" +#include "BSP/bsp_EEPROM.h" +#include "BSP/bsp_pb_decode_encode.h" +#include "bsp_MB_host.h" +#include "BSP/bsp_include.h" +#include "BSP/bsp_UART.h" +#include "BSP/DLTuc.h" +#include "BSP/bsp_DLT_Log.h" + + +#include "BSP/bsp_cpu_flash.h" +#include "BSP/bsp_qspi_w25q128.h" +#include "BSP/bsp_UpperComputer_Handler.h" +#include "BSP/bsp_Error_Detect.h" +#include "BSP/bsp_MB_host.h" + +#include "MSP/msp_JTBATTERY.h" + +#include "MSP/msp_Force_Sensor.h" +#include "MSP/msp_TL720D.h" +#include "MSP/msp_MK32_1.h" +#include "MSP/msp_Force_Sensor.h" +#include "MSP/msp_WH_LTE_7S0.h" + + +#include "paint_gun_action.h" +#include "fsm_state_control.h" +#include "change_line_control.h" +#include "fsm_state.h" +#include "robot_move_actions.h" + +//#include "robot_state.h" +//FLASH (rx) : ORIGIN = 0x08020000, LENGTH = 896K +//#define VECT_TAB_OFFSET 0x00020000U + + + + +#define DLTViewer 1 + + +extern bool CompareTimer_Delay(int32_t Delay); + +extern GV_struct_define GV; +extern IV_struct_define IV; +extern CV_struct_define CV; +extern PV_struct_define decoded_PV; +extern PV_struct_define decoded_PV_variable; + +typedef struct sys_timer_handler +{ + int start_timer; + int sys_current_timer_count; + int sys_timer_flag; + +}Sys_timer_handler; + +extern Sys_timer_handler timer_handler_1; +extern Sys_timer_handler timer_handler_2; +extern Sys_timer_handler timer_handler_3; +extern Sys_timer_handler timer_handler_4; + +//first start Timer, then WaitTimer +extern bool CompareTimer(int32_t DelayMiliSeconds,Sys_timer_handler * timer_handler); +extern void SystemTimer_Intialize(); +extern void GF_Timer_Count(); +extern void GF_Robot_Init(void); +extern void GF_Robot_MainLoop(void); +extern void GF_WatchDog_Loop(void); +extern int32_t speed_M_min_toE01_M_min(int32_t speedm_min); + + extern void SET_BIT_1(int32_t* num,int32_t k); + + extern void SET_BIT_0(int32_t* num,int32_t k); + extern int32_t Get_BIT(int32_t* num,int32_t k); + +//A &= ~(1 << bit) + + + +extern int32_t* SystemErrorCode; +extern ErrorData* SystemErrorData; + +#define IV_Run_Mode_Maunal 0 +#define IV_Run_Mode_Automation 1 +#define IV_Run_Mode_EmergencyStop 2 +#define IV_Run_Mode_Vertical_LaneChange 3 +#define IV_Run_Mode_Horizontal_LaneChange 4 +#define IV_Run_Mode_Forward 5 +#define IV_Run_Mode_BackWard 6 +#define IV_Run_Mode_TurnLeft 7 +#define IV_Run_Mode_TurnRight 8 +#define IV_Run_Mode_HALT 9 + +//extern LS_MotorParameters* Frames_Motor[4]; + + +extern int32_t SystemTimeMiliCount; //2ms加一 + +#endif /* INC_BHBF_ROBOT_H_ */ diff --git a/Bingoo/include/base/DLTuc.h b/Bingoo/include/base/DLTuc.h new file mode 100644 index 0000000..d3453e7 --- /dev/null +++ b/Bingoo/include/base/DLTuc.h @@ -0,0 +1,248 @@ +/** + * @file DLTuc.h + * @author teodor + * @date 1 Jul 2022 + * @brief This file is a part of DLTuc library + * + * In this header, you can find types, Api functions, which are provided by DLTuc library + * Usefull macros, for convience usage of DLTuc library in logging purposes + * + * Requirments: + * Around ~2kB of RAM + * Check Configuration file and defines: + * DLT_TRANSMIT_RING_BUFFER_SIZE, DLT_TRANSMIT_MAX_SINGLE_MESSAGE_SIZE + * + */ + +#ifndef INC_DLT_LOGS_MCU_H_ +#define INC_DLT_LOGS_MCU_H_ + +/* + * ******************************************************************************************* + * Includes + * ******************************************************************************************* + * */ + +#include "stdint.h" +#include +#include + +#include "DLTucConfig.h" + +/* + * ******************************************************************************************* + * Exported defines + * ******************************************************************************************* + * */ + +/*@brief + * + * - convert the To strings to uint32_t + */ +#define DLT_LOG_ECUID_VALUE ((uint32_t)((((uint32_t) ((uint8_t)DLT_LOG_ECUID[0])) << 24UL) | \ + (((uint32_t) ((uint8_t)DLT_LOG_ECUID[1])) << 16UL) | \ + (((uint32_t) ((uint8_t)DLT_LOG_ECUID[2])) << 8UL) | \ + ((uint32_t)((uint8_t)DLT_LOG_ECUID[3])))) + + +#define DLT_LOG_APPID_VALUE ((uint32_t)((((uint32_t) ((uint8_t)DLT_LOG_APPID[0])) << 24UL) | \ + (((uint32_t) ((uint8_t)DLT_LOG_APPID[1])) << 16UL) | \ + (((uint32_t) ((uint8_t)DLT_LOG_APPID[2])) << 8UL) | \ + ((uint32_t)((uint8_t)DLT_LOG_APPID[3])))) + + +#define DLT_LOG_CONTEX_VALUE ((uint32_t)((((uint32_t) ((uint8_t)DLT_LOG_CONTEX[0])) << 24UL) | \ + (((uint32_t) ((uint8_t)DLT_LOG_CONTEX[1])) << 16UL) | \ + (((uint32_t) ((uint8_t)DLT_LOG_CONTEX[2])) << 8UL) | \ + ((uint32_t)((uint8_t)DLT_LOG_CONTEX[3])))) + + + + +/* + * Definitions of DLT services. + */ +#define DLT_SERVICE_ID_SET_LOG_LEVEL 0x01 /**< Service ID: Set log level */ +#define DLT_SERVICE_ID_SETRACE_STATUS 0x02 /**< Service ID: Set trace status */ +#define DLT_SERVICE_ID_GET_LOG_INFO 0x03 /**< Service ID: Get log info */ +#define DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL 0x04 /**< Service ID: Get dafault log level */ +#define DLT_SERVICE_ID_STORE_CONFIG 0x05 /**< Service ID: Store configuration */ +#define DLT_SERVICE_ID_RESETO_FACTORY_DEFAULT 0x06 /**< Service ID: Reset to factory defaults */ +#define DLT_SERVICE_ID_SET_COM_INTERFACE_STATUS 0x07 /**< Service ID: Set communication interface status */ +#define DLT_SERVICE_ID_SET_COM_INTERFACE_MAX_BANDWIDTH 0x08 /**< Service ID: Set communication interface maximum bandwidth */ +#define DLT_SERVICE_ID_SET_VERBOSE_MODE 0x09 /**< Service ID: Set verbose mode */ +#define DLT_SERVICE_ID_SET_MESSAGE_FILTERING 0x0A /**< Service ID: Set message filtering */ +#define DLT_SERVICE_ID_SETIMING_PACKETS 0x0B /**< Service ID: Set timing packets */ +#define DLT_SERVICE_ID_GET_LOCALIME 0x0C /**< Service ID: Get local time */ +#define DLT_SERVICE_ID_USE_ECU_ID 0x0D /**< Service ID: Use ECU id */ +#define DLT_SERVICE_ID_USE_SESSION_ID 0x0E /**< Service ID: Use session id */ +#define DLT_SERVICE_ID_USEIMESTAMP 0x0F /**< Service ID: Use timestamp */ +#define DLT_SERVICE_ID_USE_EXTENDED_HEADER 0x10 /**< Service ID: Use extended header */ +#define DLT_SERVICE_ID_SET_DEFAULT_LOG_LEVEL 0x11 /**< Service ID: Set default log level */ +#define DLT_SERVICE_ID_SET_DEFAULTRACE_STATUS 0x12 /**< Service ID: Set default trace status */ +#define DLT_SERVICE_ID_GET_SOFTWARE_VERSION 0x13 /**< Service ID: Get software version */ +#define DLT_SERVICE_ID_MESSAGE_BUFFER_OVERFLOW 0x14 /**< Service ID: Message buffer overflow */ +#define DLT_SERVICE_ID_CALLSW_CINJECTION 0xFFF /**< Service ID: Message Injection (minimal ID) */ + +/* + * ******************************************************************************************* + * Exported types + * ******************************************************************************************* + * */ + +/**! + * \brief DltLogLevel_t + * \details Typdef used to identify the DLT log level + * */ +typedef enum +{ + DL_FATAL =1, + DL_ERROR =2, + DL_WARN =3, + DL_INFO =4, + DL_DEBUG =5, + DL_VERBOSE =6, +}DltLogLevel_t; + + + + + +/* + * ******************************************************************************************* + * Exported function - API + * ******************************************************************************************* + * */ + +/*! + ************************************************************************************************ + * \brief DLTuc_RawDataReceiveDone + * \details OPTIONAL - Use only if you need handle data receive, like Injection messages + * Call the function to inform DLTuc that Raw data packet has been received + ************************************************************************************************/ +void DLTuc_RawDataReceiveDone(uint16_t Size); + +/*! + ************************************************************************************************ + * \brief DLTuc_RegisterReceiveSerialDataFunction + * \details OPTIONAL - Use only if you need handle data receive, like Injection messages. + * - Register callback function which will be used by DLTuc to start data receive process. + * The Callback function is basicly called only after registration and if data packet has been received, + * to start again receive data packet + * \param in LLSerialRecDataFunctionC ... + ************************************************************************************************/ +void DLTuc_RegisterReceiveSerialDataFunction(void LLSerialRecDataFunctionC(uint8_t *DltLogData, uint16_t Size)); + +/*! + ************************************************************************************************ + * \brief DLTuc_RegisterInjectionDataReceivedCb + * \details OPTIONAL - Use only if you need handle data receive, like Injection messages + * Register injection data received call back + * Use the function if you want register call back function to handle the Injection messages in your application + * \param in InjectionDataRcvd ... + ************************************************************************************************/ +void DLTuc_RegisterInjectionDataReceivedCb + (void InjectionDataRcvd(uint32_t AppId, uint32_t ConId,uint32_t ServId,uint8_t *Data, uint16_t Size)); + +/*! + ************************************************************************************************ + * \brief DLTuc_RegisterTransmitSerialDataFunction + * \details This simple stack/library must be initialized by "DLTuc_RegisterTransmitSerialDataFunction" + * As a parameter must be passed function which will transmit serial data + * \param in LLSerialTrDataFunctionC transmit function pointer + ************************************************************************************************/ +void DLTuc_RegisterTransmitSerialDataFunction(void LLSerialTrDataFunctionC(uint8_t *DltLogData, uint8_t Size)); + +/*! + ************************************************************************************************ + * \brief DLTuc_RegisterGetTimeStampMsCallback + * \details function to update time stamp in library +* \param in GetSysTime - pointer to function which allow to read system time in msec + *************************************************************************************************/ +void DLTuc_RegisterGetTimeStampMsCallback(uint32_t GetSysTime(void)); + + +/*! + ************************************************************************************************ + * \brief DLTuc_MessageTransmitDone + * \details IMPORTANT!!!!! + * Call this function when the transsmision is end + * For example in "DMA transmission end callback" to inform the lib that the message is transmitted + ************************************************************************************************ + * */ +void DLTuc_MessageTransmitDone(void); + +/*! + ************************************************************************************************ + * \brief DLTuc_LogOutVarArgs + * \details default function to create DLT Log + * \param DltLogLevel_t Level - of Dlt log + * \param in AppId - size of the "DltLogData" (return value) + * \param in ContextId - pointer to the message stored in RingBuffer (return value) + * \param in Payload String to send as dlt log + * \param in ... parameters same as in printf function + *************************************************************************************************/ +void DLTuc_LogOutVarArgs(DltLogLevel_t Level, uint32_t AppId, uint32_t ContextId, uint8_t *Payload, ...); + + +/* + * ******************************************************************************************* + * Additional macros to facilitate the use of the library + * ******************************************************************************************* + * */ + +#ifdef LOGS_ENABLE + +/**! + * \brief LOGL(level, str, ...) + * \details Transmit DltLog using function DLTuc_LogOutVarArgs but user don't have to add + * log_level, DLT_LOG_APPID_VALUE and DLT_LOG_CONTEX_VALUE + * + * */ +#define LOG(str, ...)\ + if(DL_INFO <= DLT_LOG_ENABLE_LEVEL){\ + DLTuc_LogOutVarArgs(DL_INFO, DLT_LOG_APPID_VALUE, DLT_LOG_CONTEX_VALUE,(uint8_t *) str, ##__VA_ARGS__);\ + } + +/**! + * \brief LOGL(level, str, ...) + * \details Transmit DltLog using function DLTuc_LogOutVarArgs but user don't have to add DLT_LOG_APPID_VALUE and DLT_LOG_CONTEX_VALUE + * + * */ +#define LOGL(log_level, str, ...)\ + if(log_level <= DLT_LOG_ENABLE_LEVEL){\ + DLTuc_LogOutVarArgs(log_level, DLT_LOG_APPID_VALUE, DLT_LOG_CONTEX_VALUE,(uint8_t *) str, ##__VA_ARGS__);\ + } + +/**! + * @brief LOGF(log_level, str, ...) + * \details Transmit DltLog using function DLTuc_LogOutVarArgs but user don't have to add DLT_LOG_APPID_VALUE and DLT_LOG_CONTEX_VALUE + * Additionally add the name of the calling function + * + * + * */ +#define LOGF(log_level, str, ...)\ + if(log_level <= DLT_LOG_ENABLE_LEVEL){\ + DLTuc_LogOutVarArgs(log_level, DLT_LOG_APPID_VALUE, DLT_LOG_CONTEX_VALUE,(uint8_t *) "FUN:%s LOG: "str, __FUNCTION__,##__VA_ARGS__);\ + } + +/**! + * \brief LOGFF(log_level, str, ...) + * \details Transmit DltLog using function DLTuc_LogOutVarArgs but user don't have to add DLT_LOG_APPID_VALUE and DLT_LOG_CONTEX_VALUE + * Additionally add the name of the calling function and file name + * + * + * */ +#define LOGFF(log_level, str, ...)\ + if(log_level <= DLT_LOG_ENABLE_LEVEL){\ + DLTuc_LogOutVarArgs(log_level, DLT_LOG_APPID_VALUE, DLT_LOG_CONTEX_VALUE,(uint8_t *)"FILE:%s LINE: %d FUN:%s LOG: "str,__FILE__,__LINE__,__FUNCTION__,##__VA_ARGS__);\ + } + +#else +LOG(str, ...) +LOGL(log_level, str, ...) +LOGF(log_level, str, ...) +LOGFF(log_level, str, ...) +#endif + +#endif /* INC_DLT_LOGS_MCU_H_ */ diff --git a/Bingoo/include/base/DLTucConfig.h b/Bingoo/include/base/DLTucConfig.h new file mode 100644 index 0000000..25df93b --- /dev/null +++ b/Bingoo/include/base/DLTucConfig.h @@ -0,0 +1,74 @@ +/** + * @file DLTuc.c + * @author teodor + * @date 1 Jul 2022 + * @brief This file is a part of DLTuc library + * + * In this header file is placed DLTuc configuration template + * + */ + +#if 1 /*Set it to "1" to enable content*/ + +#ifndef __DLT_CONFIG__ + +/*Comment this line to turn off all logs..*/ +#define LOGS_ENABLE + +/*Pass here the entry critical entry function for your RTOS or + Interrupt block functions if you want use the library from diffrent context*/ +#define DLTuc_OS_CRITICAL_START() +#define DLTuc_OS_CRITICAL_END() + + +/*Default minimum log level to transmit the log*/ +//#ifndef DLT_LOG_ENABLE_LEVEL +////#define DLT_LOG_ENABLE_LEVEL DL_VERBOSE +// #define DLT_LOG_ENABLE_LEVEL 0 +//#endif + +extern char DLT_LOG_ENABLE_LEVEL; + + +/**! +* \brief DLT_LOG_CONTEX +* \details to define the minimum level log which will printed using the debug macros +* +*/ +#ifndef DLT_LOG_CONTEX +#define DLT_LOG_CONTEX "DFLT" +#endif + +/**! +* \brief DLT_LOG_APPID +* \details to define the minimum level log which will printed using the debug macros +* +*/ +#ifndef DLT_LOG_APPID +#define DLT_LOG_APPID "0000" +#endif + +/**! +* \brief DLT_LOG_ECUID +* \details you can define here you ECUID .. +* +*/ +#define DLT_LOG_ECUID "uCID" /*Electronic Controller Unit ID*/ + +#define DLT_ECU_SW_VER 0001 + +/* +*@brief DLT_TRANSMIT_MAX_SINGLE_MESSAGE_SIZE & DLT_TRANSMIT_RING_BUFFER_SIZE +* these values define the size of the circular buffer and the maximum size of a single DLT message +* Size of out Circular DLT messages buffer is equal: DLT_TRANSMIT_MAX_SINGLE_MESSAGE_SIZE*DLT_TRANSMIT_RING_BUFFER_SIZE +*/ +#define DLT_TRANSMIT_MAX_SINGLE_MESSAGE_SIZE 255 +#define DLT_TRANSMIT_RING_BUFFER_SIZE 15 + + +#define DLT_REC_SINGLE_MESSAGE_MAX_SIZE 255 +#define DLT_RECEIVE_RING_BUFFER_SIZE 2 + +#endif //__DLT_CONFIG__ + +#endif //Content enable diff --git a/Bingoo/include/base/Handset_Status_Setting.h b/Bingoo/include/base/Handset_Status_Setting.h new file mode 100644 index 0000000..6520623 --- /dev/null +++ b/Bingoo/include/base/Handset_Status_Setting.h @@ -0,0 +1,73 @@ +/* + * Handset_Status_Setting.h + * + * Created on: 2026年1月15日 + * Author: bm673 + */ + +#ifndef FSM_INC_HANDSET_STATUS_SETTING_H_ +#define FSM_INC_HANDSET_STATUS_SETTING_H_ + +// 按键定义 +typedef enum { + EMERGENCE_STOP=0, // SE和SF同时按下触发急停 + INPUT_NONE , // 无输入 + // 摇杆方向 + INPUT_ROCKER_STOP, // 摇杆停止 + INPUT_ROCKER_FORWARD, // 摇杆前进 + INPUT_ROCKER_BACKWARD, // 摇杆后退 + INPUT_ROCKER_TURN_LEFT, // 摇杆左转 + INPUT_ROCKER_TURN_RIGHT, // 摇杆右转 + // 按键 + INPUT_KEY_LANE_CHANGE_UP, // CH4_SA = -1000 换道上 + INPUT_KEY_LANE_CHANGE_DOWN, // CH4_SA = 1000 换道下 + INPUT_KEY_FORWARD_CRUISE, // CH5_SB = -1000 前进巡航 + INPUT_KEY_BACKWARD_CRUISE, // CH5_SB = 1000 后退巡航 + INPUT_KEY_AUTO_WORK_UP, // CH7_SD = -1000 自动作业上 + INPUT_KEY_AUTO_WORK_DOWN, // CH7_SD = 1000 自动作业下 + INPUT_KEY_AUTO_WELD, // CH6_SC = -1000 焊缝跟踪 + //摆臂 + INPUT_ROCKER_SWING, //动摆臂了 + + + KEY_COUNT, // 输入总数 + +} InputEvent; + +// 主状态枚举,串口状态定义 +typedef enum { + Serial_Mode_Config, + Action_Execute, + Action_Shut_down, + MAIN_STATE_COUNT +} MainState; + +// 机器人模式枚举 +typedef enum { + Halt_Mode = 0, + Manual_Mode, + Horizontal_Mode, + Flat_Mode, + Vertical_Mode_Left, + Vertical_Mode_Right, + Regional_Horizontal_Automatic_Task, + Regional_Flat_Automatic_Task, + MODE_COUNT // 模式总数 +} Robot_Mode; + +// IO状态枚举 +typedef enum { + IO_STATE_NONE, + IO_STATE_RISE, + IO_STATE_DESCEND +} IO_State; + +// 函数声明 + +Robot_Mode RobotRockerState(void); +InputEvent RemoteControl_GetKeyIndex(Robot_Mode current_mode); +void PV_control(void); +void IV_control(void); +IO_State GetIOState(void); + +#endif /* FSM_INC_HANDSET_STATUS_SETTING_H_ */ diff --git a/Bingoo/include/base/bsp_CV.pb.h b/Bingoo/include/base/bsp_CV.pb.h new file mode 100644 index 0000000..d107c68 --- /dev/null +++ b/Bingoo/include/base/bsp_CV.pb.h @@ -0,0 +1,125 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_BSP_CV_PB_H_INCLUDED +#define PB_BSP_CV_PB_H_INCLUDED +#include "pb.h" +#include "bsp_PV.pb.h" +#include "bsp_PID.pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +typedef struct _CV_struct_define { + int32_t Speed_m_per_min; /* MPMin = 1m/min 1米每分钟 m/min */ + int32_t LeftTurnSpeed; + int32_t RightTurnSpeed; + int32_t RobotLeftAngleValue; /* 水平左方向 单位0.01° */ + int32_t RobotRightAngleValue; /* 水平右方向角度值 单位0.01° */ + int32_t RobotUpAngleValue; /* 竖直方向角度值 单位0.01° */ + int32_t RobotDownAngleValue; /* 竖直向下角度值 单位0.01° */ + int32_t Robot_Permitted_Angler_Error_Value_E_2D; /* 作业时需用的最大角度偏差值 0.01°,超出将停止作业 */ + int32_t Robot_Angle_Start_BaseE_2D; /* 角度值 0.01° */ + int32_t Lane_Change_Speed_m_per_min; + int32_t Is_Automation_Authorized; + int32_t Is_Function_Authorized; + int32_t Joy_Sticker_Angle_Allowance; /* 例如在90度的±30° */ + int32_t Joy_Sticker_Value_Allowance; /* 例如 joysticker的值超过600 */ + int32_t Allowable_Error_For_Angle_Tracking; /* 纠偏角度跟踪的允许误差1 度 */ + int32_t Paint_Gun_Shutdown_Distance; /* 喷枪关闭距离,喷枪关闭后多上厘米停止运行 */ + int32_t Horizontal_ChangeLane_Compensation; /* 水平换道补偿距离 */ + int32_t Vertical_ChangeLane_Compensation; /* 竖直换道补偿距离 */ + int32_t pulse_Per_Circle; /* 每转多少脉冲 */ + int32_t wheel_Reduction_Ratio; /* 减速比 */ + double wheel_Diameter_m; /* 车轮直径 m */ + bool has_PID_high; + PID_Parameters PID_high; + bool has_PID_mid; + PID_Parameters PID_mid; + bool has_PID_low; + PID_Parameters PID_low; +} CV_struct_define; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define CV_struct_define_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, PID_Parameters_init_default, false, PID_Parameters_init_default, false, PID_Parameters_init_default} +#define CV_struct_define_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, PID_Parameters_init_zero, false, PID_Parameters_init_zero, false, PID_Parameters_init_zero} + +/* Field tags (for use in manual encoding/decoding) */ +#define CV_struct_define_Speed_m_per_min_tag 1 +#define CV_struct_define_LeftTurnSpeed_tag 2 +#define CV_struct_define_RightTurnSpeed_tag 3 +#define CV_struct_define_RobotLeftAngleValue_tag 4 +#define CV_struct_define_RobotRightAngleValue_tag 5 +#define CV_struct_define_RobotUpAngleValue_tag 6 +#define CV_struct_define_RobotDownAngleValue_tag 7 +#define CV_struct_define_Robot_Permitted_Angler_Error_Value_E_2D_tag 8 +#define CV_struct_define_Robot_Angle_Start_BaseE_2D_tag 9 +#define CV_struct_define_Lane_Change_Speed_m_per_min_tag 10 +#define CV_struct_define_Is_Automation_Authorized_tag 11 +#define CV_struct_define_Is_Function_Authorized_tag 12 +#define CV_struct_define_Joy_Sticker_Angle_Allowance_tag 13 +#define CV_struct_define_Joy_Sticker_Value_Allowance_tag 14 +#define CV_struct_define_Allowable_Error_For_Angle_Tracking_tag 15 +#define CV_struct_define_Paint_Gun_Shutdown_Distance_tag 16 +#define CV_struct_define_Horizontal_ChangeLane_Compensation_tag 17 +#define CV_struct_define_Vertical_ChangeLane_Compensation_tag 18 +#define CV_struct_define_pulse_Per_Circle_tag 19 +#define CV_struct_define_wheel_Reduction_Ratio_tag 20 +#define CV_struct_define_wheel_Diameter_m_tag 21 +#define CV_struct_define_PID_high_tag 22 +#define CV_struct_define_PID_mid_tag 23 +#define CV_struct_define_PID_low_tag 24 + +/* Struct field encoding specification for nanopb */ +#define CV_struct_define_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, Speed_m_per_min, 1) \ +X(a, STATIC, SINGULAR, INT32, LeftTurnSpeed, 2) \ +X(a, STATIC, SINGULAR, INT32, RightTurnSpeed, 3) \ +X(a, STATIC, SINGULAR, INT32, RobotLeftAngleValue, 4) \ +X(a, STATIC, SINGULAR, INT32, RobotRightAngleValue, 5) \ +X(a, STATIC, SINGULAR, INT32, RobotUpAngleValue, 6) \ +X(a, STATIC, SINGULAR, INT32, RobotDownAngleValue, 7) \ +X(a, STATIC, SINGULAR, INT32, Robot_Permitted_Angler_Error_Value_E_2D, 8) \ +X(a, STATIC, SINGULAR, INT32, Robot_Angle_Start_BaseE_2D, 9) \ +X(a, STATIC, SINGULAR, INT32, Lane_Change_Speed_m_per_min, 10) \ +X(a, STATIC, SINGULAR, INT32, Is_Automation_Authorized, 11) \ +X(a, STATIC, SINGULAR, INT32, Is_Function_Authorized, 12) \ +X(a, STATIC, SINGULAR, INT32, Joy_Sticker_Angle_Allowance, 13) \ +X(a, STATIC, SINGULAR, INT32, Joy_Sticker_Value_Allowance, 14) \ +X(a, STATIC, SINGULAR, INT32, Allowable_Error_For_Angle_Tracking, 15) \ +X(a, STATIC, SINGULAR, INT32, Paint_Gun_Shutdown_Distance, 16) \ +X(a, STATIC, SINGULAR, INT32, Horizontal_ChangeLane_Compensation, 17) \ +X(a, STATIC, SINGULAR, INT32, Vertical_ChangeLane_Compensation, 18) \ +X(a, STATIC, SINGULAR, INT32, pulse_Per_Circle, 19) \ +X(a, STATIC, SINGULAR, INT32, wheel_Reduction_Ratio, 20) \ +X(a, STATIC, SINGULAR, DOUBLE, wheel_Diameter_m, 21) \ +X(a, STATIC, OPTIONAL, MESSAGE, PID_high, 22) \ +X(a, STATIC, OPTIONAL, MESSAGE, PID_mid, 23) \ +X(a, STATIC, OPTIONAL, MESSAGE, PID_low, 24) +#define CV_struct_define_CALLBACK NULL +#define CV_struct_define_DEFAULT NULL +#define CV_struct_define_PID_high_MSGTYPE PID_Parameters +#define CV_struct_define_PID_mid_MSGTYPE PID_Parameters +#define CV_struct_define_PID_low_MSGTYPE PID_Parameters + +extern const pb_msgdesc_t CV_struct_define_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define CV_struct_define_fields &CV_struct_define_msg + +/* Maximum encoded size of messages (where known) */ +#define BSP_CV_PB_H_MAX_SIZE CV_struct_define_size +#define CV_struct_define_size 358 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/bsp_Cmd.pb.h b/Bingoo/include/base/bsp_Cmd.pb.h new file mode 100644 index 0000000..602e930 --- /dev/null +++ b/Bingoo/include/base/bsp_Cmd.pb.h @@ -0,0 +1,80 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_BSP_CMD_PB_H_INCLUDED +#define PB_BSP_CMD_PB_H_INCLUDED +#include "pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +/* this message is used for the computer to send command */ +typedef struct _Cmd { + int32_t CommadNum; + /* 定义 1 上位机获取默认CV值 +定义 2 下位机返回CV值 +定义 3 上位机设定CV值 +定义 4 上位机设定Trace等级值,无返回 +定义 5 下位机上传位置点数据 +定义 6 上位机设定编码器角度值为0 +定义 7 上位机获取拟合点 +定义 8 上位机获取位置点 +定义 9 上位机向下位机下发程序 此时,Parameter0 下发的程序起始位,Parameter0 是校验位 +Buff_Data_Length 是下发的字节数, */ + int32_t Parameter0; + int32_t Parameter1; + int32_t Parameter2; + int32_t Parameter3; + int32_t Parameter4; + int32_t Buff_Data_Length; + pb_byte_t Buff_Data[512]; +} Cmd; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define Cmd_init_default {0, 0, 0, 0, 0, 0, 0, {0}} +#define Cmd_init_zero {0, 0, 0, 0, 0, 0, 0, {0}} + +/* Field tags (for use in manual encoding/decoding) */ +#define Cmd_CommadNum_tag 1 +#define Cmd_Parameter0_tag 2 +#define Cmd_Parameter1_tag 3 +#define Cmd_Parameter2_tag 4 +#define Cmd_Parameter3_tag 5 +#define Cmd_Parameter4_tag 6 +#define Cmd_Buff_Data_Length_tag 7 +#define Cmd_Buff_Data_tag 8 + +/* Struct field encoding specification for nanopb */ +#define Cmd_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, CommadNum, 1) \ +X(a, STATIC, SINGULAR, INT32, Parameter0, 2) \ +X(a, STATIC, SINGULAR, INT32, Parameter1, 3) \ +X(a, STATIC, SINGULAR, INT32, Parameter2, 4) \ +X(a, STATIC, SINGULAR, INT32, Parameter3, 5) \ +X(a, STATIC, SINGULAR, INT32, Parameter4, 6) \ +X(a, STATIC, SINGULAR, INT32, Buff_Data_Length, 7) \ +X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, Buff_Data, 8) +#define Cmd_CALLBACK NULL +#define Cmd_DEFAULT NULL + +extern const pb_msgdesc_t Cmd_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define Cmd_fields &Cmd_msg + +/* Maximum encoded size of messages (where known) */ +#define BSP_CMD_PB_H_MAX_SIZE Cmd_size +#define Cmd_size 592 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/bsp_DLT_Log.h b/Bingoo/include/base/bsp_DLT_Log.h new file mode 100644 index 0000000..52aaabf --- /dev/null +++ b/Bingoo/include/base/bsp_DLT_Log.h @@ -0,0 +1,16 @@ +/* + * bsp_DLT_Log.h + * + * Created on: Aug 8, 2024 + * Author: akeguo + */ + +#ifndef INC_BSP_BSP_DLT_LOG_H_ +#define INC_BSP_BSP_DLT_LOG_H_ + +#include "BHBF_ROBOT.h" + + +extern void dLT_Log_intialize(struct UARTHandler *Handler); +extern void dLT_Log_intialize_udp_tcp(); +#endif /* INC_BSP_BSP_DLT_LOG_H_ */ diff --git a/Bingoo/include/base/bsp_EEPROM.h b/Bingoo/include/base/bsp_EEPROM.h new file mode 100644 index 0000000..7da52ce --- /dev/null +++ b/Bingoo/include/base/bsp_EEPROM.h @@ -0,0 +1,73 @@ +/* + * bsp_EEPROM.h + * + * Created on: Oct 26, 2023 + * Author: shiya + */ + +#ifndef INC_BSP_EEPROM_H_ +#define INC_BSP_EEPROM_H_ + + + + +#include "bsp_include.h" +#include "bsp_CV.pb.h" +#include "bsp_IAP.pb.h" + + +#define EEPROM_WP_Pin GPIO_PIN_11 +#define EEPROM_WP_GPIO_Port GPIOE +#define EEPROM_SCL_Pin GPIO_PIN_12 +#define EEPROM_SCL_GPIO_Port GPIOE +#define EEPROM_SDA_Pin GPIO_PIN_13 +#define EEPROM_SDA_GPIO_Port GPIOE + +#define AT24C512 +#ifdef AT24C512 +#define EE_MODEL_NAME "AT24C512" +#define EE_DEV_ADDR 0xA0 /* 设备地址 */ +#define EE_PAGE_SIZE 128 /* 页面大小(字节) */ +#define EE_SIZE (512*128) /* 总容量(字节) */ // not used in this progrm +#define EE_ADDR_BYTES 2 /* 地址字节个数 */ +#endif + +#define I2C_WR 0 /* 写控制bit */ +#define I2C_RD 1 /* 读控制bit */ + +////////////////////////////////////////////////////////////////// +//there are 12M eeprom in total, and the code download Address is App_Download_EEPROM_Addr +//512 Pages x 128 Bytes = 65536 Bytes = 512 kbits + + +#define GF_BSP_EEPROM_CV_struct_define_Start_Address 0 +#define IAP_struct_define_Start_Address 512 + +extern uint16_t App_Download_EEPROM_Addr; + +//返回值::1-正常;0-错误 +uint8_t GF_BSP_EEPROM_Init(void); + +uint8_t GF_BSP_EEPROM_CheckOK(void); +uint8_t GF_BSP_EEPROM_ReadBytes(uint8_t *_pReadBuf, uint16_t _usAddress, + uint16_t _usSize); +uint8_t GF_BSP_EEPROM_WriteBytes(uint8_t *_pWriteBuf, uint16_t _usAddress, + uint16_t _usSize); + + + + +CV_struct_define GF_BSP_EEPROM_Get_CV(void); +uint8_t GF_BSP_EEPROM_Set_CV(CV_struct_define cv); + +IAP_struct_define GF_BSP_EEPROM_Get_IAP(void); +uint8_t GF_BSP_EEPROM_Set_IAP(IAP_struct_define iap); + + + +PV_struct_define GF_BSP_EEPROM_Get_PV(void); + +uint8_t GF_BSP_EEPROM_Set_PV(PV_struct_define pv); + + +#endif /* INC_BSP_EEPROM_H_ */ diff --git a/Bingoo/include/base/bsp_Error.pb.h b/Bingoo/include/base/bsp_Error.pb.h new file mode 100644 index 0000000..14ddd5c --- /dev/null +++ b/Bingoo/include/base/bsp_Error.pb.h @@ -0,0 +1,78 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_BSP_ERROR_PB_H_INCLUDED +#define PB_BSP_ERROR_PB_H_INCLUDED +#include "pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Enum definitions */ +typedef enum _ComError { + ComError_Mk32_SBus = 0, /* proto3版本中,首成员必须为0,成员不应有相同的值 */ + ComError_MK32_Serial = 1, + ComError_MK32_InitialState = 2, + ComError_TL720D = 3, + ComError_ZQ_CAN_ID1_LeftMotor = 4, + ComError_ZQ_CAN_ID2_RightMotor = 5, + ComError_ZQ_CAN_ID3_SwingMotor = 6, + ComError_Force_Sensor = 7, + ComError_Mfog40 = 8, + ComError_Ultrasonic_Sensor = 9, + ComError_UWB_20_Error = 10, + ComError_Strain_Gauge = 11, + ComError_Ground_Management = 12 +} ComError; + +/* Struct definitions */ +typedef struct _ErrorData { + int32_t Com_Error_Code; + int32_t Left_Motor_Error_Code; + int32_t Right_Motor_Error_Code; +} ErrorData; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Helper constants for enums */ +#define _ComError_MIN ComError_Mk32_SBus +#define _ComError_MAX ComError_Ground_Management +#define _ComError_ARRAYSIZE ((ComError)(ComError_Ground_Management+1)) + + + +/* Initializer values for message structs */ +#define ErrorData_init_default {0, 0, 0} +#define ErrorData_init_zero {0, 0, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define ErrorData_Com_Error_Code_tag 1 +#define ErrorData_Left_Motor_Error_Code_tag 2 +#define ErrorData_Right_Motor_Error_Code_tag 3 + +/* Struct field encoding specification for nanopb */ +#define ErrorData_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, Com_Error_Code, 1) \ +X(a, STATIC, SINGULAR, INT32, Left_Motor_Error_Code, 2) \ +X(a, STATIC, SINGULAR, INT32, Right_Motor_Error_Code, 3) +#define ErrorData_CALLBACK NULL +#define ErrorData_DEFAULT NULL + +extern const pb_msgdesc_t ErrorData_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define ErrorData_fields &ErrorData_msg + +/* Maximum encoded size of messages (where known) */ +#define BSP_ERROR_PB_H_MAX_SIZE ErrorData_size +#define ErrorData_size 33 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/bsp_Error_Detect.h b/Bingoo/include/base/bsp_Error_Detect.h new file mode 100644 index 0000000..12b92d5 --- /dev/null +++ b/Bingoo/include/base/bsp_Error_Detect.h @@ -0,0 +1,25 @@ +/* + * bsp_Error_Detect.h + * + * Created on: Oct 23, 2024 + * Author: akeguo + */ + +#ifndef INC_BSP_BSP_ERROR_DETECT_H_ +#define INC_BSP_BSP_ERROR_DETECT_H_ + + +/* Includes ------------------------------------------------------------------*/ +#include "BHBF_ROBOT.h" +#include "bsp_com_helper.h" +#include "BSP/bsp_include.h" +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +extern HardWareController *HardWareErrorController; +/* Exported functions ------------------------------------------------------- */ +extern char Error_Detect_Enable; +extern void Error_Detect_Intialzie(uint16_t DispacherPeriod); + + +#endif /* INC_BSP_BSP_ERROR_DETECT_H_ */ diff --git a/Bingoo/include/base/bsp_FDCAN.h b/Bingoo/include/base/bsp_FDCAN.h new file mode 100644 index 0000000..7796c5b --- /dev/null +++ b/Bingoo/include/base/bsp_FDCAN.h @@ -0,0 +1,84 @@ +/* + * bsp_FDCAN.h + * + * Created on: Oct 26, 2023 + * Author: shiya + */ + +#ifndef INC_BSP_FDCAN_H_ +#define INC_BSP_FDCAN_H_ +#include "bsp_Error.pb.h" +#include "bsp_com_helper.h" +uint8_t GF_BSP_FDCAN_Init(void); + +void GF_BSP_FDCAN_Senddata(uint8_t FDCAN_CH, uint32_t FrameID, + uint8_t DataLength, uint8_t *Txdata); + +extern uint8_t CAN_Buf[8]; + +extern uint8_t CAN_Buf[8]; +extern uint8_t CAN_Buf_2[8]; +typedef struct _CANSendHandler +{ + uint32_t CAN_ID; + uint32_t SendListTimePeriod; + uint8_t SendLength; + uint8_t Tx_Buf[8]; + void (*CAN_Decode)(uint32_t, uint8_t*, uint32_t); + struct _CANSendHandler *pNext; +} CANSendHandler; + +typedef struct _FDCANHandler +{ + + FDCAN_HandleTypeDef *canfd; //CAN to use + struct _DispacherController *dispacherController; + + + uint8_t timeSpan; + + uint8_t SendListExists; + uint32_t SendList_Period; //时间ms + uint32_t SendList_time_Count; + + CANSendHandler *pCurrentCANSendHadler; // + void (*AddCANSendList)(struct _FDCANHandler*, uint32_t, uint8_t, uint8_t*,uint32_t,//这里是修改等待时间 + void (*CAN_Decode)(uint32_t, uint8_t*, uint32_t)); +//void CANHandlerAddTxList(FDCANHandler *handler, uint32_t CAN_ID,uint8_t SendLength, uint8_t *Tx_Buf,uint32_t sendListTimePeriod,void (*CAN_Decode)(uint32_t, uint8_t*, uint32_t)) //参数其实就是一组can数据 在FDHandler添加东西 + void (*CAN_Decode)(uint32_t, uint8_t*, uint32_t); // decode can frame, received from other devices + + void (*CAN_Send)(struct _FDCANHandler*, uint32_t, uint8_t, uint8_t*); + void (*CAN_Send_Data)(struct _FDCANHandler*); + //(uint8_t FDCAN_CH, uint32_t FrameID,uint8_t DataLength, uint8_t *Txdata) + uint8_t Rx_Buf[128]; //接收缓冲 + uint8_t Tx_Buf[128]; //发送缓冲 + uint32_t ReceivedLength;//接收长度 + uint32_t SendLength; //发送长度 + uint32_t ReceivedFrameID; //接收帧ID + uint32_t SendFrameID; //发送帧ID + +} FDCANHandler; + +extern FDCANHandler FD_CAN_1_Handler; +extern FDCANHandler FD_CAN_2_Handler; +void GF_BSP_CAN_Timer(); +void CAN_Send_t(struct _FDCANHandler *fd, uint32_t FrameID, uint8_t DataLength, + uint8_t *Txdata); +void CAN_Send_Data_t(struct _FDCANHandler *fd); + +void GF_CAN_Send_List_Send(FDCANHandler *handler); +void CANHandlerAddTxList(FDCANHandler *handler, uint32_t CAN_ID, + uint8_t SendLength, uint8_t *Tx_Buf,uint32_t sendListTimePeriod, + void (*CAN_Decode)(uint32_t, uint8_t*, uint32_t)); +void GF_BSP_CANHandler_Init(int can1_sendListPeriod, int can1_DispacherPeriod, + int can2_sendListPeriod, int can2_DispacherPeriod); +void GF_BSP_CANHandler_Init_CAN(FDCANHandler *handler, + FDCAN_HandleTypeDef *canfd, int sendListPeriod, int DispacherPeriod); + +void DecodeMotorCAN(uint32_t canID, uint8_t *buffer, uint32_t length); + +extern FDCANHandler FD_CAN_1_Handler; +extern FDCANHandler FD_CAN_2_Handler; +extern int32_t CAN_ID; +extern int32_t CAN_ID_2; +#endif /* INC_BSP_FDCAN_H_ */ diff --git a/Bingoo/include/base/bsp_GPIO.h b/Bingoo/include/base/bsp_GPIO.h new file mode 100644 index 0000000..dfc4c76 --- /dev/null +++ b/Bingoo/include/base/bsp_GPIO.h @@ -0,0 +1,18 @@ +/* + * bsp_GPIO.h + * + * Created on: Oct 26, 2023 + * Author: shiya + */ + +#ifndef INC_BSP_GPIO_H_ +#define INC_BSP_GPIO_H_ + +#include "bsp_include.h" + +uint8_t GF_BSP_GPIO_Init(void); +void GF_BSP_GPIO_SetIO(uint8_t IO_Index,uint8_t Level); +uint8_t GF_BSP_GPIO_ReadIO(uint8_t IO_Index); +uint8_t GF_BSP_GPIO_ToggleIO(uint8_t IO_Index); + +#endif /* INC_BSP_GPIO_H_ */ diff --git a/Bingoo/include/base/bsp_GV.pb.h b/Bingoo/include/base/bsp_GV.pb.h new file mode 100644 index 0000000..5c1ef7b --- /dev/null +++ b/Bingoo/include/base/bsp_GV.pb.h @@ -0,0 +1,167 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_BSP_GV_PB_H_INCLUDED +#define PB_BSP_GV_PB_H_INCLUDED +#include "pb.h" +#include "msp_MK32.pb.h" +#include "msp_Motor.pb.h" +#include "msp_ZQ_MotorParameters.pb.h" +#include "msp_TL720D.pb.h" +#include "bsp_Error.pb.h" +#include "bsp_PV.pb.h" +#include "bsp_IO.pb.h" +#include "bsp_strain_gauge.pb.h" +#include "bsp_ground_management.pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +typedef struct _GV_struct_define { + int32_t TempatureE_2C; /* E_2C=0.01 Celsius 0.01摄氏度 */ + float Left_Compensation; /* E_2D =0.01 Degree 0.01度 */ + float Right_Compensation; /* 0.01度 */ + float Robot_Angle_Desire; /* 机器人期望角度 //改为 float,单位:度(不再需要0.01缩放) */ + float Robot_Move_Speed; /* 0.1rpm */ + float Robot_Desired_Speed; /* 0.1rpm */ + float Left_Speed_M_min; /* m/Min */ + float Right_Speed_M_min; /* m/Min */ + float Vertical_Adjust; /* 0.1° */ + int32_t ForceValue; + int32_t LaneChangeDistance; + bool has_P_MK32; + SP_MSP_MK32_Button P_MK32; + bool has_LeftMotor; + TT_MotorParameters LeftMotor; /* 左电机 ID2 */ + bool has_RightMotor; + TT_MotorParameters RightMotor; /* 右电机 ID3 */ + bool has_SwingMotor; + TT_MotorParameters SwingMotor; /* 右电机 ID3 */ + bool has_TL720DParameters; + MSP_TL720DParameters TL720DParameters; + bool has_IO; + IO_Data IO; + bool has_SystemErrorData; + ErrorData SystemErrorData; + bool has_PV; + PV_struct_define PV; /* 用户配置数据 */ + float Tar_Position_angle; /* 位置环模式,期望角度 */ + int32_t Tar_Position_Velcity_Degree_S; /* 位置环模式,速度(m/min) */ + int32_t symmetricalOrNot; + int32_t Robot_backMode; + int32_t Robot_Swing_Speed; + bool has_Strain_Gauge; + Strain_Gauge_Struct Strain_Gauge; + float weld_data_X; + int32_t weld_exist; + int32_t Now_press; + int32_t turn_center_difference; + bool has_GroundManagementValue; + ground_management_struct GroundManagementValue; + int32_t robot_back_distance; +} GV_struct_define; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define GV_struct_define_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, SP_MSP_MK32_Button_init_default, false, TT_MotorParameters_init_default, false, TT_MotorParameters_init_default, false, TT_MotorParameters_init_default, false, MSP_TL720DParameters_init_default, false, IO_Data_init_default, false, ErrorData_init_default, false, PV_struct_define_init_default, 0, 0, 0, 0, 0, false, Strain_Gauge_Struct_init_default, 0, 0, 0, 0, false, ground_management_struct_init_default, 0} +#define GV_struct_define_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, SP_MSP_MK32_Button_init_zero, false, TT_MotorParameters_init_zero, false, TT_MotorParameters_init_zero, false, TT_MotorParameters_init_zero, false, MSP_TL720DParameters_init_zero, false, IO_Data_init_zero, false, ErrorData_init_zero, false, PV_struct_define_init_zero, 0, 0, 0, 0, 0, false, Strain_Gauge_Struct_init_zero, 0, 0, 0, 0, false, ground_management_struct_init_zero, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define GV_struct_define_TempatureE_2C_tag 1 +#define GV_struct_define_Left_Compensation_tag 2 +#define GV_struct_define_Right_Compensation_tag 3 +#define GV_struct_define_Robot_Angle_Desire_tag 4 +#define GV_struct_define_Robot_Move_Speed_tag 5 +#define GV_struct_define_Robot_Desired_Speed_tag 6 +#define GV_struct_define_Left_Speed_M_min_tag 7 +#define GV_struct_define_Right_Speed_M_min_tag 8 +#define GV_struct_define_Vertical_Adjust_tag 9 +#define GV_struct_define_ForceValue_tag 10 +#define GV_struct_define_LaneChangeDistance_tag 11 +#define GV_struct_define_P_MK32_tag 12 +#define GV_struct_define_LeftMotor_tag 13 +#define GV_struct_define_RightMotor_tag 14 +#define GV_struct_define_SwingMotor_tag 15 +#define GV_struct_define_TL720DParameters_tag 16 +#define GV_struct_define_IO_tag 17 +#define GV_struct_define_SystemErrorData_tag 18 +#define GV_struct_define_PV_tag 19 +#define GV_struct_define_Tar_Position_angle_tag 20 +#define GV_struct_define_Tar_Position_Velcity_Degree_S_tag 21 +#define GV_struct_define_symmetricalOrNot_tag 22 +#define GV_struct_define_Robot_backMode_tag 23 +#define GV_struct_define_Robot_Swing_Speed_tag 24 +#define GV_struct_define_Strain_Gauge_tag 25 +#define GV_struct_define_weld_data_X_tag 26 +#define GV_struct_define_weld_exist_tag 27 +#define GV_struct_define_Now_press_tag 28 +#define GV_struct_define_turn_center_difference_tag 29 +#define GV_struct_define_GroundManagementValue_tag 30 +#define GV_struct_define_robot_back_distance_tag 31 + +/* Struct field encoding specification for nanopb */ +#define GV_struct_define_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, TempatureE_2C, 1) \ +X(a, STATIC, SINGULAR, FLOAT, Left_Compensation, 2) \ +X(a, STATIC, SINGULAR, FLOAT, Right_Compensation, 3) \ +X(a, STATIC, SINGULAR, FLOAT, Robot_Angle_Desire, 4) \ +X(a, STATIC, SINGULAR, FLOAT, Robot_Move_Speed, 5) \ +X(a, STATIC, SINGULAR, FLOAT, Robot_Desired_Speed, 6) \ +X(a, STATIC, SINGULAR, FLOAT, Left_Speed_M_min, 7) \ +X(a, STATIC, SINGULAR, FLOAT, Right_Speed_M_min, 8) \ +X(a, STATIC, SINGULAR, FLOAT, Vertical_Adjust, 9) \ +X(a, STATIC, SINGULAR, INT32, ForceValue, 10) \ +X(a, STATIC, SINGULAR, INT32, LaneChangeDistance, 11) \ +X(a, STATIC, OPTIONAL, MESSAGE, P_MK32, 12) \ +X(a, STATIC, OPTIONAL, MESSAGE, LeftMotor, 13) \ +X(a, STATIC, OPTIONAL, MESSAGE, RightMotor, 14) \ +X(a, STATIC, OPTIONAL, MESSAGE, SwingMotor, 15) \ +X(a, STATIC, OPTIONAL, MESSAGE, TL720DParameters, 16) \ +X(a, STATIC, OPTIONAL, MESSAGE, IO, 17) \ +X(a, STATIC, OPTIONAL, MESSAGE, SystemErrorData, 18) \ +X(a, STATIC, OPTIONAL, MESSAGE, PV, 19) \ +X(a, STATIC, SINGULAR, FLOAT, Tar_Position_angle, 20) \ +X(a, STATIC, SINGULAR, INT32, Tar_Position_Velcity_Degree_S, 21) \ +X(a, STATIC, SINGULAR, INT32, symmetricalOrNot, 22) \ +X(a, STATIC, SINGULAR, INT32, Robot_backMode, 23) \ +X(a, STATIC, SINGULAR, INT32, Robot_Swing_Speed, 24) \ +X(a, STATIC, OPTIONAL, MESSAGE, Strain_Gauge, 25) \ +X(a, STATIC, SINGULAR, FLOAT, weld_data_X, 26) \ +X(a, STATIC, SINGULAR, INT32, weld_exist, 27) \ +X(a, STATIC, SINGULAR, INT32, Now_press, 28) \ +X(a, STATIC, SINGULAR, INT32, turn_center_difference, 29) \ +X(a, STATIC, OPTIONAL, MESSAGE, GroundManagementValue, 30) \ +X(a, STATIC, SINGULAR, INT32, robot_back_distance, 31) +#define GV_struct_define_CALLBACK NULL +#define GV_struct_define_DEFAULT NULL +#define GV_struct_define_P_MK32_MSGTYPE SP_MSP_MK32_Button +#define GV_struct_define_LeftMotor_MSGTYPE TT_MotorParameters +#define GV_struct_define_RightMotor_MSGTYPE TT_MotorParameters +#define GV_struct_define_SwingMotor_MSGTYPE TT_MotorParameters +#define GV_struct_define_TL720DParameters_MSGTYPE MSP_TL720DParameters +#define GV_struct_define_IO_MSGTYPE IO_Data +#define GV_struct_define_SystemErrorData_MSGTYPE ErrorData +#define GV_struct_define_PV_MSGTYPE PV_struct_define +#define GV_struct_define_Strain_Gauge_MSGTYPE Strain_Gauge_Struct +#define GV_struct_define_GroundManagementValue_MSGTYPE ground_management_struct + +extern const pb_msgdesc_t GV_struct_define_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define GV_struct_define_fields &GV_struct_define_msg + +/* Maximum encoded size of messages (where known) */ +#define BSP_GV_PB_H_MAX_SIZE GV_struct_define_size +#define GV_struct_define_size 2004 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/bsp_IAP.pb.h b/Bingoo/include/base/bsp_IAP.pb.h new file mode 100644 index 0000000..e166370 --- /dev/null +++ b/Bingoo/include/base/bsp_IAP.pb.h @@ -0,0 +1,58 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_BSP_IAP_PB_H_INCLUDED +#define PB_BSP_IAP_PB_H_INCLUDED +#include "pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +/* IAP,即In Application Programming,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写。 */ +typedef struct _IAP_struct_define { + int32_t Total_Bytes; /* all the received data; */ + int32_t NextCodeVrsion; /* the New upgrade Version of the Project */ + int32_t UtcTime; /* Udgrade Time */ + int32_t UpgradeSucceeded; /* */ +} IAP_struct_define; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define IAP_struct_define_init_default {0, 0, 0, 0} +#define IAP_struct_define_init_zero {0, 0, 0, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define IAP_struct_define_Total_Bytes_tag 1 +#define IAP_struct_define_NextCodeVrsion_tag 2 +#define IAP_struct_define_UtcTime_tag 3 +#define IAP_struct_define_UpgradeSucceeded_tag 4 + +/* Struct field encoding specification for nanopb */ +#define IAP_struct_define_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, Total_Bytes, 1) \ +X(a, STATIC, SINGULAR, INT32, NextCodeVrsion, 2) \ +X(a, STATIC, SINGULAR, INT32, UtcTime, 3) \ +X(a, STATIC, SINGULAR, INT32, UpgradeSucceeded, 4) +#define IAP_struct_define_CALLBACK NULL +#define IAP_struct_define_DEFAULT NULL + +extern const pb_msgdesc_t IAP_struct_define_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define IAP_struct_define_fields &IAP_struct_define_msg + +/* Maximum encoded size of messages (where known) */ +#define BSP_IAP_PB_H_MAX_SIZE IAP_struct_define_size +#define IAP_struct_define_size 44 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/bsp_IO.pb.h b/Bingoo/include/base/bsp_IO.pb.h new file mode 100644 index 0000000..28ae8f8 --- /dev/null +++ b/Bingoo/include/base/bsp_IO.pb.h @@ -0,0 +1,81 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_BSP_IO_PB_H_INCLUDED +#define PB_BSP_IO_PB_H_INCLUDED +#include "pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +typedef struct _IO_Data { + int32_t DO0; + int32_t DO1; + int32_t DO2; + int32_t DO3; + int32_t DO4; + int32_t DO5; + int32_t DI0; + int32_t DI1; + int32_t DI2; + int32_t DI3; + int32_t DI4; + int32_t DI5; +} IO_Data; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define IO_Data_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define IO_Data_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define IO_Data_DO0_tag 1 +#define IO_Data_DO1_tag 2 +#define IO_Data_DO2_tag 3 +#define IO_Data_DO3_tag 4 +#define IO_Data_DO4_tag 5 +#define IO_Data_DO5_tag 6 +#define IO_Data_DI0_tag 7 +#define IO_Data_DI1_tag 8 +#define IO_Data_DI2_tag 9 +#define IO_Data_DI3_tag 10 +#define IO_Data_DI4_tag 11 +#define IO_Data_DI5_tag 12 + +/* Struct field encoding specification for nanopb */ +#define IO_Data_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, DO0, 1) \ +X(a, STATIC, SINGULAR, INT32, DO1, 2) \ +X(a, STATIC, SINGULAR, INT32, DO2, 3) \ +X(a, STATIC, SINGULAR, INT32, DO3, 4) \ +X(a, STATIC, SINGULAR, INT32, DO4, 5) \ +X(a, STATIC, SINGULAR, INT32, DO5, 6) \ +X(a, STATIC, SINGULAR, INT32, DI0, 7) \ +X(a, STATIC, SINGULAR, INT32, DI1, 8) \ +X(a, STATIC, SINGULAR, INT32, DI2, 9) \ +X(a, STATIC, SINGULAR, INT32, DI3, 10) \ +X(a, STATIC, SINGULAR, INT32, DI4, 11) \ +X(a, STATIC, SINGULAR, INT32, DI5, 12) +#define IO_Data_CALLBACK NULL +#define IO_Data_DEFAULT NULL + +extern const pb_msgdesc_t IO_Data_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define IO_Data_fields &IO_Data_msg + +/* Maximum encoded size of messages (where known) */ +#define BSP_IO_PB_H_MAX_SIZE IO_Data_size +#define IO_Data_size 132 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/bsp_IV.pb.h b/Bingoo/include/base/bsp_IV.pb.h new file mode 100644 index 0000000..c91e465 --- /dev/null +++ b/Bingoo/include/base/bsp_IV.pb.h @@ -0,0 +1,147 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_BSP_IV_PB_H_INCLUDED +#define PB_BSP_IV_PB_H_INCLUDED +#include "pb.h" +#include "bsp_PV.pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +/* 抛丸机器人状态采集参数结构体(IV:Input/Status Value) + 作用:用于机器人控制系统向APP/上位机上报实时状态、传感器数据、故障报警信息 */ +typedef struct _IV_struct_define { + /* 左侧补偿值(摆臂/位置角度补偿) + 单位换算:发送值 ÷ 100 = 实际显示角度(°),例:发送100 → 显示1°,发送250 → 显示2.5° */ + int32_t LeftCompensation; + /* 右侧补偿值(摆臂/位置角度补偿) + 单位换算:发送值 ÷ 100 = 实际显示角度(°),例:发送100 → 显示1°,发送300 → 显示3° */ + int32_t RightCompensation; + /* 机器人实际移动速度(派生采集值) + 单位换算:发送值 ÷ 10 = 实际显示速度(m/min),例:发送100 → 显示10m/min,发送180 → 显示18m/min(最大速度) + 作用:上报机器人当前行走速度,匹配协议书中0~18m/min的速度范围 */ + int32_t Robot_Move_Deri_Speed; + /* 机器人陀螺仪角度(姿态检测) + 单位换算:发送值 ÷ 100 = 实际显示角度(°),例:发送100 → 显示1°,发送9000 → 显示90° + 作用:上报机器人当前姿态角度(水平/竖直/倾斜),用于作业面姿态校准 */ + int32_t Robot_Gyro; + /* 距离传感器采集值(测距/避障) + 单位换算:发送值 ÷ 10 = 实际显示距离(cm),例:发送100 → 显示10cm,发送500 → 显示50cm + 作用:检测机器人与作业面/障碍物的距离,防止碰撞或吸附失效 */ + int32_t Distance_Sensor; + /* 系统级错误码 + 取值规则:0 = 无错误;非0 = 错误类型(需配套错误码表) + 错误类型:包含硬件通讯故障、按键未初始化故障等核心系统异常 */ + int32_t SystemError; + /* 左轮电机报警状态 + 取值规则:0 = 正常(无报警);1 = 报警(过流/过载/堵转等) + 作用:上报左轮驱动电机的故障状态,用于电机故障排查 */ + int32_t Left_Motor_Err; + /* 右轮电机报警状态 + 取值规则:0 = 正常(无报警);1 = 报警(过流/过载/堵转等) + 作用:上报右轮驱动电机的故障状态,用于电机故障排查 */ + int32_t Right_Motor_Err; + /* 摆臂电机报警状态 + 取值规则:0 = 正常(无报警);1 = 报警(过流/过载/堵转等) + 作用:上报抛丸/喷砂摆臂电机的故障状态,适配摆臂速度≥25°/S的作业要求 */ + int32_t Swing_Motor_Err; + /* 机器人在线状态 + 取值规则:0 = 离线(通讯中断);1 = 在线(通讯正常) + 作用:APP/上位机判断机器人通讯状态,离线时触发声光报警 */ + int32_t Is_Online; + /* 备用数据1 + 用途:预留扩展字段,可用于后续新增传感器/状态采集(如吸附压力、吸尘装置状态等) */ + int32_t Spara_Data_1; + /* 备用数据2 + 用途:预留扩展字段,可用于后续新增传感器/状态采集(如作业面温度等) */ + int32_t Spara_Data_2; + /* 备用数据3 + 用途:预留扩展字段,可用于后续新增传感器/状态采集(如急停按钮状态、电池电量等) */ + int32_t Spara_Data_3; + /* 焊缝数据 */ + int32_t Weld_data; + /* 焊缝是否存在 */ + int32_t Weld_exist; + /* 回转中心偏距 */ + int32_t Turn_difference; + /* 当前压力 */ + int32_t Present_press; + int32_t left_angle; + int32_t right_angle; + /* 检测机器人是否到达设定的启动时间 */ + int32_t robot_start; +} IV_struct_define; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define IV_struct_define_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define IV_struct_define_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define IV_struct_define_LeftCompensation_tag 1 +#define IV_struct_define_RightCompensation_tag 2 +#define IV_struct_define_Robot_Move_Deri_Speed_tag 3 +#define IV_struct_define_Robot_Gyro_tag 4 +#define IV_struct_define_Distance_Sensor_tag 5 +#define IV_struct_define_SystemError_tag 6 +#define IV_struct_define_Left_Motor_Err_tag 7 +#define IV_struct_define_Right_Motor_Err_tag 8 +#define IV_struct_define_Swing_Motor_Err_tag 9 +#define IV_struct_define_Is_Online_tag 10 +#define IV_struct_define_Spara_Data_1_tag 11 +#define IV_struct_define_Spara_Data_2_tag 12 +#define IV_struct_define_Spara_Data_3_tag 13 +#define IV_struct_define_Weld_data_tag 14 +#define IV_struct_define_Weld_exist_tag 15 +#define IV_struct_define_Turn_difference_tag 16 +#define IV_struct_define_Present_press_tag 17 +#define IV_struct_define_left_angle_tag 18 +#define IV_struct_define_right_angle_tag 19 +#define IV_struct_define_robot_start_tag 20 + +/* Struct field encoding specification for nanopb */ +#define IV_struct_define_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, LeftCompensation, 1) \ +X(a, STATIC, SINGULAR, INT32, RightCompensation, 2) \ +X(a, STATIC, SINGULAR, INT32, Robot_Move_Deri_Speed, 3) \ +X(a, STATIC, SINGULAR, INT32, Robot_Gyro, 4) \ +X(a, STATIC, SINGULAR, INT32, Distance_Sensor, 5) \ +X(a, STATIC, SINGULAR, INT32, SystemError, 6) \ +X(a, STATIC, SINGULAR, INT32, Left_Motor_Err, 7) \ +X(a, STATIC, SINGULAR, INT32, Right_Motor_Err, 8) \ +X(a, STATIC, SINGULAR, INT32, Swing_Motor_Err, 9) \ +X(a, STATIC, SINGULAR, INT32, Is_Online, 10) \ +X(a, STATIC, SINGULAR, INT32, Spara_Data_1, 11) \ +X(a, STATIC, SINGULAR, INT32, Spara_Data_2, 12) \ +X(a, STATIC, SINGULAR, INT32, Spara_Data_3, 13) \ +X(a, STATIC, SINGULAR, INT32, Weld_data, 14) \ +X(a, STATIC, SINGULAR, INT32, Weld_exist, 15) \ +X(a, STATIC, SINGULAR, INT32, Turn_difference, 16) \ +X(a, STATIC, SINGULAR, INT32, Present_press, 17) \ +X(a, STATIC, SINGULAR, INT32, left_angle, 18) \ +X(a, STATIC, SINGULAR, INT32, right_angle, 19) \ +X(a, STATIC, SINGULAR, INT32, robot_start, 20) +#define IV_struct_define_CALLBACK NULL +#define IV_struct_define_DEFAULT NULL + +extern const pb_msgdesc_t IV_struct_define_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define IV_struct_define_fields &IV_struct_define_msg + +/* Maximum encoded size of messages (where known) */ +#define BSP_IV_PB_H_MAX_SIZE IV_struct_define_size +#define IV_struct_define_size 225 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/bsp_MB_host.h b/Bingoo/include/base/bsp_MB_host.h new file mode 100644 index 0000000..8b6bff5 --- /dev/null +++ b/Bingoo/include/base/bsp_MB_host.h @@ -0,0 +1,52 @@ +#ifndef __BSP_MB_HOST_H__ +#define __BSP_MB_HOST_H__ + +/* 包含头文件 ----------------------------------------------------------------*/ + +/* 类型定义 ------------------------------------------------------------------*/ + +/* 宏定义 --------------------------------------------------------------------*/ +#define MB_SLAVEADDR 0x0001 //从机地址 +#define MB_REG_ADDR 0 //寄存器地址(离散、线圈) +#define HoldingReg 0 //保持寄存器 +#define InputRegReg 0x0020 //输入寄存器 +#define SWAP_ENDIAN_16(x) (((x) >> 8) | ((x) << 8)) +#include "bsp_include.h" +#include "BSP/bsp_UART.h" + +/* 扩展变量 ------------------------------------------------------------------*/ + typedef struct +{ + + uint16_t DATA_01H; + uint16_t DATA_02H; + uint16_t DATA_03H; + + uint16_t DATA_04H; + uint16_t DATA_05H; + uint16_t DATA_06H; + uint8_t DATA_10H[64]; + +}MB_REG_DATA; + +//; +extern uint8_t MB_rx_flag; +extern uint16_t Read_Reg_Num; + + +/* 函数声明 ------------------------------------------------------------------*/ +uint16_t MB_CRC16(uint8_t *pushMsg, uint16_t usDataLen); +void MB_ReadCoil(uint8_t* Tx_Buf,uint8_t* TxCount_t,uint8_t _addr, uint16_t _reg, uint16_t _num); +void MB_WriteCoil(uint8_t* Tx_Buf,uint8_t* TxCount_t,uint8_t _addr, uint16_t _reg, uint16_t _sta); +void MB_ReadInput(uint8_t* Tx_Buf,uint8_t* TxCount_t,uint8_t _addr, uint16_t _reg, uint16_t _num); +void MB_ReadHoldingReg(uint8_t* Tx_Buf,uint8_t* TxCount_t,uint8_t _addr, uint16_t _reg, uint16_t _num); +void MB_ReadInputReg(uint8_t* Tx_Buf,uint8_t* TxCount_t,uint8_t _addr, uint16_t _reg, uint16_t _num); +void MB_WriteHoldingReg(uint8_t* Tx_Buf,uint8_t* TxCount_t,uint8_t _addr, uint16_t _reg, uint16_t _data); +//void MB_WriteNumHoldingReg(uint8_t* Tx_Buf,uint8_t* TxCount_t,uint8_t _addr, uint16_t _reg, uint16_t _num,uint8_t *_databuf) +void MB_WriteNumHoldingReg(uint8_t* Tx_Buf,uint8_t* TxCount_t,uint8_t _addr, uint16_t _reg, uint16_t _num,uint8_t *_databuf); +void MB_WriteNumCoil(uint8_t *Tx_Buf, uint8_t *TxCount_t, uint8_t _addr, + uint16_t _reg, uint16_t _num, uint8_t *_databuf); + +#endif /* __BSP_MB_HOST_H__ */ + +/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/ diff --git a/Bingoo/include/base/bsp_PID.pb.h b/Bingoo/include/base/bsp_PID.pb.h new file mode 100644 index 0000000..339179b --- /dev/null +++ b/Bingoo/include/base/bsp_PID.pb.h @@ -0,0 +1,57 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_BSP_PID_PB_H_INCLUDED +#define PB_BSP_PID_PB_H_INCLUDED +#include "pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +typedef struct _PID_Parameters { + int32_t PID_Angle; /* 调整 单位0.01° 配置时需要*100 */ + double Kp; /* PID参数 */ + double Ki; + double Kd; +} PID_Parameters; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define PID_Parameters_init_default {0, 0, 0, 0} +#define PID_Parameters_init_zero {0, 0, 0, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define PID_Parameters_PID_Angle_tag 1 +#define PID_Parameters_Kp_tag 2 +#define PID_Parameters_Ki_tag 3 +#define PID_Parameters_Kd_tag 4 + +/* Struct field encoding specification for nanopb */ +#define PID_Parameters_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, PID_Angle, 1) \ +X(a, STATIC, SINGULAR, DOUBLE, Kp, 2) \ +X(a, STATIC, SINGULAR, DOUBLE, Ki, 3) \ +X(a, STATIC, SINGULAR, DOUBLE, Kd, 4) +#define PID_Parameters_CALLBACK NULL +#define PID_Parameters_DEFAULT NULL + +extern const pb_msgdesc_t PID_Parameters_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define PID_Parameters_fields &PID_Parameters_msg + +/* Maximum encoded size of messages (where known) */ +#define BSP_PID_PB_H_MAX_SIZE PID_Parameters_size +#define PID_Parameters_size 38 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/bsp_PV.pb.h b/Bingoo/include/base/bsp_PV.pb.h new file mode 100644 index 0000000..ede80e1 --- /dev/null +++ b/Bingoo/include/base/bsp_PV.pb.h @@ -0,0 +1,136 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_BSP_PV_PB_H_INCLUDED +#define PB_BSP_PV_PB_H_INCLUDED +#include "pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +/* 抛丸机器人作业参数结构体定义 + 作用:用于APP/遥控器与机器人控制系统之间的参数传输,涵盖操作模式、运动参数、摆臂参数、作业参数等核心配置 */ +typedef struct _PV_struct_define { + /* 操作模式(枚举值) + 1 - 手动模式:人工摇杆/按键控制机器人所有动作 + 2 - 水平模式:适配水平作业面的半自动/手动操作 + 3 - 平面模式:适配平面作业面的操作(修正原文笔误:原"平民"为"平面") + 4 - 竖直左模式:左侧垂直作业面(如船舶外壁左侧)操作 + 5 - 竖直右模式:右侧垂直作业面(如船舶外壁右侧)操作 + 6 - 水平区域自动:水平作业面的区域自动作业模式 + 7 - 平面区域自动:平面作业面的区域自动作业模式 */ + int32_t Robot_Operation_Mode; + /* 机器人移动速度(基础行走速度) + 单位:0.1m/min(字段值×0.1=实际速度,如值为10则实际速度1m/min) + 取值范围:0~180(对应实际0~18m/min,符合协议书中最大18m/min的要求) */ + int32_t Robot_Move_Speed; + /* 换道距离(自动换道功能的核心参数) + 单位:mm(建议,可根据实际硬件标定调整) + 作用:一键换道时机器人横向移动的距离,用于控制换道压边量 */ + int32_t Robot_Change_Lane_Distance; + /* 摆臂速度(抛丸/喷砂摆臂装置的摆动速度) + 单位:°/s(度/秒) + 取值要求:≥25(对应协议书中摆臂速度≥25°/S的要求) */ + int32_t Robot_Swing_Speed; + /* 摆臂角度设置模式(对称/非对称) + 1 - 对称模式:摆臂以中心轴左右对称摆动 + 2 - 非对称模式:摆臂仅单侧(左/右)摆动 */ + int32_t Robot_symmetricalOrNot; + /* 对称模式下摆臂总摆动角度 + 单位:°(度) + 示例:值为90则摆臂从-45°~+45°对称摆动 */ + int32_t Robot_Swing_Range_Angle; + /* 非对称模式下的摆动侧选择 + 1 - 左侧:仅摆臂左侧区域摆动 + 2 - 右侧:仅摆臂右侧区域摆动 */ + int32_t Robot_asymmetricalAngleSetValue; + /* 后退作业模式(抛丸/喷砂作业时的后退逻辑) + 1 - 打退交替:作业一段距离后停止作业,后退指定距离再继续作业 + 2 - 边打边退:作业过程中同步后退,持续作业无中断 */ + int32_t Robot_backMode; + /* 打退交替模式下的后退距离 + 单位:mm(建议) + 作用:打退交替时单次后退的距离,适配不同作业面的补抛需求 */ + int32_t Robot_Back_Distance; + /* 边打边退模式下的后退速度 + 单位:0.1m/min(同Robot_Move_Speed) + 取值范围:0~180(对应实际0~18m/min) */ + int32_t Robot_Back_Speed; + /* 压力设置(抛丸/喷砂作业的介质压力) + 单位:0.01MPa(建议,如值为50则实际0.5MPa) + 作用:控制抛丸/喷砂的强度,适配不同表面处理等级(≥Sa2.5) */ + int32_t Robot_Press_Set; + /* 竖直微调(竖直作业模式下的位置微调量) + 单位:mm(建议) + 作用:竖直作业时微调机器人位置,补偿曲面/安装误差 */ + int32_t Robot_Vertical_Adjust; + /* 自动模式下的作业长度 + 单位:mm(建议) + 作用:区域自动作业时,单次作业的纵向长度(完成后自动换道) */ + int32_t Robot_Length_Homework; + /* 自动模式下的作业宽度 + 单位:mm(建议) + 作用:区域自动作业时,单次作业的横向宽度(默认适配110mm标准作业宽度) */ + int32_t Robot_Width_Homework; +} PV_struct_define; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define PV_struct_define_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PV_struct_define_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define PV_struct_define_Robot_Operation_Mode_tag 1 +#define PV_struct_define_Robot_Move_Speed_tag 2 +#define PV_struct_define_Robot_Change_Lane_Distance_tag 3 +#define PV_struct_define_Robot_Swing_Speed_tag 4 +#define PV_struct_define_Robot_symmetricalOrNot_tag 5 +#define PV_struct_define_Robot_Swing_Range_Angle_tag 6 +#define PV_struct_define_Robot_asymmetricalAngleSetValue_tag 7 +#define PV_struct_define_Robot_backMode_tag 8 +#define PV_struct_define_Robot_Back_Distance_tag 9 +#define PV_struct_define_Robot_Back_Speed_tag 10 +#define PV_struct_define_Robot_Press_Set_tag 11 +#define PV_struct_define_Robot_Vertical_Adjust_tag 12 +#define PV_struct_define_Robot_Length_Homework_tag 13 +#define PV_struct_define_Robot_Width_Homework_tag 14 + +/* Struct field encoding specification for nanopb */ +#define PV_struct_define_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, Robot_Operation_Mode, 1) \ +X(a, STATIC, SINGULAR, INT32, Robot_Move_Speed, 2) \ +X(a, STATIC, SINGULAR, INT32, Robot_Change_Lane_Distance, 3) \ +X(a, STATIC, SINGULAR, INT32, Robot_Swing_Speed, 4) \ +X(a, STATIC, SINGULAR, INT32, Robot_symmetricalOrNot, 5) \ +X(a, STATIC, SINGULAR, INT32, Robot_Swing_Range_Angle, 6) \ +X(a, STATIC, SINGULAR, INT32, Robot_asymmetricalAngleSetValue, 7) \ +X(a, STATIC, SINGULAR, INT32, Robot_backMode, 8) \ +X(a, STATIC, SINGULAR, INT32, Robot_Back_Distance, 9) \ +X(a, STATIC, SINGULAR, INT32, Robot_Back_Speed, 10) \ +X(a, STATIC, SINGULAR, INT32, Robot_Press_Set, 11) \ +X(a, STATIC, SINGULAR, INT32, Robot_Vertical_Adjust, 12) \ +X(a, STATIC, SINGULAR, INT32, Robot_Length_Homework, 13) \ +X(a, STATIC, SINGULAR, INT32, Robot_Width_Homework, 14) +#define PV_struct_define_CALLBACK NULL +#define PV_struct_define_DEFAULT NULL + +extern const pb_msgdesc_t PV_struct_define_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define PV_struct_define_fields &PV_struct_define_msg + +/* Maximum encoded size of messages (where known) */ +#define BSP_PV_PB_H_MAX_SIZE PV_struct_define_size +#define PV_struct_define_size 154 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/bsp_ReCmd.pb.h b/Bingoo/include/base/bsp_ReCmd.pb.h new file mode 100644 index 0000000..724cf70 --- /dev/null +++ b/Bingoo/include/base/bsp_ReCmd.pb.h @@ -0,0 +1,80 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_BSP_RECMD_PB_H_INCLUDED +#define PB_BSP_RECMD_PB_H_INCLUDED +#include "pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +/* this message is used for the reply the command */ +typedef struct _ReCmd { + int32_t CommadNum; + /* 定义 1 上位机获取默认CV值 +定义 2 下位机返回CV值 +定义 3 上位机设定CV值 +定义 4 上位机设定Trace等级值,无返回 +定义 5 下位机上传位置点数据 +定义 6 上位机设定编码器角度值为0 +定义 7 上位机获取拟合点 +定义 8 上位机获取位置点 +定义 9 上位机向下位机下发程序 此时,Parameter0 下发的程序起始位,Parameter0 是校验位 +Buff_Data_Length 是下发的字节数, */ + int32_t Parameter0; + int32_t Parameter1; + int32_t Parameter2; + int32_t Parameter3; + int32_t Parameter4; + int32_t Buff_Data_Length; + pb_byte_t Buff_Data[512]; +} ReCmd; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define ReCmd_init_default {0, 0, 0, 0, 0, 0, 0, {0}} +#define ReCmd_init_zero {0, 0, 0, 0, 0, 0, 0, {0}} + +/* Field tags (for use in manual encoding/decoding) */ +#define ReCmd_CommadNum_tag 1 +#define ReCmd_Parameter0_tag 2 +#define ReCmd_Parameter1_tag 3 +#define ReCmd_Parameter2_tag 4 +#define ReCmd_Parameter3_tag 5 +#define ReCmd_Parameter4_tag 6 +#define ReCmd_Buff_Data_Length_tag 7 +#define ReCmd_Buff_Data_tag 8 + +/* Struct field encoding specification for nanopb */ +#define ReCmd_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, CommadNum, 1) \ +X(a, STATIC, SINGULAR, INT32, Parameter0, 2) \ +X(a, STATIC, SINGULAR, INT32, Parameter1, 3) \ +X(a, STATIC, SINGULAR, INT32, Parameter2, 4) \ +X(a, STATIC, SINGULAR, INT32, Parameter3, 5) \ +X(a, STATIC, SINGULAR, INT32, Parameter4, 6) \ +X(a, STATIC, SINGULAR, INT32, Buff_Data_Length, 7) \ +X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, Buff_Data, 8) +#define ReCmd_CALLBACK NULL +#define ReCmd_DEFAULT NULL + +extern const pb_msgdesc_t ReCmd_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define ReCmd_fields &ReCmd_msg + +/* Maximum encoded size of messages (where known) */ +#define BSP_RECMD_PB_H_MAX_SIZE ReCmd_size +#define ReCmd_size 592 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/bsp_TCPClient.h b/Bingoo/include/base/bsp_TCPClient.h new file mode 100644 index 0000000..72a1a5d --- /dev/null +++ b/Bingoo/include/base/bsp_TCPClient.h @@ -0,0 +1,63 @@ +/* + * bsp_TCPClient.h + * + * Created on: Oct 22, 2024 + * Author: akeguo + */ + +#ifndef INC_BSP_BSP_TCPCLIENT_H_ +#define INC_BSP_BSP_TCPCLIENT_H_ + + +/* Includes ------------------------------------------------------------------*/ + + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +#define USE_LCD /* enable LCD */ + +#define DEST_IP_ADDR0 ((uint8_t)192U) +#define DEST_IP_ADDR1 ((uint8_t)168U) +#define DEST_IP_ADDR2 ((uint8_t)1U) +#define DEST_IP_ADDR3 ((uint8_t)10U) + +#define DEST_PORT ((uint16_t)502U) + + +/*NETMASK*/ +#define NETMASK_ADDR0 ((uint8_t) 255U) +#define NETMASK_ADDR1 ((uint8_t) 255U) +#define NETMASK_ADDR2 ((uint8_t) 255U) +#define NETMASK_ADDR3 ((uint8_t) 0U) + +/*Gateway Address*/ +#define GW_ADDR0 ((uint8_t) 192U) +#define GW_ADDR1 ((uint8_t) 168U) +#define GW_ADDR2 ((uint8_t) 1U) +#define GW_ADDR3 ((uint8_t) 1U) + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +//void tcp_client_connect(void); +typedef struct _LazorData +{ + float Feature_X; //特征点X + float Feature_Y; //特征点Y + float Feature_Z; //特征点Z + float Gap; //间隙 + float WrongEdgeQuantity; //错边量 + float Area; //面积 +} LazorData; +extern unsigned char *Weld_Out_Flag; +extern unsigned char Weld_Out_Count; +extern unsigned char Weld_Out_SafeCount; +extern LazorData *ReadLazorData; +void TCP_Client_Init(void); +#endif /* INC_BSP_BSP_TCPCLIENT_H_ */ diff --git a/Bingoo/include/base/bsp_TIMER.h b/Bingoo/include/base/bsp_TIMER.h new file mode 100644 index 0000000..95bfc73 --- /dev/null +++ b/Bingoo/include/base/bsp_TIMER.h @@ -0,0 +1,17 @@ +/* + * bsp_TIMER.h + * + * Created on: Oct 26, 2023 + * Author: shiya + */ + +#ifndef INC_BSP_TIMER_H_ +#define INC_BSP_TIMER_H_ +#include "BSP/bsp_TCPClient.h" +#include "bsp_include.h" + +uint8_t GF_BSP_TIMER_Init(void); +void GF_BSP_TIMER_DelayUS(uint32_t n); + + +#endif /* INC_BSP_TIMER_H_ */ diff --git a/Bingoo/include/base/bsp_UART.h b/Bingoo/include/base/bsp_UART.h new file mode 100644 index 0000000..8059730 --- /dev/null +++ b/Bingoo/include/base/bsp_UART.h @@ -0,0 +1,109 @@ + + +#ifndef INC_BSP_UART_H_ +#define INC_BSP_UART_H_ + +#include "BSP/bsp_include.h" +#include "main.h" +#include "bsp_Error.pb.h" +#define UART_Transmit_MAX_NUM 1024 +#define UART_Receive_MAX_NUM 100 + +extern struct UARTHandler RS_485_1_UART_Handler; +extern struct UARTHandler RS_485_2_UART_Handler; +extern struct UARTHandler RS_485_3_UART_Handler; +extern struct UARTHandler RS_485_4_UART_Handler; +extern struct UARTHandler InterCall_DEBUG_UART_Handler; +extern struct UARTHandler E28_SBUS_UART_Handler; +extern struct UARTHandler LTE_7S0_Serial_UART_Handler; + + + +#if defined (hlpuart1Exit) + extern struct UARTHandler LPUART1_UART_Handler; + +#endif + +uint8_t GF_BSP_UART_Init(void); + +void GF_BSP_UARTHandlers_Intialize( + int32_t RS485_1_WaitTime, + int32_t RS485_2_WaitTime, + int32_t RS485_3_WaitTime, + int32_t RS485_4_WaitTime, + int32_t LTE_7S0_Serial_WaitTime, + int32_t InterCall_DEBUG_WaitTime, + int32_t E28_SBUS_WaitTime, + int32_t LPUART1_UART_WaitTime, + int32_t RS485_1_Dispacher_Time, + int32_t RS485_2_Dispacher_Time, + int32_t RS485_3_Dispacher_Time, + int32_t RS485_4_Dispacher_Time, + int32_t LTE_7S0_Serial_Dispacher_Time, + int32_t InterCall_DEBUG_Dispacher_Time, + int32_t E28_SBUS_Dispacher_Time, + int32_t LPUART1_UART_Dispacher_Time +); + +//串行发送完成后才能发送第二帧数据,没有做缓冲,如未发送完成,第二次发送无效,丢弃发送数据 +void GF_BSP_UART_Transmit(const uint8_t RS485_Index,const uint8_t *pData, uint16_t Size); + + + + +typedef struct UARTSendHandler +{ + uint16_t SendLength; + uint16_t SendListTimePeriod; + uint8_t Tx_Buf[502]; + void (*UART_Decode)(uint8_t*, uint16_t); // 发送缓存 + struct UARTSendHandler* pNext; +}UARTSendHandler; + + +struct UARTHandler +{ + char startCountFlag; //indicate that to start counting + char send_finished;//indicate decode finished or not + char decode_finished;//indicate decode finished or not + uint8_t tmp_Rx_Buf[2]; // temporary data to store received data + + uint32_t Wait_time; // the time to wait + //uint32_t Send_time; + //uint32_t count; + uint32_t Wait_Time_Count; + uint32_t SendList_time_Count; + + uint32_t SendList_Period; + uint8_t SendListExists; + + UART_HandleTypeDef* uart; //UART to use + unsigned char timeSpan; // timer elapsed time + uint8_t Rx_Buf[2048]; // 接收缓存,最大256字节 + uint8_t Tx_Buf[2048]; //发送缓存 157,864 + uint16_t TxCount; + + uint16_t RxCount; + + + //(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size) + void (*UART_Tx)(struct UARTHandler*); //void UART_Tx(uint8_t *Tx_Buf,uint16_t TxCount); + void (*UART_Rx)(struct UARTHandler*); + void (*UART_Decode)(uint8_t*, uint16_t); //Decode Rx_Buf + UARTSendHandler *pCurrentUARTSendHadler; // + void (*AddSendList)(struct UARTHandler*, uint8_t*, uint16_t,uint32_t,//这里是修改等待时间 + void (*UART_Decode)(uint8_t*, uint16_t)); + struct _DispacherController *dispacherController; +}; + +void UARTHandlerTx(struct UARTHandler *uartHandler); +void UARTHandlerRX(struct UARTHandler *uartHandler); +//void IntializeUARTHandler(struct UARTHandler *uartHandler, UART_HandleTypeDef uart,int32_t WaitTime,unsigned char timeSpan); +void Counting(struct UARTHandler *uartHandler); + + +void IntializeUARTHandler(struct UARTHandler *uartHandler, + UART_HandleTypeDef *uart, int32_t WaitTime, unsigned char timeSpan,int32_t Dispacher_Time); +void GF_BSP_UART_Timer(); + +#endif /* INC_BSP_UART_H_ */ diff --git a/Bingoo/include/base/bsp_UDP.h b/Bingoo/include/base/bsp_UDP.h new file mode 100644 index 0000000..0d6b4b7 --- /dev/null +++ b/Bingoo/include/base/bsp_UDP.h @@ -0,0 +1,23 @@ +/* + * bsp_UDP.h + * + * Created on: Aug 13, 2024 + * Author: akeguo + */ + +#ifndef INC_BSP_BSP_UDP_H_ +#define INC_BSP_BSP_UDP_H_ + +void udp_client_init(void); + + +void udp_dlt_send_back(char *pData,uint16_t Size); +void udp_cmd_send_back(char *pData, uint16_t Size); + +typedef void (*DLT_DecodeFuncPtr)(uint8_t*, uint16_t); +void udp_send_by_pcb(struct udp_pcb * upcb,char *pData, uint16_t Size); +// 再用该类型声明变量 +extern DLT_DecodeFuncPtr UDP_DLT_ReceivedCallback; +extern int8_t is_udp_GV_update_loop_enalbed; + +#endif /* INC_BSP_BSP_UDP_H_ */ diff --git a/Bingoo/include/base/bsp_UpperComputer_Handler.h b/Bingoo/include/base/bsp_UpperComputer_Handler.h new file mode 100644 index 0000000..198b159 --- /dev/null +++ b/Bingoo/include/base/bsp_UpperComputer_Handler.h @@ -0,0 +1,27 @@ +/* + * bsp_desulfurizer_handler.h + * + * Created on: Jul 29, 2024 + * Author: akeguo + */ + +#ifndef INC_BSP_BSP_UPPERCOMPUTER_HANDLER_H_ +#define INC_BSP_BSP_UPPERCOMPUTER_HANDLER_H_ +#include +#include +#include "bsp_MB_host.h" +#include "stdio.h" +#include "BSP/bsp_UART.h" +#include "usart.h" +#include "gpio.h" + + +extern struct UARTHandler *desulfurizer_message_UART_Handler; +void upper_Computer_UART_Handler_intialize(struct UARTHandler *Handler); + +void decode_command_from_computer(uint8_t *buffer, uint16_t length); + + +void send_data_to_upper_computer(double Angle, double WireLength, + double Thickness, char IsFittingPoint,char isMqtt,struct UARTHandler *send_UART_Handler); +#endif /* INC_BSP_BSP_UPPERCOMPUTER_HANDLER_H_ */ diff --git a/Bingoo/include/base/bsp_client_setting.h b/Bingoo/include/base/bsp_client_setting.h new file mode 100644 index 0000000..1b13112 --- /dev/null +++ b/Bingoo/include/base/bsp_client_setting.h @@ -0,0 +1,13 @@ +/* + * bsp_pv_setting.h + * + * Created on: Jan 8, 2025 + * Author: akeguo + */ + +#ifndef INC_BSP_BSP_CLIENT_SETTING_H_ +#define INC_BSP_BSP_CLIENT_SETTING_H_ +#include "BHBF_ROBOT.h" + +void client_setting_intialize(struct UARTHandler *Handler); +#endif /* INC_BSP_BSP_CLIENT_SETTING_H_ */ diff --git a/Bingoo/include/base/bsp_com_helper.h b/Bingoo/include/base/bsp_com_helper.h new file mode 100644 index 0000000..a0b0d80 --- /dev/null +++ b/Bingoo/include/base/bsp_com_helper.h @@ -0,0 +1,82 @@ +/* + * bsp_com_helper.h + * + * Created on: Oct 9, 2024 + * Author: akeguo + */ + +#ifndef INC_BSP_BSP_COM_HELPER_H_ +#define INC_BSP_BSP_COM_HELPER_H_ +#include "bsp_include.h" + + +typedef struct _Dispatcher +{ + //uint8_t IsDeleted; + void (*dispache)(void); + + //struct _Dispatcher* pBefore; + struct _Dispatcher* pNext; +}Dispatcher; + + +//通讯链表节点结构体 +typedef struct _ComHardWare +{ + //void (*dispache)(void); + char Name[50]; + char IsOnline; + uint32_t BitFlag; + struct _ComHardWare* pNext; +}ComHardWare; + + + + + +typedef struct _DispacherController +{ + Dispatcher *pHead; // = NULL; //环形链表中的数据头指针 + Dispatcher *pTail; // = NULL; //环形链表中的数据尾指针 + uint16_t DispacherNumber; // = 0; + uint16_t DispacherCallTime; // + uint16_t Dispacher_Counter; // = 0; + uint16_t Dispacher_Enable; // = 0 disable 1 enable + void (*Add_Dispatcher_List)(struct _DispacherController* , + void (*dispacher)(void)); //UART的调度程序 + void (*Dispatcher_Run)(struct _DispacherController* ); //UART的调度程序 + +}DispacherController; + +typedef struct _HardWareController +{ + struct _ComHardWare *pComHWHead; + struct _ComHardWare *pComHWTail; + uint16_t HardWare_Check_Counter; + uint16_t DispacherCallTime; //= 100; //2ms 一次, + void (*Add_PCOMHardWare)(struct _HardWareController *, char* , char ,uint32_t); + void (*PCOMHardWare_Check)(struct _HardWareController *); + int (*Set_PCOMHardWare)(struct _HardWareController *, char* , char ); + + +} HardWareController; + + + + + void Dispatch_t(DispacherController *uartHandler); + +void Dispatcher_List_Add_t(DispacherController *uartHandler,void (*dispache)(void)); +// void Dispatcher_List_Add_t(DispacherController *uartHandler, +// void (*dispache)(void),void (*Decode)(uint8_t*, uint16_t)); +// void ComHardWare_List_Add_t(HardWareController *uartHandler, char *name,char value); + + void PCOMHardWare_Check_t(HardWareController *uartHandler); + +int Set_PCOMHardWare_t(HardWareController *uartHandler, char *name, char value); + +void ComHardWare_List_Add_t(HardWareController *uartHandler, char *name, + char value,uint32_t bitFlag); + + +#endif /* INC_BSP_BSP_COM_HELPER_H_ */ diff --git a/Bingoo/include/base/bsp_cpu_flash.h b/Bingoo/include/base/bsp_cpu_flash.h new file mode 100644 index 0000000..898c10b --- /dev/null +++ b/Bingoo/include/base/bsp_cpu_flash.h @@ -0,0 +1,66 @@ +/* + * bsp_cpu_flash.h + * + * Created on: Aug 28, 2024 + * Author: akeguo + */ + +#ifndef SRC_BSP_BSP_CPU_FLASH_H_ +#define SRC_BSP_BSP_CPU_FLASH_H_ + +#include "main.h" + +#include +#include "quadspi.h" + +#define ENABLE_INT() __set_PRIMASK(0) /* 使能全局中断 */ +#define DISABLE_INT() __set_PRIMASK(1) /* 禁止全局中断 */ + + +#define CPU_FLASH_BASE_ADDR (uint32_t)(FLASH_BASE) /* 0x08000000 */ +#define CPU_FLASH_END_ADDR (uint32_t)(0x081FFFFF) + +#define CPU_FLASH_SIZE (2 * 1024 * 1024) /* FLASH总容量 */ +#define CPU_FLASH_SECTOR_SIZE (128 * 1024) /* 扇区大小,字节 */ + +/* Base address of the Flash sectors Bank 1 */ +#define ADDR_FLASH_SECTOR_0_BANK1 ((uint32_t)0x08000000) /* Base @ of Sector 0, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_1_BANK1 ((uint32_t)0x08020000) /* Base @ of Sector 1, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_2_BANK1 ((uint32_t)0x08040000) /* Base @ of Sector 2, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_3_BANK1 ((uint32_t)0x08060000) /* Base @ of Sector 3, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_4_BANK1 ((uint32_t)0x08080000) /* Base @ of Sector 4, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_5_BANK1 ((uint32_t)0x080A0000) /* Base @ of Sector 5, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_6_BANK1 ((uint32_t)0x080C0000) /* Base @ of Sector 6, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_7_BANK1 ((uint32_t)0x080E0000) /* Base @ of Sector 7, 128 Kbytes */ + +/* Base address of the Flash sectors Bank 2 */ +#define ADDR_FLASH_SECTOR_0_BANK2 ((uint32_t)0x08100000) /* Base @ of Sector 0, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_1_BANK2 ((uint32_t)0x08120000) /* Base @ of Sector 1, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_2_BANK2 ((uint32_t)0x08140000) /* Base @ of Sector 2, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_3_BANK2 ((uint32_t)0x08160000) /* Base @ of Sector 3, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_4_BANK2 ((uint32_t)0x08180000) /* Base @ of Sector 4, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_5_BANK2 ((uint32_t)0x081A0000) /* Base @ of Sector 5, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_6_BANK2 ((uint32_t)0x081C0000) /* Base @ of Sector 6, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_7_BANK2 ((uint32_t)0x081E0000) /* Base @ of Sector 7, 128 Kbytes */ + +#define FLASH_IS_EQU 0 /* Flash内容和待写入的数据相等,不需要擦除和写操作 */ +#define FLASH_REQ_WRITE 1 /* Flash不需要擦除,直接写 */ +#define FLASH_REQ_ERASE 2 /* Flash需要先擦除,再写 */ +#define FLASH_PARAM_ERR 3 /* 函数参数错误 */ + + +#define App_Start_Addr 0x08000000 +#define App_Run_Addr 0x08020000 +#define App_Download_Addr 0x08080000 // ADDR_FLASH_SECTOR_4_BANK1 + + + +uint8_t bsp_ReadCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpDst, uint32_t _ulSize); +uint8_t bsp_WriteCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpSrc, uint32_t _ulSize); +uint8_t bsp_CmpCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpBuf, uint32_t _ulSize); +void JumpToApp(void); +void Copy_Peripheral_Download_Flash_to_App_Start(uint32_t totalBytes); +uint8_t bsp_EraseCpuFlash(uint32_t _ulFlashAddr); +void Erase_App_Download_Flash_Addr(); +void Copy_Download_Flash_to_Start(); +#endif /* SRC_BSP_BSP_CPU_FLASH_H_ */ diff --git a/Bingoo/include/base/bsp_decode_command.h b/Bingoo/include/base/bsp_decode_command.h new file mode 100644 index 0000000..494370a --- /dev/null +++ b/Bingoo/include/base/bsp_decode_command.h @@ -0,0 +1,39 @@ +/* + * bsp_decode_command.h + * + * Created on: Sep 24, 2024 + * Author: akeguo + */ + +#ifndef INC_BSP_BSP_DECODE_COMMAND_H_ +#define INC_BSP_BSP_DECODE_COMMAND_H_ +#include "main.h" +#include "msp_WH_LTE_7S0.h" + +#include "pb_decode.h" +#include "pb_encode.h" +#include "bsp_include.h" +#include "pb.h" + +#include "bsp_Cmd.pb.h" +#include +#include +#include + +#include "BHBF_ROBOT.h" +#include "bsp_cpu_flash.h" +#include +#include +#include "bsp_ReCmd.pb.h" +#include "bsp_IV.pb.h" + +void send_received_data_to_upper_computer(uint8_t *buffer, uint16_t length); +void decode_command_and_feedback(uint8_t *buffer, uint16_t length, char sendWay, + struct UARTHandler *send_Handler); + +extern void WrapInCmdAndSend(ReCmd send_Cmd, uint8_t *buf, int8_t sendWay,struct UARTHandler *send_Handler); + + +extern void WrapInCmdAndSendMessage(ReCmd send_Cmd,int8_t functionNum,int8_t isSuccess, uint8_t *buf, int8_t sendWay, + struct UARTHandler *send_Handler); +#endif /* INC_BSP_BSP_DECODE_COMMAND_H_ */ diff --git a/Bingoo/include/base/bsp_ground_management.pb.h b/Bingoo/include/base/bsp_ground_management.pb.h new file mode 100644 index 0000000..7096209 --- /dev/null +++ b/Bingoo/include/base/bsp_ground_management.pb.h @@ -0,0 +1,82 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_BSP_GROUND_MANAGEMENT_PB_H_INCLUDED +#define PB_BSP_GROUND_MANAGEMENT_PB_H_INCLUDED +#include "pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +/* 从机地址0x34; */ +typedef struct _ground_management_struct { + int32_t K1; /* 寄存器0:K1继电器,=0断开,=1吸合 */ + int32_t K2; /* 寄存器1:K2继电器 */ + int32_t K3; /* 寄存器2:K3继电器 */ + int32_t K4; /* 寄存器3:K4继电器 */ + int32_t K5_Default; /* 寄存器4:K5继电器的默认状态,超时寄存器5后,继电器取反(需要周期性收到其有效的modbus数据包) */ + int32_t MaualControlPower; /* 手动控制开关 */ + int32_t MaualPowerState; /* 手动控制开关 */ + int32_t Time_Out_Period; /* 寄存器5:超时时间,毫秒 */ + int32_t DMK_Speed; /* 德玛克电机速度 */ + int32_t DMK_WorkState; /* 0停止 1正转 2反转 */ + int32_t Save_To_Flash; /* 寄存器9:设置为55时,把当前寄存器输入存入flash,写入成功自动变成1 */ + int32_t Read_Time_Out_Period; /* 从寄存器中读取的时间 */ +} ground_management_struct; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define ground_management_struct_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define ground_management_struct_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define ground_management_struct_K1_tag 1 +#define ground_management_struct_K2_tag 2 +#define ground_management_struct_K3_tag 3 +#define ground_management_struct_K4_tag 4 +#define ground_management_struct_K5_Default_tag 5 +#define ground_management_struct_MaualControlPower_tag 6 +#define ground_management_struct_MaualPowerState_tag 7 +#define ground_management_struct_Time_Out_Period_tag 8 +#define ground_management_struct_DMK_Speed_tag 9 +#define ground_management_struct_DMK_WorkState_tag 10 +#define ground_management_struct_Save_To_Flash_tag 11 +#define ground_management_struct_Read_Time_Out_Period_tag 12 + +/* Struct field encoding specification for nanopb */ +#define ground_management_struct_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, K1, 1) \ +X(a, STATIC, SINGULAR, INT32, K2, 2) \ +X(a, STATIC, SINGULAR, INT32, K3, 3) \ +X(a, STATIC, SINGULAR, INT32, K4, 4) \ +X(a, STATIC, SINGULAR, INT32, K5_Default, 5) \ +X(a, STATIC, SINGULAR, INT32, MaualControlPower, 6) \ +X(a, STATIC, SINGULAR, INT32, MaualPowerState, 7) \ +X(a, STATIC, SINGULAR, INT32, Time_Out_Period, 8) \ +X(a, STATIC, SINGULAR, INT32, DMK_Speed, 9) \ +X(a, STATIC, SINGULAR, INT32, DMK_WorkState, 10) \ +X(a, STATIC, SINGULAR, INT32, Save_To_Flash, 11) \ +X(a, STATIC, SINGULAR, INT32, Read_Time_Out_Period, 12) +#define ground_management_struct_CALLBACK NULL +#define ground_management_struct_DEFAULT NULL + +extern const pb_msgdesc_t ground_management_struct_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define ground_management_struct_fields &ground_management_struct_msg + +/* Maximum encoded size of messages (where known) */ +#define BSP_GROUND_MANAGEMENT_PB_H_MAX_SIZE ground_management_struct_size +#define ground_management_struct_size 132 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/bsp_include.h b/Bingoo/include/base/bsp_include.h new file mode 100644 index 0000000..a8d831f --- /dev/null +++ b/Bingoo/include/base/bsp_include.h @@ -0,0 +1,57 @@ +/* + * bsp_include.h + * + * Created on: Oct 26, 2023 + * Author: shiya + */ + +#ifndef INC_BSP_INCLUDE_H_ +#define INC_BSP_INCLUDE_H_ + +#include "main.h" +#include "dma.h" +#include "fdcan.h" +#include "i2c.h" +#include "tim.h" +#include "usart.h" +#include "gpio.h" + +#include "bsp_EEPROM.h" +#include "bsp_GPIO.h" +#include "bsp_FDCAN.h" + +#include "bsp_TIMER.h" +#include "bsp_PV.pb.h" + +#include "bsp_GV.pb.h" +#include "bsp_CV.pb.h" +#include "pb.h" +#include "pb_decode.h" +#include "pb_common.h" +#include "DLTuc.h" +//一个中断回调函数支持多少个回调函数链接 +#define DF_BSP_InterCall_Num 20 + +//一共支持多少种中断函数 +#define DF_BSP_InterCall_Type_Num 11 + +enum DF_BSP_InterCall_Type +{ + DF_BSP_InterCall_FDCAN1_RxFifo0Callback = 0, + DF_BSP_InterCall_FDCAN2_RxFifo0Callback, + DF_BSP_InterCall_RS485_1_RxCpltCallback, + DF_BSP_InterCall_RS485_2_RxCpltCallback, + DF_BSP_InterCall_RS485_3_RxCpltCallback, + DF_BSP_InterCall_RS485_4_RxCpltCallback, + DF_BSP_InterCall_DEBUG_RxCpltCallback, + DF_BSP_InterCall_E22_Serial_RxCpltCallback, + DF_BSP_InterCall_E28_SBUS_RxFifo0Callback, + DF_BSP_InterCall_TIM1_100ms_PeriodElapsedCallback, + DF_BSP_InterCall_TIM8_2ms_PeriodElapsedCallback +}; + +uint8_t GF_BSP_Interrupt_Add_CallBack(enum DF_BSP_InterCall_Type _type, + void (*_fn)(void)); +void GF_BSP_Interrupt_Run_CallBack(enum DF_BSP_InterCall_Type _type); + +#endif /* INC_BSP_INCLUDE_H_ */ diff --git a/Bingoo/include/base/bsp_mqtt.h b/Bingoo/include/base/bsp_mqtt.h new file mode 100644 index 0000000..f7bb15d --- /dev/null +++ b/Bingoo/include/base/bsp_mqtt.h @@ -0,0 +1,36 @@ + +#ifndef __BSP_MQTT_H +#define __BSP_MQTT_H + +/*----------------------------------------------------------- + * Includes files + *----------------------------------------------------------*/ + +/*----------------------------------------------------------- + * Exported constants + *----------------------------------------------------------*/ + + +/*----------------------------------------------------------- + * Exported macro + *----------------------------------------------------------*/ + +/*----------------------------------------------------------- + * Exported function + *----------------------------------------------------------*/ +/*! +* @brief 封装 MQTT 初始化接口 +* 执行条件:无 +* +* @retval: 无 +*/ +void bsp_mqtt_init(void); +void bsp_mqtt_test(void); + + +extern void bsp_mqtt_pub_send(char topic[],char buf[],size_t len); + + +#include "bsp_pb_decode_encode.h" + +#endif /* __BSP_WOLFSSL_H */ diff --git a/Bingoo/include/base/bsp_mqtt_pub.h b/Bingoo/include/base/bsp_mqtt_pub.h new file mode 100644 index 0000000..3764cb0 --- /dev/null +++ b/Bingoo/include/base/bsp_mqtt_pub.h @@ -0,0 +1,26 @@ +/* + * bsp_mqtt_pub.h + * + * Created on: Jul 9, 2024 + * Author: akeguo + */ + +#ifndef INC_BSP_BSP_MQTT_PUB_H_ +#define INC_BSP_BSP_MQTT_PUB_H_ + +#include "bsp_pb_decode_encode.h" +#include "pb_decode.h" +#include "pb_encode.h" +#include "bsp_CV.pb.h" +#include "bsp_pb_decode_encode.h" +#include "BSP/bsp_EEPROM.h" + + + + + +extern void log_info(char logger[], char message[]); +extern void log_debug(char logger[], char message[]); +extern void log_err(char logger[], char message[]); + +#endif /* INC_BSP_BSP_MQTT_PUB_H_ */ diff --git a/Bingoo/include/base/bsp_pb_decode_encode.h b/Bingoo/include/base/bsp_pb_decode_encode.h new file mode 100644 index 0000000..8480dbe --- /dev/null +++ b/Bingoo/include/base/bsp_pb_decode_encode.h @@ -0,0 +1,51 @@ +/* + * bsp_pb_decode_encode.h + * + * Created on: Jul 5, 2024 + * Author: akeguo + */ + +#ifndef INC_BSP_BSP_PB_DECODE_ENCODE_H_ +#define INC_BSP_BSP_PB_DECODE_ENCODE_H_ + +#include +#include +#include +#include + +#include "pb_decode.h" +#include "pb_encode.h" +#include "pb.h" +#include "bsp_CV.pb.h" +#include "bsp_GV.pb.h" +#include "msp_MK32.pb.h" +#include "msp_Motor.pb.h" +#include "bsp_PV.pb.h" +#include "bsp_CV.pb.h" +#include "bsp_CV.pb.h" +#include "pb_common.h" + +#include "bsp_IAP.pb.h" +IAP_struct_define pb_decode_IAP(uint8_t *buf, size_t length); + +typedef struct pb_buffer_arg +{ + /* Buffer to be written, or reference to read buffer */ + void const *buf; + /* Length of buf */ + size_t buf_len; +} pb_buffer_arg; + + + bool pb_encode_string_cb(pb_ostream_t *stream, const pb_field_t *field, void *const *arg); + bool pb_decode_string_cb(pb_istream_t *stream, const pb_field_t *field, void **arg); + + +extern CV_struct_define pb_decode_CV(char *buf, size_t length); +extern void Test_CV(); + +//extern void pb_encode_TraceMessage(char buf[], size_t buf_len,size_t* len,TraceLevel traceLevel, char logger[], char message[] ); +void pb_encode_TraceMessage(char buf[],size_t buf_len, size_t* len, + char traceLevel[], char logger[], char message[] ); + +#endif /* INC_BSP_BSP_PB_DECODE_ENCODE_H_ */ diff --git a/Bingoo/include/base/bsp_qspi_w25q128.h b/Bingoo/include/base/bsp_qspi_w25q128.h new file mode 100644 index 0000000..61791e4 --- /dev/null +++ b/Bingoo/include/base/bsp_qspi_w25q128.h @@ -0,0 +1,107 @@ +/* + * bsp_quadspi_W25Q128.h + * + * Created on: Apr 21, 2021 + * Author: Administrator + * + * 该bsp用于华邦的w25q128JV,跟华邦的w25q128JV不一样 + * 坑爹的 + */ + +#ifndef BSP_QSPI_W25Q128_H_ +#define BSP_QSPI_W25Q128_H_ + + +#include "quadspi.h" +#include "stdio.h" + +/* 宏定义 --------------------------------------------------------------------*/ +#define FLASH_BEGIN_ADDRESS 0x00000 + +#define CODE_DOWNLOAD_FLASH_BEGIN_ADDRESS 0x00000 +#define CODE_FLASH_STORAGE_SIZE 1024*1024 // 留下1M的空间存储数据 + +#define W25Q128FV_FLASH_SIZE 0x1000000 /* 128 MBits => 16MBytes */ +#define W25Q128FV_BLOCK_SIZE 0x10000 /* 256 Blocks of 64KBytes */ +#define W25Q128FV_HALF_BLOCK_SIZE 0x8000 /* 128 Blocks of 32KBytes */ +#define W25Q128FV_SECTOR_SIZE 0x1000 /* 4096 sectors of 4kBytes */ +#define W25Q128FV_PAGE_SIZE 0x100 /* 65536 pages of 256 bytes */ + +#define W25Q128FV_DUMMY_CYCLES_READ 4 +#define W25Q128FV_DUMMY_CYCLES_READ_QUAD 10 + +#define W25Q128FV_BULK_ERASE_MAX_TIME 250000//ms +#define W25Q128FV_SECTOR_ERASE_MAX_TIME 3000 +#define W25Q128FV_SUBSECTOR_ERASE_MAX_TIME 800 + +#define W25Q128FV_FLASH_ID 0XEF4018 +/* W25Q128FV 指令 */ +/* 复位操作 */ +#define RESET_ENABLE_CMD 0x66 +#define RESET_MEMORY_CMD 0x99 + +#define ENTER_QPI_MODE_CMD 0x38 +#define EXIT_QPI_MODE_CMD 0xFF + +/* 读取ID指令 */ +#define READ_ID_CMD 0x90 +#define DUAL_READ_ID_CMD 0x92 +#define QUAD_READ_ID_CMD 0x94 +#define READ_JEDEC_ID_CMD 0x9F + +/* 读操作指令 */ +#define READ_CMD 0x03 +#define FAST_READ_CMD 0x0B +#define DUAL_OUT_FAST_READ_CMD 0x3B +#define DUAL_INOUT_FAST_READ_CMD 0xBB +#define QUAD_OUT_FAST_READ_CMD 0x6B +#define QUAD_INOUT_FAST_READ_CMD 0xEB + +/* 写使能操作指令 */ +#define WRITE_ENABLE_CMD 0x06 +#define WRITE_DISABLE_CMD 0x04 + +/* 读写状态寄存器操作指令 */ +#define READ_STATUS_REG1_CMD 0x05 +#define READ_STATUS_REG2_CMD 0x35 +#define READ_STATUS_REG3_CMD 0x15 + +#define WRITE_STATUS_REG1_CMD 0x01 +#define WRITE_STATUS_REG2_CMD 0x31 +#define WRITE_STATUS_REG3_CMD 0x11 + +/* 编程指令 */ +#define PAGE_PROG_CMD 0x02 +#define QUAD_INPUT_PAGE_PROG_CMD 0x32 + +/* 擦除Flash指令 */ +#define SECTOR_ERASE_CMD 0x20 +#define BLOCK_32KB_ERASE_CMD 0x52 +#define BLOCK_64KB_ERASE_CMD 0xD8 +#define CHIP_ERASE_CMD 0xC7 + +#define PROG_ERASE_RESUME_CMD 0x7A +#define PROG_ERASE_SUSPEND_CMD 0x75 + +/* 状态寄存器标志位 */ +#define W25Q128FV_FSR_BUSY ((uint8_t)0x01) /* busy */ +#define W25Q128FV_FSR_WREN ((uint8_t)0x02) /* write enable */ +#define W25Q128FV_FSR_QE ((uint8_t)0x02) /* quad enable */ + +/* Flash 状态码*/ +#define FLASH_OK ((uint8_t)0x00) +#define FLASH_ERROR ((uint8_t)0x01) +#define FLASH_BUSY ((uint8_t)0x02) +#define FLASH_NOT_SUPPORTED ((uint8_t)0x04) +#define FLASH_SUSPENDED ((uint8_t)0x08) + + + +uint32_t QSPI_W25Qx_ReadID(void); +void QSPI_W25Qx_Reset_Memory(); +void QSPI_W25Qx_EraseSector(uint32_t _SectorAddr); +uint8_t QSPI_W25Qx_Write_Buffer(uint8_t *_pBuf,uint32_t _write_Addr,uint16_t _write_Size); +void QSPI_W25Qx_Read_Buffer(uint8_t *_pBuf,uint32_t _read_Addr,uint32_t _read_Size); +void QSPI_W25Qx_EraseDownLoadFlash(); +void user_Assert(char *file,uint32_t line); +#endif /* BSP_QSPI_W25Q128_H_ */ diff --git a/Bingoo/include/base/bsp_slide_averager.h b/Bingoo/include/base/bsp_slide_averager.h new file mode 100644 index 0000000..6672ebf --- /dev/null +++ b/Bingoo/include/base/bsp_slide_averager.h @@ -0,0 +1,14 @@ +/* + * bsp_slide_averager.h + * + * Created on: 2026年3月20日 + * Author: L1ng the codeGod + */ + +#ifndef BASE_INC_BSP_BSP_SLIDE_AVERAGER_H_ +#define BASE_INC_BSP_BSP_SLIDE_AVERAGER_H_ + +void slide_averager_init(float buffer[], uint8_t *p_index, uint8_t *p_count); +float slide_averager_calc(float buffer[], uint8_t *p_index, uint8_t *p_count, float new_data); + +#endif /* BASE_INC_BSP_BSP_SLIDE_AVERAGER_H_ */ diff --git a/Bingoo/include/base/bsp_strain_gauge.pb.h b/Bingoo/include/base/bsp_strain_gauge.pb.h new file mode 100644 index 0000000..d1839a4 --- /dev/null +++ b/Bingoo/include/base/bsp_strain_gauge.pb.h @@ -0,0 +1,61 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_BSP_STRAIN_GAUGE_PB_H_INCLUDED +#define PB_BSP_STRAIN_GAUGE_PB_H_INCLUDED +#include "pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +/* 从机地址0x32; */ +typedef struct _Strain_Gauge_Struct { + int32_t MotorControl; /* 寄存器0: 电机控制,=0 停止,=1 前进,=2 后退 */ + int32_t Pressure; /* 寄存器1: 输出的传感器最终数据 */ + int32_t HX711_K; /* 寄存器2 HX711_K */ + int32_t HX711_D; /* 寄存器3 HX711_D */ + int32_t Save; /* 寄存器9: 设置为55时,把当前寄存器输入存入flash,写入成功自动变成1 */ +} Strain_Gauge_Struct; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define Strain_Gauge_Struct_init_default {0, 0, 0, 0, 0} +#define Strain_Gauge_Struct_init_zero {0, 0, 0, 0, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define Strain_Gauge_Struct_MotorControl_tag 1 +#define Strain_Gauge_Struct_Pressure_tag 2 +#define Strain_Gauge_Struct_HX711_K_tag 3 +#define Strain_Gauge_Struct_HX711_D_tag 4 +#define Strain_Gauge_Struct_Save_tag 5 + +/* Struct field encoding specification for nanopb */ +#define Strain_Gauge_Struct_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, MotorControl, 1) \ +X(a, STATIC, SINGULAR, INT32, Pressure, 2) \ +X(a, STATIC, SINGULAR, INT32, HX711_K, 3) \ +X(a, STATIC, SINGULAR, INT32, HX711_D, 4) \ +X(a, STATIC, SINGULAR, INT32, Save, 5) +#define Strain_Gauge_Struct_CALLBACK NULL +#define Strain_Gauge_Struct_DEFAULT NULL + +extern const pb_msgdesc_t Strain_Gauge_Struct_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define Strain_Gauge_Struct_fields &Strain_Gauge_Struct_msg + +/* Maximum encoded size of messages (where known) */ +#define BSP_STRAIN_GAUGE_PB_H_MAX_SIZE Strain_Gauge_Struct_size +#define Strain_Gauge_Struct_size 55 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/bsp_tempature.h b/Bingoo/include/base/bsp_tempature.h new file mode 100644 index 0000000..a93fdb0 --- /dev/null +++ b/Bingoo/include/base/bsp_tempature.h @@ -0,0 +1,19 @@ +/* + * bsp_adc.h + * + * Created on: Feb 21, 2025 + * Author: akeguo + */ + +#ifndef INC_BSP_BSP_TEMPATURE_H_ +#define INC_BSP_BSP_TEMPATURE_H_ + + +#include "main.h" +#include "DLTuc.h" + +int32_t read_temperature(); +void ADC_Intialize(); + +extern int32_t * tempature; +#endif /* INC_BSP_BSP_TEMPATURE_H_ */ diff --git a/Bingoo/include/base/change_line_control.h b/Bingoo/include/base/change_line_control.h new file mode 100644 index 0000000..e1e08a8 --- /dev/null +++ b/Bingoo/include/base/change_line_control.h @@ -0,0 +1,56 @@ +/* + * change_line_control.h + * + * Created on: 2025年8月12日 + * Author: xsq + */ + +#ifndef FSM_INC_CHANGE_LINE_CONTROL_H_ +#define FSM_INC_CHANGE_LINE_CONTROL_H_ + + +typedef enum _vertical_LaneChangeState +{ + VerticalChange_TurnToUP, + VerticalChange_TurnToDown, + VerticalChange_TurnToLeft, + VerticalChange_TurnToRight, + VerticalChange_DelayMove, + VerticalChange_End, + VerticalChange_StateZero, + //0---6 +} Lane_Vertical_ChangeState; +/**********************************************************/ +typedef enum _horizontal_LaneChangeState +{ + HorizontalChange_TurnToUP, + HorizontalChange_TurnToDown, + HorizontalChange_TurnToLeft, + HorizontalChange_TurnToRight, + HorizontalChange_DelayMove, + HorizontalChange_End, + HorizontalChange_StateZero, + +} Lane_Horizontal_ChangeState; +/***********************************************************************/ +//设置 换道距离和设置后退距离 +typedef enum _laneChangeControlSTATE_t +{ + Lane_Change_Stop = 0, Lane_Change_Start, + +} LaneChangeControlSTATE; +/*****************************************************************************/ +extern Lane_Vertical_ChangeState Current_Vertical_ChangeState; + +extern LaneChangeControlSTATE VerticalLaneChangeState; /*当前换道处于开始或者结束*/ +extern int LaneChangeControl_Paint(); + + + +extern void Vertical_Lane_Change_From_Left_To_Right_UP_Control(); +extern void Vertical_Lane_Change_From_Left_To_Right_Down_Control(); +extern void Vertical_Lane_Change_From_Right_To_Left_UP_Control(); +extern void Vertical_Lane_Change_From_Right_To_Left_Down_Control(); + +extern int LaneChangeWaittime ; +#endif /* FSM_INC_CHANGE_LINE_CONTROL_H_ */ diff --git a/Bingoo/include/base/fsm_state.h b/Bingoo/include/base/fsm_state.h new file mode 100644 index 0000000..2bd95b7 --- /dev/null +++ b/Bingoo/include/base/fsm_state.h @@ -0,0 +1,44 @@ +/* + * fsm.h + * + * Created on: 2025年7月14日 + * Author: akeguo + */ + +#ifndef FSM_INC_FSM_STATE_H_ +#define FSM_INC_FSM_STATE_H_ +#include "stdint.h" +#include + + +struct _transition_t; +typedef struct _transition_t transition_t; + + +//抽象类,用于派生其他类 将事件处理方法包含在基类中 + +typedef struct _transition_state_t +{ + + void (*robotEnter)(transition_t* p_transition); //执行Enter 激活标志位 + void (*robotRun)(transition_t* p_transition); //执行相关动作 + void (*robotExit)(transition_t* p_transition); //执行Exit + int State; //状态 + +}transition_state_t; + + + +typedef struct _transition_t { + transition_state_t* p_state; +}transition_t; + + +extern void fsm_state_set(transition_t* p_this, transition_state_t* p_new_state); +extern void fsm_state_run(transition_t* p_this); + +extern void fsm_state_init(transition_t* p_this,transition_state_t* inti_state); + + + +#endif /* FSM_INC_FSM_STATE_H_ */ diff --git a/Bingoo/include/base/fsm_state_control.h b/Bingoo/include/base/fsm_state_control.h new file mode 100644 index 0000000..b39ef66 --- /dev/null +++ b/Bingoo/include/base/fsm_state_control.h @@ -0,0 +1,18 @@ +/* + * fsm_state_control.h + * + * Created on: Jan 13, 2026 + * Author: bm673 + */ + +#ifndef FSM_INC_FSM_STATE_CONTROL_H_ +#define FSM_INC_FSM_STATE_CONTROL_H_ + +void Fsm_Init(); +void GF_Dispatch(); +void IV_control(); +int AbnormalDetect(); + +typedef void (*ActionFunc)(void); + +#endif /* FSM_INC_FSM_STATE_CONTROL_H_ */ diff --git a/Bingoo/include/base/motor.h b/Bingoo/include/base/motor.h new file mode 100644 index 0000000..4fc052f --- /dev/null +++ b/Bingoo/include/base/motor.h @@ -0,0 +1,21 @@ +/* + * motor.h + * + * Created on: 2026年1月29日 + * Author: bm673 + */ + +#ifndef FSM_INC_MOTOR_H_ +#define FSM_INC_MOTOR_H_ + + + + + + + + + + + +#endif /* FSM_INC_MOTOR_H_ */ diff --git a/Bingoo/include/base/motors.h b/Bingoo/include/base/motors.h new file mode 100644 index 0000000..bcfabf8 --- /dev/null +++ b/Bingoo/include/base/motors.h @@ -0,0 +1,26 @@ +/* + * LS_CAN_Motor_Frames.h + * + * Created on: Mar 21, 2025 + * Author: BingooRobotFJX + */ + +#ifndef SRC_LS_CAN_MOTOR_FRAMES_H_ +#define SRC_LS_CAN_MOTOR_FRAMES_H_ + +#include "BHBF_ROBOT.h" +#include "bsp_FDCAN.h" +#include "bsp_Error_Detect.h" + + + +extern char LS_Motor_Need_To_Activate; +void LS_Motor_Controller_intialize(FDCANHandler *Handler); +void Motor_Controller_intialize_CAN2(FDCANHandler *Handler); + +void LS_Motor_DOSet(uint8_t state); +int32_t speed_m_per_min_to_pulse_s(int32_t speed_m_per_min); + +int32_t RunTime_DistanceCm_SpeedE_2MPMin(); + +#endif /* SRC_LS_CAN_MOTOR_FRAMES_H_ */ diff --git a/Bingoo/include/base/motors_power_action.h b/Bingoo/include/base/motors_power_action.h new file mode 100644 index 0000000..fa01361 --- /dev/null +++ b/Bingoo/include/base/motors_power_action.h @@ -0,0 +1,31 @@ +/* + * motors_power_action.h + * + * Created on: 2025年7月14日 + * Author: akeguo + */ + +#ifndef FSM_INC_MOTORS_POWER_ACTION_H_ +#define FSM_INC_MOTORS_POWER_ACTION_H_ + +#include "fsm_state.h" + + + + + +void Motors_Power_On_Do(transition_t *p_this); +void Motors_Power_Off_Do(transition_t *p_this); +void Motors_Power_On_Enter(transition_t *p_this); +void Motors_Power_On_Exit(transition_t *p_this); + + + +extern transition_t current_motor_power_state; + +extern transition_state_t motor_power_on_state; +extern transition_state_t motor_power_off_state; + + + +#endif /* FSM_INC_MOTORS_POWER_ACTION_H_ */ diff --git a/Bingoo/include/base/msp_DAM_Relay.h b/Bingoo/include/base/msp_DAM_Relay.h new file mode 100644 index 0000000..f1e1bee --- /dev/null +++ b/Bingoo/include/base/msp_DAM_Relay.h @@ -0,0 +1,15 @@ +/* + * msp_DAM_Relay.h + * + * Created on: Nov 5, 2024 + * Author: akeguo + */ + +#ifndef INC_MSP_MSP_DAM_RELAY_H_ +#define INC_MSP_MSP_DAM_RELAY_H_ + +#include "BHBF_ROBOT.h" +extern int32_t DMA_DO_Value_[4]; +void DAM_Relay_intialize(struct UARTHandler *Handler); + +#endif /* INC_MSP_MSP_DAM_RELAY_H_ */ diff --git a/Bingoo/include/base/msp_Force_Sensor.h b/Bingoo/include/base/msp_Force_Sensor.h new file mode 100644 index 0000000..8548a94 --- /dev/null +++ b/Bingoo/include/base/msp_Force_Sensor.h @@ -0,0 +1,13 @@ +/* + * msp_Force_Sensor.h + * + * Created on: Oct 8, 2024 + * Author: akeguo + */ + +#ifndef INC_MSP_MSP_FORCE_SENSOR_H_ +#define INC_MSP_MSP_FORCE_SENSOR_H_ +#include "bsp_MB_host.h" +extern void force_sensor_intialize(struct UARTHandler *Handler); +extern int32_t* ForceValue; +#endif /* INC_MSP_MSP_FORCE_SENSOR_H_ */ diff --git a/Bingoo/include/base/msp_JTBATTERY.h b/Bingoo/include/base/msp_JTBATTERY.h new file mode 100644 index 0000000..777a51b --- /dev/null +++ b/Bingoo/include/base/msp_JTBATTERY.h @@ -0,0 +1,15 @@ +/* + * msp_JTBATTERY.h + * + * Created on: Oct 26, 2023 + * Author: shiya + */ + +#ifndef INC_MSP_MSP_JTBATTERY_H_ +#define INC_MSP_MSP_JTBATTERY_H_ + +#include "BSP/bsp_include.h" + + + +#endif /* INC_MSP_MSP_JTBATTERY_H_ */ diff --git a/Bingoo/include/base/msp_MK32.pb.h b/Bingoo/include/base/msp_MK32.pb.h new file mode 100644 index 0000000..d707cb7 --- /dev/null +++ b/Bingoo/include/base/msp_MK32.pb.h @@ -0,0 +1,99 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_MSP_MK32_PB_H_INCLUDED +#define PB_MSP_MK32_PB_H_INCLUDED +#include "pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +typedef struct _SP_MSP_MK32_Button { + int32_t RxIndex; + int32_t CH0_RY_H; /* 上1000,下-1000 */ + int32_t CH1_RY_V; /* 上1000,下-1000 */ + int32_t CH2_LY_V; /* 上1000,下-1000 */ + int32_t CH3_LY_H; /* 上1000,下-1000 */ + int32_t CH4_SA; /* 上-1000,下1000 */ + int32_t CH5_SB; /* 上-1000,下1000 */ + int32_t CH6_SC; /* 上-1000,下1000 */ + int32_t CH7_SD; /* 上-1000,下1000 */ + int32_t CH8_SE; /* 上-1000,下1000 */ + int32_t CH9_SF; /* 上-1000,下1000 */ + int32_t CH10_LD1; + int32_t CH11_RD1; + int32_t CH12_S1; + int32_t CH13_S2; + int32_t CH14_LT; + int32_t CH15_RT; + int32_t IsOnline; +} SP_MSP_MK32_Button; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define SP_MSP_MK32_Button_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define SP_MSP_MK32_Button_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define SP_MSP_MK32_Button_RxIndex_tag 1 +#define SP_MSP_MK32_Button_CH0_RY_H_tag 2 +#define SP_MSP_MK32_Button_CH1_RY_V_tag 3 +#define SP_MSP_MK32_Button_CH2_LY_V_tag 4 +#define SP_MSP_MK32_Button_CH3_LY_H_tag 5 +#define SP_MSP_MK32_Button_CH4_SA_tag 6 +#define SP_MSP_MK32_Button_CH5_SB_tag 7 +#define SP_MSP_MK32_Button_CH6_SC_tag 8 +#define SP_MSP_MK32_Button_CH7_SD_tag 9 +#define SP_MSP_MK32_Button_CH8_SE_tag 10 +#define SP_MSP_MK32_Button_CH9_SF_tag 11 +#define SP_MSP_MK32_Button_CH10_LD1_tag 12 +#define SP_MSP_MK32_Button_CH11_RD1_tag 13 +#define SP_MSP_MK32_Button_CH12_S1_tag 14 +#define SP_MSP_MK32_Button_CH13_S2_tag 15 +#define SP_MSP_MK32_Button_CH14_LT_tag 16 +#define SP_MSP_MK32_Button_CH15_RT_tag 17 +#define SP_MSP_MK32_Button_IsOnline_tag 18 + +/* Struct field encoding specification for nanopb */ +#define SP_MSP_MK32_Button_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, RxIndex, 1) \ +X(a, STATIC, SINGULAR, INT32, CH0_RY_H, 2) \ +X(a, STATIC, SINGULAR, INT32, CH1_RY_V, 3) \ +X(a, STATIC, SINGULAR, INT32, CH2_LY_V, 4) \ +X(a, STATIC, SINGULAR, INT32, CH3_LY_H, 5) \ +X(a, STATIC, SINGULAR, INT32, CH4_SA, 6) \ +X(a, STATIC, SINGULAR, INT32, CH5_SB, 7) \ +X(a, STATIC, SINGULAR, INT32, CH6_SC, 8) \ +X(a, STATIC, SINGULAR, INT32, CH7_SD, 9) \ +X(a, STATIC, SINGULAR, INT32, CH8_SE, 10) \ +X(a, STATIC, SINGULAR, INT32, CH9_SF, 11) \ +X(a, STATIC, SINGULAR, INT32, CH10_LD1, 12) \ +X(a, STATIC, SINGULAR, INT32, CH11_RD1, 13) \ +X(a, STATIC, SINGULAR, INT32, CH12_S1, 14) \ +X(a, STATIC, SINGULAR, INT32, CH13_S2, 15) \ +X(a, STATIC, SINGULAR, INT32, CH14_LT, 16) \ +X(a, STATIC, SINGULAR, INT32, CH15_RT, 17) \ +X(a, STATIC, SINGULAR, INT32, IsOnline, 18) +#define SP_MSP_MK32_Button_CALLBACK NULL +#define SP_MSP_MK32_Button_DEFAULT NULL + +extern const pb_msgdesc_t SP_MSP_MK32_Button_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define SP_MSP_MK32_Button_fields &SP_MSP_MK32_Button_msg + +/* Maximum encoded size of messages (where known) */ +#define MSP_MK32_PB_H_MAX_SIZE SP_MSP_MK32_Button_size +#define SP_MSP_MK32_Button_size 201 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/msp_MK32_1.h b/Bingoo/include/base/msp_MK32_1.h new file mode 100644 index 0000000..9c48328 --- /dev/null +++ b/Bingoo/include/base/msp_MK32_1.h @@ -0,0 +1,18 @@ +/* + * msp_MK32_1.h + * + * Created on: Oct 8, 2024 + * Author: akeguo + */ + +#ifndef INC_MSP_MSP_MK32_1_H_ +#define INC_MSP_MSP_MK32_1_H_ +#include "BSP/bsp_UART.h" +#include "msp_MK32.pb.h" +void Sbus_Data_Count(uint8_t *buf, int32_t *But_Value); +extern SP_MSP_MK32_Button *P_MK32; + +extern char ReceivedFromMK32; +void MK32_Sbus_UART_Handler_intialize(struct UARTHandler* Handler); +extern char Is_All_Button_Reset; +#endif /* INC_MSP_MSP_MK32_1_H_ */ diff --git a/Bingoo/include/base/msp_Motor.pb.h b/Bingoo/include/base/msp_Motor.pb.h new file mode 100644 index 0000000..44fcab2 --- /dev/null +++ b/Bingoo/include/base/msp_Motor.pb.h @@ -0,0 +1,91 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_MSP_MOTOR_PB_H_INCLUDED +#define PB_MSP_MOTOR_PB_H_INCLUDED +#include "pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +typedef struct _MotorParameters { + int32_t MotorID; + int32_t RxIndex; + int32_t Run_Mode; + int32_t Current; + int32_t Target_Current; + int32_t Velcity; + int32_t Target_Velcity; + int32_t Position; + int32_t Target_Position; + int32_t ERROR_Flag; + int32_t Temperature_Motor; + int32_t Temperature_PCB; + int32_t AccTime; + int32_t DecTime; + int32_t EncoderOffset; /* 53 83 设置位置偏移 int32_t "设置偏移值和目标位置 +(目标位置=编码器位置 - 偏移值)" */ +} MotorParameters; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define MotorParameters_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define MotorParameters_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define MotorParameters_MotorID_tag 1 +#define MotorParameters_RxIndex_tag 2 +#define MotorParameters_Run_Mode_tag 3 +#define MotorParameters_Current_tag 4 +#define MotorParameters_Target_Current_tag 5 +#define MotorParameters_Velcity_tag 6 +#define MotorParameters_Target_Velcity_tag 7 +#define MotorParameters_Position_tag 8 +#define MotorParameters_Target_Position_tag 9 +#define MotorParameters_ERROR_Flag_tag 10 +#define MotorParameters_Temperature_Motor_tag 11 +#define MotorParameters_Temperature_PCB_tag 12 +#define MotorParameters_AccTime_tag 13 +#define MotorParameters_DecTime_tag 14 +#define MotorParameters_EncoderOffset_tag 15 + +/* Struct field encoding specification for nanopb */ +#define MotorParameters_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, MotorID, 1) \ +X(a, STATIC, SINGULAR, INT32, RxIndex, 2) \ +X(a, STATIC, SINGULAR, INT32, Run_Mode, 3) \ +X(a, STATIC, SINGULAR, INT32, Current, 4) \ +X(a, STATIC, SINGULAR, INT32, Target_Current, 5) \ +X(a, STATIC, SINGULAR, INT32, Velcity, 6) \ +X(a, STATIC, SINGULAR, INT32, Target_Velcity, 7) \ +X(a, STATIC, SINGULAR, INT32, Position, 8) \ +X(a, STATIC, SINGULAR, INT32, Target_Position, 9) \ +X(a, STATIC, SINGULAR, INT32, ERROR_Flag, 10) \ +X(a, STATIC, SINGULAR, INT32, Temperature_Motor, 11) \ +X(a, STATIC, SINGULAR, INT32, Temperature_PCB, 12) \ +X(a, STATIC, SINGULAR, INT32, AccTime, 13) \ +X(a, STATIC, SINGULAR, INT32, DecTime, 14) \ +X(a, STATIC, SINGULAR, INT32, EncoderOffset, 15) +#define MotorParameters_CALLBACK NULL +#define MotorParameters_DEFAULT NULL + +extern const pb_msgdesc_t MotorParameters_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define MotorParameters_fields &MotorParameters_msg + +/* Maximum encoded size of messages (where known) */ +#define MSP_MOTOR_PB_H_MAX_SIZE MotorParameters_size +#define MotorParameters_size 165 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/msp_PID.h b/Bingoo/include/base/msp_PID.h new file mode 100644 index 0000000..c7951a2 --- /dev/null +++ b/Bingoo/include/base/msp_PID.h @@ -0,0 +1,20 @@ + +/* + * msp_PID.h - 两轮差速机器人角度追踪PID(内置参数,数组输出) + */ + +#ifndef INC_MSP_MSP_PID_H_ +#define INC_MSP_MSP_PID_H_ +/** + * @brief 两轮差速角度控制(内置 dt=0.1s,最大速度 = 1.6 * |base_speed|) + * @param current_angle 当前角度(度) + * @param desired_angle 期望角度(度) + * @param base_speed 基础前进速度(可正可负) + * @param speeds 输出速度数组,speeds[0]=左轮,speeds[1]=右轮 + */ +void TwoWheel_AngleControl(float current_angle, float desired_angle, + float base_speed,float zoom, float speeds[2]); +void TwoWheel_AngleControl_Weld(float current_angle, float desired_angle, + float base_speed,float zoom, float speeds[2]); + +#endif diff --git a/Bingoo/include/base/msp_TL720D.h b/Bingoo/include/base/msp_TL720D.h new file mode 100644 index 0000000..8b380da --- /dev/null +++ b/Bingoo/include/base/msp_TL720D.h @@ -0,0 +1,24 @@ +/* + * msp_TL720D.h + * + * Created on: Jul 19, 2024 + * Author: bihon + */ + +#ifndef INC_MSP_MSP_TL720D_H_ +#define INC_MSP_MSP_TL720D_H_ + +#include +#include +#include "bsp_MB_host.h" +#include "stdio.h" +#include "BSP/bsp_UART.h" +#include "usart.h" +#include "gpio.h" + +void TL720D_intialize(struct UARTHandler *Handler); + +extern MSP_TL720DParameters* SP_MSP_RF_TL720D_Parameters_In; +extern int32_t *RobotAngle;//机器人角度 + +#endif /* INC_MSP_MSP_TL720D_H_ */ diff --git a/Bingoo/include/base/msp_TL720D.pb.h b/Bingoo/include/base/msp_TL720D.pb.h new file mode 100644 index 0000000..6020cd6 --- /dev/null +++ b/Bingoo/include/base/msp_TL720D.pb.h @@ -0,0 +1,72 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_MSP_TL720D_PB_H_INCLUDED +#define PB_MSP_TL720D_PB_H_INCLUDED +#include "pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +typedef struct _MSP_TL720DParameters { + int32_t RF_Angle_Roll; /* 横滚角 */ + int32_t RF_Angle_Pitch; /* 俯仰角 */ + int32_t RF_Angle_Yaw; /* 航向角 */ + int32_t RF_Acc_X; /* X轴加速度 */ + int32_t RF_Acc_Y; /* Y轴加速度 */ + int32_t RF_Acc_Z; /* Z轴加速度 */ + int32_t RF_Gro_X; /* X轴陀螺 */ + int32_t RF_Gro_Y; /* Y轴陀螺 */ + int32_t RF_Gro_Z; /* Z轴陀螺 */ +} MSP_TL720DParameters; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define MSP_TL720DParameters_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0} +#define MSP_TL720DParameters_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define MSP_TL720DParameters_RF_Angle_Roll_tag 1 +#define MSP_TL720DParameters_RF_Angle_Pitch_tag 2 +#define MSP_TL720DParameters_RF_Angle_Yaw_tag 3 +#define MSP_TL720DParameters_RF_Acc_X_tag 4 +#define MSP_TL720DParameters_RF_Acc_Y_tag 5 +#define MSP_TL720DParameters_RF_Acc_Z_tag 6 +#define MSP_TL720DParameters_RF_Gro_X_tag 7 +#define MSP_TL720DParameters_RF_Gro_Y_tag 8 +#define MSP_TL720DParameters_RF_Gro_Z_tag 9 + +/* Struct field encoding specification for nanopb */ +#define MSP_TL720DParameters_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, RF_Angle_Roll, 1) \ +X(a, STATIC, SINGULAR, INT32, RF_Angle_Pitch, 2) \ +X(a, STATIC, SINGULAR, INT32, RF_Angle_Yaw, 3) \ +X(a, STATIC, SINGULAR, INT32, RF_Acc_X, 4) \ +X(a, STATIC, SINGULAR, INT32, RF_Acc_Y, 5) \ +X(a, STATIC, SINGULAR, INT32, RF_Acc_Z, 6) \ +X(a, STATIC, SINGULAR, INT32, RF_Gro_X, 7) \ +X(a, STATIC, SINGULAR, INT32, RF_Gro_Y, 8) \ +X(a, STATIC, SINGULAR, INT32, RF_Gro_Z, 9) +#define MSP_TL720DParameters_CALLBACK NULL +#define MSP_TL720DParameters_DEFAULT NULL + +extern const pb_msgdesc_t MSP_TL720DParameters_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define MSP_TL720DParameters_fields &MSP_TL720DParameters_msg + +/* Maximum encoded size of messages (where known) */ +#define MSP_TL720DParameters_size 99 +#define MSP_TL720D_PB_H_MAX_SIZE MSP_TL720DParameters_size + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/msp_TTMotor_ZQ.h b/Bingoo/include/base/msp_TTMotor_ZQ.h new file mode 100644 index 0000000..d98f8e9 --- /dev/null +++ b/Bingoo/include/base/msp_TTMotor_ZQ.h @@ -0,0 +1,105 @@ +/* + * msp_TTMotor_ZQ.h + * + * Created on: Oct 10, 2024 + * Author: akeguo + */ + +#ifndef INC_MSP_MSP_TTMOTOR_ZQ_H_ +#define INC_MSP_MSP_TTMOTOR_ZQ_H_ +#include "bsp_include.h" +#include "bsp_FDCAN.h" +#include "msp_ZQ_MotorParameters.pb.h" + + +#include "fsm.h" + +#define DF_MSP_TT_Motor_PositionMode 01 +#define DF_MSP_TT_Motor_SpeedMode 02 +#define DF_MSP_TT_Motor_CurrentMode 03 +#define DF_MSP_TT_Motor_Posi_Now 04 + +#define TT_One_Deg_Count 11014///32768*121/360(减速比121)=11014 + +#define TT_Left_limt 84080 //-775000+75*11014 +#define TT_Right_limt -1568020 //-775000-75*11014 +//#define Sw_Rust_Mid_Posi -775000 //-775000-75*11014 + +//double Sw_Rust_Mid_Posi=-775000;//需检测修改 +#define DF_MSP_TT_Motor_StartID 2 + +void SwingMotorSetCheckTargetPositon(); + +void TT_Analytic_Fun(int32_t ID_A_T_A, char *buffer); + +extern int SwingMotorID; +extern int LeftMotorID; +extern int RightMotorID; +extern TT_MotorParameters *TT_Motor[7]; + +extern void ActivateMotor(int32_t MotorID, FDCANHandler *ZQ_Motor_Controller, + int32_t WaitTime) ; + +extern void CANSendMessageSDO_ADD_To_SendList(int32_t MotorID, uint8_t Function, + uint16_t ControlWord, uint8_t subWord, int32_t ControlWordValue, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime); + +//位置速度模式 +extern void Postion_Velcocity_Run_SetParameter(int32_t MotorID, int32_t TargetPosition, + int32_t TargetSpeed, int32_t AccTime, int32_t DecTime, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime); +extern void Postion_Velcocity_Set_Position(int32_t MotorID, int32_t TargetPosition, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime) ; + +extern void Driver_ReadError(int32_t MotorID, FDCANHandler *ZQ_Motor_Controller, + int32_t WaitTime); +extern void SetMotorTargetPosition(int32_t MotorID, int32_t TargetPosition, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime) ; + +extern void Postion_Velcocity_Stop(int32_t MotorID, FDCANHandler *ZQ_Motor_Controller, + int32_t WaitTime) ; + +//extern void SetCurrentPositionZero(int MotorID, FDCANHandler *ZQ_Motor_Controller, +// int32_t WaitTime) ; + +extern void Motor_Controller_intialize(FDCANHandler *Handler); + +extern void Swing_Motor_Set_Target_Position() ; + +extern void Swing_Motor_Read_ReachedEnd() ; +extern void Set_Current_Positon_Zero(uint8_t MotorID, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime) ; + +extern void TT_Request_Position(uint32_t Motor_ID_1, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime) ; +extern void TT_Request_Velocity(uint32_t Motor_ID_1, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime) ; + + +extern void Position_Immediately_Setting(uint8_t MotorID, FDCANHandler *ZQ_Motor_Controller, + int32_t Deri_Position,int32_t Deri_Speed, int32_t WaitTime); // Home 设置当前位置为零点 + +extern void Position_Lag_Setting(uint8_t MotorID, FDCANHandler *ZQ_Motor_Controller, + int32_t Deri_Position,int32_t Deri_Speed, int32_t WaitTime) ; // Home 设置当前位置为零点 + +extern void TT_Request_Fault(uint32_t Motor_ID_1, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime) ; + +extern void TT_Request_Current(uint32_t Motor_ID_1, + FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime); + +extern void TT_Analytic_Fun(int32_t ID_A_T_A, char *buffer); + + +extern void TT_Analytic_Fun(int32_t ID_A_T_A, char *buffer); + +extern void SpeedModeSetup(int32_t MotorID,FDCANHandler *ZQ_Motor_Controller,int32_t WaitTime,int32_t Acc, int32_t Dec, int32_t TargetVelocity); //设定速度模式,并更改相关速度 + +extern void TT_Analytic_Fun(int32_t ID_A_T_A, char *buffer); +extern void TT_SpeedMode_Set_TargetSpeed(uint32_t MotorID,FDCANHandler *ZQ_Motor_Controller,int32_t WaitTime,int32_t TargetSpeed); + + +extern void Enable_NMT(int32_t MotorID, FDCANHandler *ZQ_Motor_Controller, int32_t Node_Number, int32_t WaitTime); +extern void Configure_Asynchronous_Mode(int32_t MotorID, FDCANHandler *ZQ_Motor_Controller, int32_t Node_Number, int32_t WaitTime); +extern void Consumer_Or_microcontroller_Heartbeat(int32_t MotorID, FDCANHandler *ZQ_Motor_Controller, int32_t WaitTime); +#endif /* INC_MSP_MSP_TTMOTOR_ZQ_H_ */ diff --git a/Bingoo/include/base/msp_WH_LTE_7S0.h b/Bingoo/include/base/msp_WH_LTE_7S0.h new file mode 100644 index 0000000..3a1f1ed --- /dev/null +++ b/Bingoo/include/base/msp_WH_LTE_7S0.h @@ -0,0 +1,21 @@ +/* + * bsp_WH_LTE_7S0.h + * + * Created on: Sep 14, 2024 + * Author: akeguo + */ + +#ifndef INC_BSP_BSP_WH_LTE_7S0_H_ +#define INC_BSP_BSP_WH_LTE_7S0_H_ +#include "stdint.h" +extern struct UARTHandler *wh_LTE_7S0_Handler; +//void WH_LTE_7S0_intialize(struct UARTHandler *Handler); +void Send_WH_LTE_7S0_Data(uint8_t* data,int length); + +void WH_LTE_7S0_intialize(struct UARTHandler *Handler); +void decode_received_data_from_computer(uint8_t *buffer, uint16_t length); +void decode_command_from_wh_LTE_7S0(uint8_t *buffer, uint16_t length); +void UpdateGV(); + +extern char NeedToFeedBackToComputer; +#endif /* INC_BSP_BSP_WH_LTE_7S0_H_ */ diff --git a/Bingoo/include/base/msp_ZQ_MotorParameters.pb.h b/Bingoo/include/base/msp_ZQ_MotorParameters.pb.h new file mode 100644 index 0000000..83f036a --- /dev/null +++ b/Bingoo/include/base/msp_ZQ_MotorParameters.pb.h @@ -0,0 +1,129 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_MSP_ZQ_MOTORPARAMETERS_PB_H_INCLUDED +#define PB_MSP_ZQ_MOTORPARAMETERS_PB_H_INCLUDED +#include "pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +typedef struct _TT_MotorParameters { + int32_t MotorID; + int32_t Real_Current; + int32_t Target_Current; + int32_t Real_Velcity; + int32_t Target_Velcity; + int32_t Target_Position; + int32_t Act_Suc; + int32_t Cont_Posi_Suc; + int32_t Acc_Suc; + int32_t Dec_Suc; + int32_t Target_Posi_Suc; + int32_t Run_Speed_Suc; + int32_t Clear_Suc; + int32_t Real_Position; + int32_t Acc_Suc_Speed; + int32_t Dec_Suc_Speed; + int32_t Suc_Speed_S; + int32_t TT_Motor_Fault; + int32_t AccTime; + int32_t DecTime; + int32_t Number_Of_Rounds; + int32_t Start_Measuring_Position; + int32_t Last_Real_Position; + double Real_Disatnce; + int32_t Start_Measuring; /* 开始测距 */ + int32_t Position_immediately1_Lag2; /* 位置环模式,立即生效1,延后生效2 */ + int32_t Tar_Position_count; /* 位置环模式,期望位置 */ + int32_t Tar_Position_Velcity_RPM; /* 位置环模式,速度 */ +} TT_MotorParameters; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define TT_MotorParameters_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define TT_MotorParameters_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define TT_MotorParameters_MotorID_tag 1 +#define TT_MotorParameters_Real_Current_tag 4 +#define TT_MotorParameters_Target_Current_tag 5 +#define TT_MotorParameters_Real_Velcity_tag 6 +#define TT_MotorParameters_Target_Velcity_tag 7 +#define TT_MotorParameters_Target_Position_tag 8 +#define TT_MotorParameters_Act_Suc_tag 25 +#define TT_MotorParameters_Cont_Posi_Suc_tag 26 +#define TT_MotorParameters_Acc_Suc_tag 27 +#define TT_MotorParameters_Dec_Suc_tag 28 +#define TT_MotorParameters_Target_Posi_Suc_tag 29 +#define TT_MotorParameters_Run_Speed_Suc_tag 30 +#define TT_MotorParameters_Clear_Suc_tag 31 +#define TT_MotorParameters_Real_Position_tag 32 +#define TT_MotorParameters_Acc_Suc_Speed_tag 33 +#define TT_MotorParameters_Dec_Suc_Speed_tag 34 +#define TT_MotorParameters_Suc_Speed_S_tag 35 +#define TT_MotorParameters_TT_Motor_Fault_tag 36 +#define TT_MotorParameters_AccTime_tag 37 +#define TT_MotorParameters_DecTime_tag 38 +#define TT_MotorParameters_Number_Of_Rounds_tag 39 +#define TT_MotorParameters_Start_Measuring_Position_tag 40 +#define TT_MotorParameters_Last_Real_Position_tag 43 +#define TT_MotorParameters_Real_Disatnce_tag 44 +#define TT_MotorParameters_Start_Measuring_tag 45 +#define TT_MotorParameters_Position_immediately1_Lag2_tag 46 +#define TT_MotorParameters_Tar_Position_count_tag 47 +#define TT_MotorParameters_Tar_Position_Velcity_RPM_tag 49 + +/* Struct field encoding specification for nanopb */ +#define TT_MotorParameters_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, MotorID, 1) \ +X(a, STATIC, SINGULAR, INT32, Real_Current, 4) \ +X(a, STATIC, SINGULAR, INT32, Target_Current, 5) \ +X(a, STATIC, SINGULAR, INT32, Real_Velcity, 6) \ +X(a, STATIC, SINGULAR, INT32, Target_Velcity, 7) \ +X(a, STATIC, SINGULAR, INT32, Target_Position, 8) \ +X(a, STATIC, SINGULAR, INT32, Act_Suc, 25) \ +X(a, STATIC, SINGULAR, INT32, Cont_Posi_Suc, 26) \ +X(a, STATIC, SINGULAR, INT32, Acc_Suc, 27) \ +X(a, STATIC, SINGULAR, INT32, Dec_Suc, 28) \ +X(a, STATIC, SINGULAR, INT32, Target_Posi_Suc, 29) \ +X(a, STATIC, SINGULAR, INT32, Run_Speed_Suc, 30) \ +X(a, STATIC, SINGULAR, INT32, Clear_Suc, 31) \ +X(a, STATIC, SINGULAR, INT32, Real_Position, 32) \ +X(a, STATIC, SINGULAR, INT32, Acc_Suc_Speed, 33) \ +X(a, STATIC, SINGULAR, INT32, Dec_Suc_Speed, 34) \ +X(a, STATIC, SINGULAR, INT32, Suc_Speed_S, 35) \ +X(a, STATIC, SINGULAR, INT32, TT_Motor_Fault, 36) \ +X(a, STATIC, SINGULAR, INT32, AccTime, 37) \ +X(a, STATIC, SINGULAR, INT32, DecTime, 38) \ +X(a, STATIC, SINGULAR, INT32, Number_Of_Rounds, 39) \ +X(a, STATIC, SINGULAR, INT32, Start_Measuring_Position, 40) \ +X(a, STATIC, SINGULAR, INT32, Last_Real_Position, 43) \ +X(a, STATIC, SINGULAR, DOUBLE, Real_Disatnce, 44) \ +X(a, STATIC, SINGULAR, INT32, Start_Measuring, 45) \ +X(a, STATIC, SINGULAR, INT32, Position_immediately1_Lag2, 46) \ +X(a, STATIC, SINGULAR, INT32, Tar_Position_count, 47) \ +X(a, STATIC, SINGULAR, INT32, Tar_Position_Velcity_RPM, 49) +#define TT_MotorParameters_CALLBACK NULL +#define TT_MotorParameters_DEFAULT NULL + +extern const pb_msgdesc_t TT_MotorParameters_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define TT_MotorParameters_fields &TT_MotorParameters_msg + +/* Maximum encoded size of messages (where known) */ +#define MSP_ZQ_MOTORPARAMETERS_PB_H_MAX_SIZE TT_MotorParameters_size +#define TT_MotorParameters_size 328 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/msp_ground_management.h b/Bingoo/include/base/msp_ground_management.h new file mode 100644 index 0000000..0cf5816 --- /dev/null +++ b/Bingoo/include/base/msp_ground_management.h @@ -0,0 +1,21 @@ +/* + * msp_ground_management.h + * + * Created on: 2025年11月25日 + * Author: akeguo + */ + +#ifndef BASE_INC_MSP_MSP_GROUND_MANAGEMENT_H_ +#define BASE_INC_MSP_MSP_GROUND_MANAGEMENT_H_ +#include "bsp_MB_host.h" +#include "bsp_Error.pb.h" +#include "bsp_ground_management.pb.h" +#include "bsp_Error_Detect.h" +extern void ground_management_intialize(struct UARTHandler *Handler); +extern void ground_management_intialize_with_slaveid(struct UARTHandler *Handler, int slave_id); +extern void ground_management_inquiry(); + + +extern ground_management_struct *ground_management_value; + +#endif /* BASE_INC_MSP_MSP_GROUND_MANAGEMENT_H_ */ diff --git a/Bingoo/include/base/msp_strain_gauge.h b/Bingoo/include/base/msp_strain_gauge.h new file mode 100644 index 0000000..ba47fe3 --- /dev/null +++ b/Bingoo/include/base/msp_strain_gauge.h @@ -0,0 +1,22 @@ +/* + * msp_strain_gauge.h + * + * Created on: 2025年11月25日 + * Author: akeguo + */ +//应变片采集模块 +#ifndef BASE_INC_MSP_MSP_STRAIN_GAUGE_H_ +#define BASE_INC_MSP_MSP_STRAIN_GAUGE_H_ + +#include "bsp_MB_host.h" +#include "bsp_Error.pb.h" +#include "bsp_strain_gauge.pb.h" +#include "bsp_Error_Detect.h" +#define OneLineWaitTime 50 //SendList 等待时间 +extern void strain_gauge_intialize(struct UARTHandler *Handler); +extern void strain_gauge_intialize_with_slaveid(struct UARTHandler *Handler, int slave_id); +extern void brake_discharge_inquiry(); +extern Strain_Gauge_Struct *strainGaugeValue; + + +#endif /* BASE_INC_MSP_MSP_STRAIN_GAUGE_H_ */ diff --git a/Bingoo/include/base/paint_gun_action.h b/Bingoo/include/base/paint_gun_action.h new file mode 100644 index 0000000..ca4348a --- /dev/null +++ b/Bingoo/include/base/paint_gun_action.h @@ -0,0 +1,23 @@ +/* + * paint_gun_action.h + * + * Created on: 2025年8月7日 + * Author: xsq + */ + +#ifndef FSM_INC_PAINT_GUN_ACTION_H_ +#define FSM_INC_PAINT_GUN_ACTION_H_ + +#include "fsm_state.h" +extern transition_t current_paintgun_state; +extern transition_state_t paintgun_on_state; +extern transition_state_t paintgun_off_state; +extern void PaintGun_ON_Do(); +extern void PaintGun_OFF_Do(); +extern void PaintGun_ON_Enter(); +extern void PaintGun_ON_Exit(); +extern void PaintGun_OFF_Enter(); +extern void PaintGun_Contronl(); +extern void PaintGun_Contronl_Press(); +extern char Paint_Gun_ButtonReset_Flag; //喷枪开启 1yes +#endif /* FSM_INC_PAINT_GUN_ACTION_H_ */ diff --git a/Bingoo/include/base/pb.h b/Bingoo/include/base/pb.h new file mode 100644 index 0000000..ef3d83e --- /dev/null +++ b/Bingoo/include/base/pb.h @@ -0,0 +1,917 @@ +/* Common parts of the nanopb library. Most of these are quite low-level + * stuff. For the high-level interface, see pb_encode.h and pb_decode.h. + */ + +#ifndef PB_H_INCLUDED +#define PB_H_INCLUDED + +/***************************************************************** + * Nanopb compilation time options. You can change these here by * + * uncommenting the lines, or on the compiler command line. * + *****************************************************************/ + +/* Enable support for dynamically allocated fields */ +/* #define PB_ENABLE_MALLOC 1 */ + +/* Define this if your CPU / compiler combination does not support + * unaligned memory access to packed structures. Note that packed + * structures are only used when requested in .proto options. */ +/* #define PB_NO_PACKED_STRUCTS 1 */ + +/* Increase the number of required fields that are tracked. + * A compiler warning will tell if you need this. */ +/* #define PB_MAX_REQUIRED_FIELDS 256 */ + +/* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */ +/* #define PB_FIELD_32BIT 1 */ + +/* Disable support for error messages in order to save some code space. */ +/* #define PB_NO_ERRMSG 1 */ + +/* Disable support for custom streams (support only memory buffers). */ +/* #define PB_BUFFER_ONLY 1 */ + +/* Disable support for 64-bit datatypes, for compilers without int64_t + or to save some code space. */ +/* #define PB_WITHOUT_64BIT 1 */ + +/* Don't encode scalar arrays as packed. This is only to be used when + * the decoder on the receiving side cannot process packed scalar arrays. + * Such example is older protobuf.js. */ +/* #define PB_ENCODE_ARRAYS_UNPACKED 1 */ + +/* Enable conversion of doubles to floats for platforms that do not + * support 64-bit doubles. Most commonly AVR. */ +/* #define PB_CONVERT_DOUBLE_FLOAT 1 */ + +/* Check whether incoming strings are valid UTF-8 sequences. Slows down + * the string processing slightly and slightly increases code size. */ +/* #define PB_VALIDATE_UTF8 1 */ + +/* This can be defined if the platform is little-endian and has 8-bit bytes. + * Normally it is automatically detected based on __BYTE_ORDER__ macro. */ +/* #define PB_LITTLE_ENDIAN_8BIT 1 */ + +/* Configure static assert mechanism. Instead of changing these, set your + * compiler to C11 standard mode if possible. */ +/* #define PB_C99_STATIC_ASSERT 1 */ +/* #define PB_NO_STATIC_ASSERT 1 */ + +/****************************************************************** + * You usually don't need to change anything below this line. * + * Feel free to look around and use the defined macros, though. * + ******************************************************************/ + + +/* Version of the nanopb library. Just in case you want to check it in + * your own program. */ +#define NANOPB_VERSION "nanopb-0.4.8-dev" + +/* Include all the system headers needed by nanopb. You will need the + * definitions of the following: + * - strlen, memcpy, memset functions + * - [u]int_least8_t, uint_fast8_t, [u]int_least16_t, [u]int32_t, [u]int64_t + * - size_t + * - bool + * + * If you don't have the standard header files, you can instead provide + * a custom header that defines or includes all this. In that case, + * define PB_SYSTEM_HEADER to the path of this file. + */ +#ifdef PB_SYSTEM_HEADER +#include PB_SYSTEM_HEADER +#else +#include +#include +#include +#include +#include + +#ifdef PB_ENABLE_MALLOC +#include +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Macro for defining packed structures (compiler dependent). + * This just reduces memory requirements, but is not required. + */ +#if defined(PB_NO_PACKED_STRUCTS) + /* Disable struct packing */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed +#elif defined(__GNUC__) || defined(__clang__) + /* For GCC and clang */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed __attribute__((packed)) +#elif defined(__ICCARM__) || defined(__CC_ARM) + /* For IAR ARM and Keil MDK-ARM compilers */ +# define PB_PACKED_STRUCT_START _Pragma("pack(push, 1)") +# define PB_PACKED_STRUCT_END _Pragma("pack(pop)") +# define pb_packed +#elif defined(_MSC_VER) && (_MSC_VER >= 1500) + /* For Microsoft Visual C++ */ +# define PB_PACKED_STRUCT_START __pragma(pack(push, 1)) +# define PB_PACKED_STRUCT_END __pragma(pack(pop)) +# define pb_packed +#else + /* Unknown compiler */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed +#endif + +/* Detect endianness */ +#ifndef PB_LITTLE_ENDIAN_8BIT +#if ((defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ + defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || \ + defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || \ + defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM)) \ + && CHAR_BIT == 8 +#define PB_LITTLE_ENDIAN_8BIT 1 +#endif +#endif + +/* Handly macro for suppressing unreferenced-parameter compiler warnings. */ +#ifndef PB_UNUSED +#define PB_UNUSED(x) (void)(x) +#endif + +/* Harvard-architecture processors may need special attributes for storing + * field information in program memory. */ +#ifndef PB_PROGMEM +#ifdef __AVR__ +#include +#define PB_PROGMEM PROGMEM +#define PB_PROGMEM_READU32(x) pgm_read_dword(&x) +#else +#define PB_PROGMEM +#define PB_PROGMEM_READU32(x) (x) +#endif +#endif + +/* Compile-time assertion, used for checking compatible compilation options. + * If this does not work properly on your compiler, use + * #define PB_NO_STATIC_ASSERT to disable it. + * + * But before doing that, check carefully the error message / place where it + * comes from to see if the error has a real cause. Unfortunately the error + * message is not always very clear to read, but you can see the reason better + * in the place where the PB_STATIC_ASSERT macro was called. + */ +#ifndef PB_NO_STATIC_ASSERT +# ifndef PB_STATIC_ASSERT +# if defined(__ICCARM__) + /* IAR has static_assert keyword but no _Static_assert */ +# define PB_STATIC_ASSERT(COND,MSG) static_assert(COND,#MSG); +# elif defined(_MSC_VER) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112) + /* MSVC in C89 mode supports static_assert() keyword anyway */ +# define PB_STATIC_ASSERT(COND,MSG) static_assert(COND,#MSG); +# elif defined(PB_C99_STATIC_ASSERT) + /* Classic negative-size-array static assert mechanism */ +# define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1]; +# define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) +# define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##_##LINE##_##COUNTER +# elif defined(__cplusplus) + /* C++11 standard static_assert mechanism */ +# define PB_STATIC_ASSERT(COND,MSG) static_assert(COND,#MSG); +# else + /* C11 standard _Static_assert mechanism */ +# define PB_STATIC_ASSERT(COND,MSG) _Static_assert(COND,#MSG); +# endif +# endif +#else + /* Static asserts disabled by PB_NO_STATIC_ASSERT */ +# define PB_STATIC_ASSERT(COND,MSG) +#endif + +/* Test that PB_STATIC_ASSERT works + * If you get errors here, you may need to do one of these: + * - Enable C11 standard support in your compiler + * - Define PB_C99_STATIC_ASSERT to enable C99 standard support + * - Define PB_NO_STATIC_ASSERT to disable static asserts altogether + */ +PB_STATIC_ASSERT(1, STATIC_ASSERT_IS_NOT_WORKING) + +/* Number of required fields to keep track of. */ +#ifndef PB_MAX_REQUIRED_FIELDS +#define PB_MAX_REQUIRED_FIELDS 64 +#endif + +#if PB_MAX_REQUIRED_FIELDS < 64 +#error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64). +#endif + +#ifdef PB_WITHOUT_64BIT +#ifdef PB_CONVERT_DOUBLE_FLOAT +/* Cannot use doubles without 64-bit types */ +#undef PB_CONVERT_DOUBLE_FLOAT +#endif +#endif + +/* List of possible field types. These are used in the autogenerated code. + * Least-significant 4 bits tell the scalar type + * Most-significant 4 bits specify repeated/required/packed etc. + */ + +typedef uint_least8_t pb_type_t; + +/**** Field data types ****/ + +/* Numeric types */ +#define PB_LTYPE_BOOL 0x00U /* bool */ +#define PB_LTYPE_VARINT 0x01U /* int32, int64, enum, bool */ +#define PB_LTYPE_UVARINT 0x02U /* uint32, uint64 */ +#define PB_LTYPE_SVARINT 0x03U /* sint32, sint64 */ +#define PB_LTYPE_FIXED32 0x04U /* fixed32, sfixed32, float */ +#define PB_LTYPE_FIXED64 0x05U /* fixed64, sfixed64, double */ + +/* Marker for last packable field type. */ +#define PB_LTYPE_LAST_PACKABLE 0x05U + +/* Byte array with pre-allocated buffer. + * data_size is the length of the allocated PB_BYTES_ARRAY structure. */ +#define PB_LTYPE_BYTES 0x06U + +/* String with pre-allocated buffer. + * data_size is the maximum length. */ +#define PB_LTYPE_STRING 0x07U + +/* Submessage + * submsg_fields is pointer to field descriptions */ +#define PB_LTYPE_SUBMESSAGE 0x08U + +/* Submessage with pre-decoding callback + * The pre-decoding callback is stored as pb_callback_t right before pSize. + * submsg_fields is pointer to field descriptions */ +#define PB_LTYPE_SUBMSG_W_CB 0x09U + +/* Extension pseudo-field + * The field contains a pointer to pb_extension_t */ +#define PB_LTYPE_EXTENSION 0x0AU + +/* Byte array with inline, pre-allocated byffer. + * data_size is the length of the inline, allocated buffer. + * This differs from PB_LTYPE_BYTES by defining the element as + * pb_byte_t[data_size] rather than pb_bytes_array_t. */ +#define PB_LTYPE_FIXED_LENGTH_BYTES 0x0BU + +/* Number of declared LTYPES */ +#define PB_LTYPES_COUNT 0x0CU +#define PB_LTYPE_MASK 0x0FU + +/**** Field repetition rules ****/ + +#define PB_HTYPE_REQUIRED 0x00U +#define PB_HTYPE_OPTIONAL 0x10U +#define PB_HTYPE_SINGULAR 0x10U +#define PB_HTYPE_REPEATED 0x20U +#define PB_HTYPE_FIXARRAY 0x20U +#define PB_HTYPE_ONEOF 0x30U +#define PB_HTYPE_MASK 0x30U + +/**** Field allocation types ****/ + +#define PB_ATYPE_STATIC 0x00U +#define PB_ATYPE_POINTER 0x80U +#define PB_ATYPE_CALLBACK 0x40U +#define PB_ATYPE_MASK 0xC0U + +#define PB_ATYPE(x) ((x) & PB_ATYPE_MASK) +#define PB_HTYPE(x) ((x) & PB_HTYPE_MASK) +#define PB_LTYPE(x) ((x) & PB_LTYPE_MASK) +#define PB_LTYPE_IS_SUBMSG(x) (PB_LTYPE(x) == PB_LTYPE_SUBMESSAGE || \ + PB_LTYPE(x) == PB_LTYPE_SUBMSG_W_CB) + +/* Data type used for storing sizes of struct fields + * and array counts. + */ +#if defined(PB_FIELD_32BIT) + typedef uint32_t pb_size_t; + typedef int32_t pb_ssize_t; +#else + typedef uint_least16_t pb_size_t; + typedef int_least16_t pb_ssize_t; +#endif +#define PB_SIZE_MAX ((pb_size_t)-1) + +/* Data type for storing encoded data and other byte streams. + * This typedef exists to support platforms where uint8_t does not exist. + * You can regard it as equivalent on uint8_t on other platforms. + */ +typedef uint_least8_t pb_byte_t; + +/* Forward declaration of struct types */ +typedef struct pb_istream_s pb_istream_t; +typedef struct pb_ostream_s pb_ostream_t; +typedef struct pb_field_iter_s pb_field_iter_t; + +/* This structure is used in auto-generated constants + * to specify struct fields. + */ +typedef struct pb_msgdesc_s pb_msgdesc_t; +struct pb_msgdesc_s { + const uint32_t *field_info; + const pb_msgdesc_t * const * submsg_info; + const pb_byte_t *default_value; + + bool (*field_callback)(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field); + + pb_size_t field_count; + pb_size_t required_field_count; + pb_size_t largest_tag; +}; + +/* Iterator for message descriptor */ +struct pb_field_iter_s { + const pb_msgdesc_t *descriptor; /* Pointer to message descriptor constant */ + void *message; /* Pointer to start of the structure */ + + pb_size_t index; /* Index of the field */ + pb_size_t field_info_index; /* Index to descriptor->field_info array */ + pb_size_t required_field_index; /* Index that counts only the required fields */ + pb_size_t submessage_index; /* Index that counts only submessages */ + + pb_size_t tag; /* Tag of current field */ + pb_size_t data_size; /* sizeof() of a single item */ + pb_size_t array_size; /* Number of array entries */ + pb_type_t type; /* Type of current field */ + + void *pField; /* Pointer to current field in struct */ + void *pData; /* Pointer to current data contents. Different than pField for arrays and pointers. */ + void *pSize; /* Pointer to count/has field */ + + const pb_msgdesc_t *submsg_desc; /* For submessage fields, pointer to field descriptor for the submessage. */ +}; + +/* For compatibility with legacy code */ +typedef pb_field_iter_t pb_field_t; + +/* Make sure that the standard integer types are of the expected sizes. + * Otherwise fixed32/fixed64 fields can break. + * + * If you get errors here, it probably means that your stdint.h is not + * correct for your platform. + */ +#ifndef PB_WITHOUT_64BIT +PB_STATIC_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t), INT64_T_WRONG_SIZE) +PB_STATIC_ASSERT(sizeof(uint64_t) == 2 * sizeof(uint32_t), UINT64_T_WRONG_SIZE) +#endif + +/* This structure is used for 'bytes' arrays. + * It has the number of bytes in the beginning, and after that an array. + * Note that actual structs used will have a different length of bytes array. + */ +#define PB_BYTES_ARRAY_T(n) struct { pb_size_t size; pb_byte_t bytes[n]; } +#define PB_BYTES_ARRAY_T_ALLOCSIZE(n) ((size_t)n + offsetof(pb_bytes_array_t, bytes)) + +struct pb_bytes_array_s { + pb_size_t size; + pb_byte_t bytes[1]; +}; +typedef struct pb_bytes_array_s pb_bytes_array_t; + +/* This structure is used for giving the callback function. + * It is stored in the message structure and filled in by the method that + * calls pb_decode. + * + * The decoding callback will be given a limited-length stream + * If the wire type was string, the length is the length of the string. + * If the wire type was a varint/fixed32/fixed64, the length is the length + * of the actual value. + * The function may be called multiple times (especially for repeated types, + * but also otherwise if the message happens to contain the field multiple + * times.) + * + * The encoding callback will receive the actual output stream. + * It should write all the data in one call, including the field tag and + * wire type. It can write multiple fields. + * + * The callback can be null if you want to skip a field. + */ +typedef struct pb_callback_s pb_callback_t; +struct pb_callback_s { + /* Callback functions receive a pointer to the arg field. + * You can access the value of the field as *arg, and modify it if needed. + */ + union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg); + } funcs; + + /* Free arg for use by callback */ + void *arg; +}; + +extern bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field); + +/* Wire types. Library user needs these only in encoder callbacks. */ +typedef enum { + PB_WT_VARINT = 0, + PB_WT_64BIT = 1, + PB_WT_STRING = 2, + PB_WT_32BIT = 5, + PB_WT_PACKED = 255 /* PB_WT_PACKED is internal marker for packed arrays. */ +} pb_wire_type_t; + +/* Structure for defining the handling of unknown/extension fields. + * Usually the pb_extension_type_t structure is automatically generated, + * while the pb_extension_t structure is created by the user. However, + * if you want to catch all unknown fields, you can also create a custom + * pb_extension_type_t with your own callback. + */ +typedef struct pb_extension_type_s pb_extension_type_t; +typedef struct pb_extension_s pb_extension_t; +struct pb_extension_type_s { + /* Called for each unknown field in the message. + * If you handle the field, read off all of its data and return true. + * If you do not handle the field, do not read anything and return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*decode)(pb_istream_t *stream, pb_extension_t *extension, + uint32_t tag, pb_wire_type_t wire_type); + + /* Called once after all regular fields have been encoded. + * If you have something to write, do so and return true. + * If you do not have anything to write, just return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension); + + /* Free field for use by the callback. */ + const void *arg; +}; + +struct pb_extension_s { + /* Type describing the extension field. Usually you'll initialize + * this to a pointer to the automatically generated structure. */ + const pb_extension_type_t *type; + + /* Destination for the decoded data. This must match the datatype + * of the extension field. */ + void *dest; + + /* Pointer to the next extension handler, or NULL. + * If this extension does not match a field, the next handler is + * automatically called. */ + pb_extension_t *next; + + /* The decoder sets this to true if the extension was found. + * Ignored for encoding. */ + bool found; +}; + +#define pb_extension_init_zero {NULL,NULL,NULL,false} + +/* Memory allocation functions to use. You can define pb_realloc and + * pb_free to custom functions if you want. */ +#ifdef PB_ENABLE_MALLOC +# ifndef pb_realloc +# define pb_realloc(ptr, size) realloc(ptr, size) +# endif +# ifndef pb_free +# define pb_free(ptr) free(ptr) +# endif +#endif + +/* This is used to inform about need to regenerate .pb.h/.pb.c files. */ +#define PB_PROTO_HEADER_VERSION 40 + +/* These macros are used to declare pb_field_t's in the constant array. */ +/* Size of a structure member, in bytes. */ +#define pb_membersize(st, m) (sizeof ((st*)0)->m) +/* Number of entries in an array. */ +#define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0])) +/* Delta from start of one member to the start of another member. */ +#define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2)) + +/* Force expansion of macro value */ +#define PB_EXPAND(x) x + +/* Binding of a message field set into a specific structure */ +#define PB_BIND(msgname, structname, width) \ + const uint32_t structname ## _field_info[] PB_PROGMEM = \ + { \ + msgname ## _FIELDLIST(PB_GEN_FIELD_INFO_ ## width, structname) \ + 0 \ + }; \ + const pb_msgdesc_t* const structname ## _submsg_info[] = \ + { \ + msgname ## _FIELDLIST(PB_GEN_SUBMSG_INFO, structname) \ + NULL \ + }; \ + const pb_msgdesc_t structname ## _msg = \ + { \ + structname ## _field_info, \ + structname ## _submsg_info, \ + msgname ## _DEFAULT, \ + msgname ## _CALLBACK, \ + 0 msgname ## _FIELDLIST(PB_GEN_FIELD_COUNT, structname), \ + 0 msgname ## _FIELDLIST(PB_GEN_REQ_FIELD_COUNT, structname), \ + 0 msgname ## _FIELDLIST(PB_GEN_LARGEST_TAG, structname), \ + }; \ + msgname ## _FIELDLIST(PB_GEN_FIELD_INFO_ASSERT_ ## width, structname) + +#define PB_GEN_FIELD_COUNT(structname, atype, htype, ltype, fieldname, tag) +1 +#define PB_GEN_REQ_FIELD_COUNT(structname, atype, htype, ltype, fieldname, tag) \ + + (PB_HTYPE_ ## htype == PB_HTYPE_REQUIRED) +#define PB_GEN_LARGEST_TAG(structname, atype, htype, ltype, fieldname, tag) \ + * 0 + tag + +/* X-macro for generating the entries in struct_field_info[] array. */ +#define PB_GEN_FIELD_INFO_1(structname, atype, htype, ltype, fieldname, tag) \ + PB_FIELDINFO_1(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \ + PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname)) + +#define PB_GEN_FIELD_INFO_2(structname, atype, htype, ltype, fieldname, tag) \ + PB_FIELDINFO_2(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \ + PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname)) + +#define PB_GEN_FIELD_INFO_4(structname, atype, htype, ltype, fieldname, tag) \ + PB_FIELDINFO_4(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \ + PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname)) + +#define PB_GEN_FIELD_INFO_8(structname, atype, htype, ltype, fieldname, tag) \ + PB_FIELDINFO_8(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \ + PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname)) + +#define PB_GEN_FIELD_INFO_AUTO(structname, atype, htype, ltype, fieldname, tag) \ + PB_FIELDINFO_AUTO2(PB_FIELDINFO_WIDTH_AUTO(_PB_ATYPE_ ## atype, _PB_HTYPE_ ## htype, _PB_LTYPE_ ## ltype), \ + tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \ + PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname)) + +#define PB_FIELDINFO_AUTO2(width, tag, type, data_offset, data_size, size_offset, array_size) \ + PB_FIELDINFO_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size) + +#define PB_FIELDINFO_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size) \ + PB_FIELDINFO_ ## width(tag, type, data_offset, data_size, size_offset, array_size) + +/* X-macro for generating asserts that entries fit in struct_field_info[] array. + * The structure of macros here must match the structure above in PB_GEN_FIELD_INFO_x(), + * but it is not easily reused because of how macro substitutions work. */ +#define PB_GEN_FIELD_INFO_ASSERT_1(structname, atype, htype, ltype, fieldname, tag) \ + PB_FIELDINFO_ASSERT_1(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \ + PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname)) + +#define PB_GEN_FIELD_INFO_ASSERT_2(structname, atype, htype, ltype, fieldname, tag) \ + PB_FIELDINFO_ASSERT_2(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \ + PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname)) + +#define PB_GEN_FIELD_INFO_ASSERT_4(structname, atype, htype, ltype, fieldname, tag) \ + PB_FIELDINFO_ASSERT_4(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \ + PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname)) + +#define PB_GEN_FIELD_INFO_ASSERT_8(structname, atype, htype, ltype, fieldname, tag) \ + PB_FIELDINFO_ASSERT_8(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \ + PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname)) + +#define PB_GEN_FIELD_INFO_ASSERT_AUTO(structname, atype, htype, ltype, fieldname, tag) \ + PB_FIELDINFO_ASSERT_AUTO2(PB_FIELDINFO_WIDTH_AUTO(_PB_ATYPE_ ## atype, _PB_HTYPE_ ## htype, _PB_LTYPE_ ## ltype), \ + tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \ + PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \ + PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname)) + +#define PB_FIELDINFO_ASSERT_AUTO2(width, tag, type, data_offset, data_size, size_offset, array_size) \ + PB_FIELDINFO_ASSERT_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size) + +#define PB_FIELDINFO_ASSERT_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size) \ + PB_FIELDINFO_ASSERT_ ## width(tag, type, data_offset, data_size, size_offset, array_size) + +#define PB_DATA_OFFSET_STATIC(htype, structname, fieldname) PB_DO ## htype(structname, fieldname) +#define PB_DATA_OFFSET_POINTER(htype, structname, fieldname) PB_DO ## htype(structname, fieldname) +#define PB_DATA_OFFSET_CALLBACK(htype, structname, fieldname) PB_DO ## htype(structname, fieldname) +#define PB_DO_PB_HTYPE_REQUIRED(structname, fieldname) offsetof(structname, fieldname) +#define PB_DO_PB_HTYPE_SINGULAR(structname, fieldname) offsetof(structname, fieldname) +#define PB_DO_PB_HTYPE_ONEOF(structname, fieldname) offsetof(structname, PB_ONEOF_NAME(FULL, fieldname)) +#define PB_DO_PB_HTYPE_OPTIONAL(structname, fieldname) offsetof(structname, fieldname) +#define PB_DO_PB_HTYPE_REPEATED(structname, fieldname) offsetof(structname, fieldname) +#define PB_DO_PB_HTYPE_FIXARRAY(structname, fieldname) offsetof(structname, fieldname) + +#define PB_SIZE_OFFSET_STATIC(htype, structname, fieldname) PB_SO ## htype(structname, fieldname) +#define PB_SIZE_OFFSET_POINTER(htype, structname, fieldname) PB_SO_PTR ## htype(structname, fieldname) +#define PB_SIZE_OFFSET_CALLBACK(htype, structname, fieldname) PB_SO_CB ## htype(structname, fieldname) +#define PB_SO_PB_HTYPE_REQUIRED(structname, fieldname) 0 +#define PB_SO_PB_HTYPE_SINGULAR(structname, fieldname) 0 +#define PB_SO_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF2(structname, PB_ONEOF_NAME(FULL, fieldname), PB_ONEOF_NAME(UNION, fieldname)) +#define PB_SO_PB_HTYPE_ONEOF2(structname, fullname, unionname) PB_SO_PB_HTYPE_ONEOF3(structname, fullname, unionname) +#define PB_SO_PB_HTYPE_ONEOF3(structname, fullname, unionname) pb_delta(structname, fullname, which_ ## unionname) +#define PB_SO_PB_HTYPE_OPTIONAL(structname, fieldname) pb_delta(structname, fieldname, has_ ## fieldname) +#define PB_SO_PB_HTYPE_REPEATED(structname, fieldname) pb_delta(structname, fieldname, fieldname ## _count) +#define PB_SO_PB_HTYPE_FIXARRAY(structname, fieldname) 0 +#define PB_SO_PTR_PB_HTYPE_REQUIRED(structname, fieldname) 0 +#define PB_SO_PTR_PB_HTYPE_SINGULAR(structname, fieldname) 0 +#define PB_SO_PTR_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF(structname, fieldname) +#define PB_SO_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) 0 +#define PB_SO_PTR_PB_HTYPE_REPEATED(structname, fieldname) PB_SO_PB_HTYPE_REPEATED(structname, fieldname) +#define PB_SO_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) 0 +#define PB_SO_CB_PB_HTYPE_REQUIRED(structname, fieldname) 0 +#define PB_SO_CB_PB_HTYPE_SINGULAR(structname, fieldname) 0 +#define PB_SO_CB_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF(structname, fieldname) +#define PB_SO_CB_PB_HTYPE_OPTIONAL(structname, fieldname) 0 +#define PB_SO_CB_PB_HTYPE_REPEATED(structname, fieldname) 0 +#define PB_SO_CB_PB_HTYPE_FIXARRAY(structname, fieldname) 0 + +#define PB_ARRAY_SIZE_STATIC(htype, structname, fieldname) PB_AS ## htype(structname, fieldname) +#define PB_ARRAY_SIZE_POINTER(htype, structname, fieldname) PB_AS_PTR ## htype(structname, fieldname) +#define PB_ARRAY_SIZE_CALLBACK(htype, structname, fieldname) 1 +#define PB_AS_PB_HTYPE_REQUIRED(structname, fieldname) 1 +#define PB_AS_PB_HTYPE_SINGULAR(structname, fieldname) 1 +#define PB_AS_PB_HTYPE_OPTIONAL(structname, fieldname) 1 +#define PB_AS_PB_HTYPE_ONEOF(structname, fieldname) 1 +#define PB_AS_PB_HTYPE_REPEATED(structname, fieldname) pb_arraysize(structname, fieldname) +#define PB_AS_PB_HTYPE_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname) +#define PB_AS_PTR_PB_HTYPE_REQUIRED(structname, fieldname) 1 +#define PB_AS_PTR_PB_HTYPE_SINGULAR(structname, fieldname) 1 +#define PB_AS_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) 1 +#define PB_AS_PTR_PB_HTYPE_ONEOF(structname, fieldname) 1 +#define PB_AS_PTR_PB_HTYPE_REPEATED(structname, fieldname) 1 +#define PB_AS_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname[0]) + +#define PB_DATA_SIZE_STATIC(htype, structname, fieldname) PB_DS ## htype(structname, fieldname) +#define PB_DATA_SIZE_POINTER(htype, structname, fieldname) PB_DS_PTR ## htype(structname, fieldname) +#define PB_DATA_SIZE_CALLBACK(htype, structname, fieldname) PB_DS_CB ## htype(structname, fieldname) +#define PB_DS_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname) +#define PB_DS_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname) +#define PB_DS_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname) +#define PB_DS_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)) +#define PB_DS_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0]) +#define PB_DS_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0]) +#define PB_DS_PTR_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname[0]) +#define PB_DS_PTR_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname[0]) +#define PB_DS_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname[0]) +#define PB_DS_PTR_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)[0]) +#define PB_DS_PTR_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0]) +#define PB_DS_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0][0]) +#define PB_DS_CB_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname) +#define PB_DS_CB_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname) +#define PB_DS_CB_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname) +#define PB_DS_CB_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)) +#define PB_DS_CB_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname) +#define PB_DS_CB_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname) + +#define PB_ONEOF_NAME(type, tuple) PB_EXPAND(PB_ONEOF_NAME_ ## type tuple) +#define PB_ONEOF_NAME_UNION(unionname,membername,fullname) unionname +#define PB_ONEOF_NAME_MEMBER(unionname,membername,fullname) membername +#define PB_ONEOF_NAME_FULL(unionname,membername,fullname) fullname + +#define PB_GEN_SUBMSG_INFO(structname, atype, htype, ltype, fieldname, tag) \ + PB_SUBMSG_INFO_ ## htype(_PB_LTYPE_ ## ltype, structname, fieldname) + +#define PB_SUBMSG_INFO_REQUIRED(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE) +#define PB_SUBMSG_INFO_SINGULAR(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE) +#define PB_SUBMSG_INFO_OPTIONAL(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE) +#define PB_SUBMSG_INFO_ONEOF(ltype, structname, fieldname) PB_SUBMSG_INFO_ONEOF2(ltype, structname, PB_ONEOF_NAME(UNION, fieldname), PB_ONEOF_NAME(MEMBER, fieldname)) +#define PB_SUBMSG_INFO_ONEOF2(ltype, structname, unionname, membername) PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername) +#define PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername) PB_SI ## ltype(structname ## _ ## unionname ## _ ## membername ## _MSGTYPE) +#define PB_SUBMSG_INFO_REPEATED(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE) +#define PB_SUBMSG_INFO_FIXARRAY(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE) +#define PB_SI_PB_LTYPE_BOOL(t) +#define PB_SI_PB_LTYPE_BYTES(t) +#define PB_SI_PB_LTYPE_DOUBLE(t) +#define PB_SI_PB_LTYPE_ENUM(t) +#define PB_SI_PB_LTYPE_UENUM(t) +#define PB_SI_PB_LTYPE_FIXED32(t) +#define PB_SI_PB_LTYPE_FIXED64(t) +#define PB_SI_PB_LTYPE_FLOAT(t) +#define PB_SI_PB_LTYPE_INT32(t) +#define PB_SI_PB_LTYPE_INT64(t) +#define PB_SI_PB_LTYPE_MESSAGE(t) PB_SUBMSG_DESCRIPTOR(t) +#define PB_SI_PB_LTYPE_MSG_W_CB(t) PB_SUBMSG_DESCRIPTOR(t) +#define PB_SI_PB_LTYPE_SFIXED32(t) +#define PB_SI_PB_LTYPE_SFIXED64(t) +#define PB_SI_PB_LTYPE_SINT32(t) +#define PB_SI_PB_LTYPE_SINT64(t) +#define PB_SI_PB_LTYPE_STRING(t) +#define PB_SI_PB_LTYPE_UINT32(t) +#define PB_SI_PB_LTYPE_UINT64(t) +#define PB_SI_PB_LTYPE_EXTENSION(t) +#define PB_SI_PB_LTYPE_FIXED_LENGTH_BYTES(t) +#define PB_SUBMSG_DESCRIPTOR(t) &(t ## _msg), + +/* The field descriptors use a variable width format, with width of either + * 1, 2, 4 or 8 of 32-bit words. The two lowest bytes of the first byte always + * encode the descriptor size, 6 lowest bits of field tag number, and 8 bits + * of the field type. + * + * Descriptor size is encoded as 0 = 1 word, 1 = 2 words, 2 = 4 words, 3 = 8 words. + * + * Formats, listed starting with the least significant bit of the first word. + * 1 word: [2-bit len] [6-bit tag] [8-bit type] [8-bit data_offset] [4-bit size_offset] [4-bit data_size] + * + * 2 words: [2-bit len] [6-bit tag] [8-bit type] [12-bit array_size] [4-bit size_offset] + * [16-bit data_offset] [12-bit data_size] [4-bit tag>>6] + * + * 4 words: [2-bit len] [6-bit tag] [8-bit type] [16-bit array_size] + * [8-bit size_offset] [24-bit tag>>6] + * [32-bit data_offset] + * [32-bit data_size] + * + * 8 words: [2-bit len] [6-bit tag] [8-bit type] [16-bit reserved] + * [8-bit size_offset] [24-bit tag>>6] + * [32-bit data_offset] + * [32-bit data_size] + * [32-bit array_size] + * [32-bit reserved] + * [32-bit reserved] + * [32-bit reserved] + */ + +#define PB_FIELDINFO_1(tag, type, data_offset, data_size, size_offset, array_size) \ + (0 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(data_offset) & 0xFF) << 16) | \ + (((uint32_t)(size_offset) & 0x0F) << 24) | (((uint32_t)(data_size) & 0x0F) << 28)), + +#define PB_FIELDINFO_2(tag, type, data_offset, data_size, size_offset, array_size) \ + (1 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(array_size) & 0xFFF) << 16) | (((uint32_t)(size_offset) & 0x0F) << 28)), \ + (((uint32_t)(data_offset) & 0xFFFF) | (((uint32_t)(data_size) & 0xFFF) << 16) | (((uint32_t)(tag) & 0x3c0) << 22)), + +#define PB_FIELDINFO_4(tag, type, data_offset, data_size, size_offset, array_size) \ + (2 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(array_size) & 0xFFFF) << 16)), \ + ((uint32_t)(int_least8_t)(size_offset) | (((uint32_t)(tag) << 2) & 0xFFFFFF00)), \ + (data_offset), (data_size), + +#define PB_FIELDINFO_8(tag, type, data_offset, data_size, size_offset, array_size) \ + (3 | (((tag) << 2) & 0xFF) | ((type) << 8)), \ + ((uint32_t)(int_least8_t)(size_offset) | (((uint32_t)(tag) << 2) & 0xFFFFFF00)), \ + (data_offset), (data_size), (array_size), 0, 0, 0, + +/* These assertions verify that the field information fits in the allocated space. + * The generator tries to automatically determine the correct width that can fit all + * data associated with a message. These asserts will fail only if there has been a + * problem in the automatic logic - this may be worth reporting as a bug. As a workaround, + * you can increase the descriptor width by defining PB_FIELDINFO_WIDTH or by setting + * descriptorsize option in .options file. + */ +#define PB_FITS(value,bits) ((uint32_t)(value) < ((uint32_t)1<2GB messages with nanopb anyway. + */ +#define PB_FIELDINFO_ASSERT_4(tag, type, data_offset, data_size, size_offset, array_size) \ + PB_STATIC_ASSERT(PB_FITS(tag,30) && PB_FITS(data_offset,31) && PB_FITS(size_offset,8) && PB_FITS(data_size,31) && PB_FITS(array_size,16), FIELDINFO_DOES_NOT_FIT_width4_field ## tag) + +#define PB_FIELDINFO_ASSERT_8(tag, type, data_offset, data_size, size_offset, array_size) \ + PB_STATIC_ASSERT(PB_FITS(tag,30) && PB_FITS(data_offset,31) && PB_FITS(size_offset,8) && PB_FITS(data_size,31) && PB_FITS(array_size,31), FIELDINFO_DOES_NOT_FIT_width8_field ## tag) +#endif + + +/* Automatic picking of FIELDINFO width: + * Uses width 1 when possible, otherwise resorts to width 2. + * This is used when PB_BIND() is called with "AUTO" as the argument. + * The generator will give explicit size argument when it knows that a message + * structure grows beyond 1-word format limits. + */ +#define PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype) PB_FI_WIDTH ## atype(htype, ltype) +#define PB_FI_WIDTH_PB_ATYPE_STATIC(htype, ltype) PB_FI_WIDTH ## htype(ltype) +#define PB_FI_WIDTH_PB_ATYPE_POINTER(htype, ltype) PB_FI_WIDTH ## htype(ltype) +#define PB_FI_WIDTH_PB_ATYPE_CALLBACK(htype, ltype) 2 +#define PB_FI_WIDTH_PB_HTYPE_REQUIRED(ltype) PB_FI_WIDTH ## ltype +#define PB_FI_WIDTH_PB_HTYPE_SINGULAR(ltype) PB_FI_WIDTH ## ltype +#define PB_FI_WIDTH_PB_HTYPE_OPTIONAL(ltype) PB_FI_WIDTH ## ltype +#define PB_FI_WIDTH_PB_HTYPE_ONEOF(ltype) PB_FI_WIDTH ## ltype +#define PB_FI_WIDTH_PB_HTYPE_REPEATED(ltype) 2 +#define PB_FI_WIDTH_PB_HTYPE_FIXARRAY(ltype) 2 +#define PB_FI_WIDTH_PB_LTYPE_BOOL 1 +#define PB_FI_WIDTH_PB_LTYPE_BYTES 2 +#define PB_FI_WIDTH_PB_LTYPE_DOUBLE 1 +#define PB_FI_WIDTH_PB_LTYPE_ENUM 1 +#define PB_FI_WIDTH_PB_LTYPE_UENUM 1 +#define PB_FI_WIDTH_PB_LTYPE_FIXED32 1 +#define PB_FI_WIDTH_PB_LTYPE_FIXED64 1 +#define PB_FI_WIDTH_PB_LTYPE_FLOAT 1 +#define PB_FI_WIDTH_PB_LTYPE_INT32 1 +#define PB_FI_WIDTH_PB_LTYPE_INT64 1 +#define PB_FI_WIDTH_PB_LTYPE_MESSAGE 2 +#define PB_FI_WIDTH_PB_LTYPE_MSG_W_CB 2 +#define PB_FI_WIDTH_PB_LTYPE_SFIXED32 1 +#define PB_FI_WIDTH_PB_LTYPE_SFIXED64 1 +#define PB_FI_WIDTH_PB_LTYPE_SINT32 1 +#define PB_FI_WIDTH_PB_LTYPE_SINT64 1 +#define PB_FI_WIDTH_PB_LTYPE_STRING 2 +#define PB_FI_WIDTH_PB_LTYPE_UINT32 1 +#define PB_FI_WIDTH_PB_LTYPE_UINT64 1 +#define PB_FI_WIDTH_PB_LTYPE_EXTENSION 1 +#define PB_FI_WIDTH_PB_LTYPE_FIXED_LENGTH_BYTES 2 + +/* The mapping from protobuf types to LTYPEs is done using these macros. */ +#define PB_LTYPE_MAP_BOOL PB_LTYPE_BOOL +#define PB_LTYPE_MAP_BYTES PB_LTYPE_BYTES +#define PB_LTYPE_MAP_DOUBLE PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_ENUM PB_LTYPE_VARINT +#define PB_LTYPE_MAP_UENUM PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_FIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_FIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_FLOAT PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE +#define PB_LTYPE_MAP_MSG_W_CB PB_LTYPE_SUBMSG_W_CB +#define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_STRING PB_LTYPE_STRING +#define PB_LTYPE_MAP_UINT32 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_UINT64 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION +#define PB_LTYPE_MAP_FIXED_LENGTH_BYTES PB_LTYPE_FIXED_LENGTH_BYTES + +/* These macros are used for giving out error messages. + * They are mostly a debugging aid; the main error information + * is the true/false return value from functions. + * Some code space can be saved by disabling the error + * messages if not used. + * + * PB_SET_ERROR() sets the error message if none has been set yet. + * msg must be a constant string literal. + * PB_GET_ERROR() always returns a pointer to a string. + * PB_RETURN_ERROR() sets the error and returns false from current + * function. + */ +#ifdef PB_NO_ERRMSG +#define PB_SET_ERROR(stream, msg) PB_UNUSED(stream) +#define PB_GET_ERROR(stream) "(errmsg disabled)" +#else +#define PB_SET_ERROR(stream, msg) (stream->errmsg = (stream)->errmsg ? (stream)->errmsg : (msg)) +#define PB_GET_ERROR(stream) ((stream)->errmsg ? (stream)->errmsg : "(none)") +#endif + +#define PB_RETURN_ERROR(stream, msg) return PB_SET_ERROR(stream, msg), false + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#ifdef __cplusplus +#if __cplusplus >= 201103L +#define PB_CONSTEXPR constexpr +#else // __cplusplus >= 201103L +#define PB_CONSTEXPR +#endif // __cplusplus >= 201103L + +#if __cplusplus >= 201703L +#define PB_INLINE_CONSTEXPR inline constexpr +#else // __cplusplus >= 201703L +#define PB_INLINE_CONSTEXPR PB_CONSTEXPR +#endif // __cplusplus >= 201703L + +extern "C++" +{ +namespace nanopb { +// Each type will be partially specialized by the generator. +template struct MessageDescriptor; +} // namespace nanopb +} +#endif /* __cplusplus */ + +#endif diff --git a/Bingoo/include/base/pb_common.h b/Bingoo/include/base/pb_common.h new file mode 100644 index 0000000..58aa90f --- /dev/null +++ b/Bingoo/include/base/pb_common.h @@ -0,0 +1,49 @@ +/* pb_common.h: Common support functions for pb_encode.c and pb_decode.c. + * These functions are rarely needed by applications directly. + */ + +#ifndef PB_COMMON_H_INCLUDED +#define PB_COMMON_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initialize the field iterator structure to beginning. + * Returns false if the message type is empty. */ +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message); + +/* Get a field iterator for extension field. */ +bool pb_field_iter_begin_extension(pb_field_iter_t *iter, pb_extension_t *extension); + +/* Same as pb_field_iter_begin(), but for const message pointer. + * Note that the pointers in pb_field_iter_t will be non-const but shouldn't + * be written to when using these functions. */ +bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message); +bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension); + +/* Advance the iterator to the next field. + * Returns false when the iterator wraps back to the first field. */ +bool pb_field_iter_next(pb_field_iter_t *iter); + +/* Advance the iterator until it points at a field with the given tag. + * Returns false if no such field exists. */ +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag); + +/* Find a field with type PB_LTYPE_EXTENSION, or return false if not found. + * There can be only one extension range field per message. */ +bool pb_field_iter_find_extension(pb_field_iter_t *iter); + +#ifdef PB_VALIDATE_UTF8 +/* Validate UTF-8 text string */ +bool pb_validate_utf8(const char *s); +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif + diff --git a/Bingoo/include/base/pb_decode.h b/Bingoo/include/base/pb_decode.h new file mode 100644 index 0000000..ae1d3cc --- /dev/null +++ b/Bingoo/include/base/pb_decode.h @@ -0,0 +1,193 @@ +/* pb_decode.h: Functions to decode protocol buffers. Depends on pb_decode.c. + * The main function is pb_decode. You also need an input stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_DECODE_H_INCLUDED +#define PB_DECODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom input streams. You will need to provide + * a callback function to read the bytes from your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause decoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer), + * and rely on pb_read to verify that no-body reads past bytes_left. + * 3) Your callback may be used with substreams, in which case bytes_left + * is different than from the main stream. Don't use bytes_left to compute + * any pointers. + */ +struct pb_istream_s +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + */ + int *callback; +#else + bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count); +#endif + + void *state; /* Free field for use by callback implementation */ + size_t bytes_left; + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +#ifndef PB_NO_ERRMSG +#define PB_ISTREAM_EMPTY {0,0,0,0} +#else +#define PB_ISTREAM_EMPTY {0,0,0} +#endif + +/*************************** + * Main decoding functions * + ***************************/ + +/* Decode a single protocol buffers message from input stream into a C structure. + * Returns true on success, false on any failure. + * The actual struct pointed to by dest must match the description in fields. + * Callback fields of the destination structure must be initialized by caller. + * All other fields will be initialized by this function. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_istream_t stream; + * + * // ... read some data into buffer ... + * + * stream = pb_istream_from_buffer(buffer, count); + * pb_decode(&stream, MyMessage_fields, &msg); + */ +bool pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct); + +/* Extended version of pb_decode, with several options to control + * the decoding process: + * + * PB_DECODE_NOINIT: Do not initialize the fields to default values. + * This is slightly faster if you do not need the default + * values and instead initialize the structure to 0 using + * e.g. memset(). This can also be used for merging two + * messages, i.e. combine already existing data with new + * values. + * + * PB_DECODE_DELIMITED: Input message starts with the message size as varint. + * Corresponds to parseDelimitedFrom() in Google's + * protobuf API. + * + * PB_DECODE_NULLTERMINATED: Stop reading when field tag is read as 0. This allows + * reading null terminated messages. + * NOTE: Until nanopb-0.4.0, pb_decode() also allows + * null-termination. This behaviour is not supported in + * most other protobuf implementations, so PB_DECODE_DELIMITED + * is a better option for compatibility. + * + * Multiple flags can be combined with bitwise or (| operator) + */ +#define PB_DECODE_NOINIT 0x01U +#define PB_DECODE_DELIMITED 0x02U +#define PB_DECODE_NULLTERMINATED 0x04U +bool pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags); + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define pb_decode_noinit(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_NOINIT) +#define pb_decode_delimited(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_DELIMITED) +#define pb_decode_delimited_noinit(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_DELIMITED | PB_DECODE_NOINIT) +#define pb_decode_nullterminated(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_NULLTERMINATED) + +/* Release any allocated pointer fields. If you use dynamic allocation, you should + * call this for any successfully decoded message when you are done with it. If + * pb_decode() returns with an error, the message is already released. + */ +void pb_release(const pb_msgdesc_t *fields, void *dest_struct); + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an input stream for reading from a memory buffer. + * + * msglen should be the actual length of the message, not the full size of + * allocated buffer. + * + * Alternatively, you can use a custom stream that reads directly from e.g. + * a file or a network socket. + */ +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t msglen); + +/* Function to read from a pb_istream_t. You can use this if you need to + * read some custom header data, or to read data in field callbacks. + */ +bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Decode the tag for the next field in the stream. Gives the wire type and + * field tag. At end of the message, returns false and sets eof to true. */ +bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof); + +/* Skip the field payload data, given the wire type. */ +bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type); + +/* Decode an integer in the varint format. This works for enum, int32, + * int64, uint32 and uint64 field types. */ +#ifndef PB_WITHOUT_64BIT +bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest); +#else +#define pb_decode_varint pb_decode_varint32 +#endif + +/* Decode an integer in the varint format. This works for enum, int32, + * and uint32 field types. */ +bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest); + +/* Decode a bool value in varint format. */ +bool pb_decode_bool(pb_istream_t *stream, bool *dest); + +/* Decode an integer in the zig-zagged svarint format. This works for sint32 + * and sint64. */ +#ifndef PB_WITHOUT_64BIT +bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest); +#else +bool pb_decode_svarint(pb_istream_t *stream, int32_t *dest); +#endif + +/* Decode a fixed32, sfixed32 or float value. You need to pass a pointer to + * a 4-byte wide C variable. */ +bool pb_decode_fixed32(pb_istream_t *stream, void *dest); + +#ifndef PB_WITHOUT_64BIT +/* Decode a fixed64, sfixed64 or double value. You need to pass a pointer to + * a 8-byte wide C variable. */ +bool pb_decode_fixed64(pb_istream_t *stream, void *dest); +#endif + +#ifdef PB_CONVERT_DOUBLE_FLOAT +/* Decode a double value into float variable. */ +bool pb_decode_double_as_float(pb_istream_t *stream, float *dest); +#endif + +/* Make a limited-length substream for reading a PB_WT_STRING field. */ +bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream); +bool pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/pb_encode.h b/Bingoo/include/base/pb_encode.h new file mode 100644 index 0000000..8913683 --- /dev/null +++ b/Bingoo/include/base/pb_encode.h @@ -0,0 +1,185 @@ +/* pb_encode.h: Functions to encode protocol buffers. Depends on pb_encode.c. + * The main function is pb_encode. You also need an output stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_ENCODE_H_INCLUDED +#define PB_ENCODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom output streams. You will need to provide + * a callback function to write the bytes to your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause encoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer). + * 3) pb_write will update bytes_written after your callback runs. + * 4) Substreams will modify max_size and bytes_written. Don't use them + * to calculate any pointers. + */ +struct pb_ostream_s +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + * Also, NULL pointer marks a 'sizing stream' that does not + * write anything. + */ + const int *callback; +#else + bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +#endif + void *state; /* Free field for use by callback implementation. */ + size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */ + size_t bytes_written; /* Number of bytes written so far. */ + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +/*************************** + * Main encoding functions * + ***************************/ + +/* Encode a single protocol buffers message from C structure into a stream. + * Returns true on success, false on any failure. + * The actual struct pointed to by src_struct must match the description in fields. + * All required fields in the struct are assumed to have been filled in. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_ostream_t stream; + * + * msg.field1 = 42; + * stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + * pb_encode(&stream, MyMessage_fields, &msg); + */ +bool pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct); + +/* Extended version of pb_encode, with several options to control the + * encoding process: + * + * PB_ENCODE_DELIMITED: Prepend the length of message as a varint. + * Corresponds to writeDelimitedTo() in Google's + * protobuf API. + * + * PB_ENCODE_NULLTERMINATED: Append a null byte to the message for termination. + * NOTE: This behaviour is not supported in most other + * protobuf implementations, so PB_ENCODE_DELIMITED + * is a better option for compatibility. + */ +#define PB_ENCODE_DELIMITED 0x02U +#define PB_ENCODE_NULLTERMINATED 0x04U +bool pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags); + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define pb_encode_delimited(s,f,d) pb_encode_ex(s,f,d, PB_ENCODE_DELIMITED) +#define pb_encode_nullterminated(s,f,d) pb_encode_ex(s,f,d, PB_ENCODE_NULLTERMINATED) + +/* Encode the message to get the size of the encoded data, but do not store + * the data. */ +bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct); + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an output stream for writing into a memory buffer. + * The number of bytes written can be found in stream.bytes_written after + * encoding the message. + * + * Alternatively, you can use a custom stream that writes directly to e.g. + * a file or a network socket. + */ +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize); + +/* Pseudo-stream for measuring the size of a message without actually storing + * the encoded data. + * + * Example usage: + * MyMessage msg = {}; + * pb_ostream_t stream = PB_OSTREAM_SIZING; + * pb_encode(&stream, MyMessage_fields, &msg); + * printf("Message size is %d\n", stream.bytes_written); + */ +#ifndef PB_NO_ERRMSG +#define PB_OSTREAM_SIZING {0,0,0,0,0} +#else +#define PB_OSTREAM_SIZING {0,0,0,0} +#endif + +/* Function to write into a pb_ostream_t stream. You can use this if you need + * to append or prepend some custom headers to the message. + */ +bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Encode field header based on type and field number defined in the field + * structure. Call this from the callback before writing out field contents. */ +bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_iter_t *field); + +/* Encode field header by manually specifying wire type. You need to use this + * if you want to write out packed arrays from a callback field. */ +bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number); + +/* Encode an integer in the varint format. + * This works for bool, enum, int32, int64, uint32 and uint64 field types. */ +#ifndef PB_WITHOUT_64BIT +bool pb_encode_varint(pb_ostream_t *stream, uint64_t value); +#else +bool pb_encode_varint(pb_ostream_t *stream, uint32_t value); +#endif + +/* Encode an integer in the zig-zagged svarint format. + * This works for sint32 and sint64. */ +#ifndef PB_WITHOUT_64BIT +bool pb_encode_svarint(pb_ostream_t *stream, int64_t value); +#else +bool pb_encode_svarint(pb_ostream_t *stream, int32_t value); +#endif + +/* Encode a string or bytes type field. For strings, pass strlen(s) as size. */ +bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size); + +/* Encode a fixed32, sfixed32 or float value. + * You need to pass a pointer to a 4-byte wide C variable. */ +bool pb_encode_fixed32(pb_ostream_t *stream, const void *value); + +#ifndef PB_WITHOUT_64BIT +/* Encode a fixed64, sfixed64 or double value. + * You need to pass a pointer to a 8-byte wide C variable. */ +bool pb_encode_fixed64(pb_ostream_t *stream, const void *value); +#endif + +#ifdef PB_CONVERT_DOUBLE_FLOAT +/* Encode a float value so that it appears like a double in the encoded + * message. */ +bool pb_encode_float_as_double(pb_ostream_t *stream, float value); +#endif + +/* Encode a submessage field. + * You need to pass the pb_field_t array and pointer to struct, just like + * with pb_encode(). This internally encodes the submessage twice, first to + * calculate message size and then to actually write it out. + */ +bool pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/Bingoo/include/base/readme.h b/Bingoo/include/base/readme.h new file mode 100644 index 0000000..d7a8510 --- /dev/null +++ b/Bingoo/include/base/readme.h @@ -0,0 +1,38 @@ + + +/* + * readme.h + * + * Created on: 2023年10月31日 + * Author: shiya + * + * CAN_H7_Bootloader程序存放位置 + * FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K + * 要求APP的存放位置为: + * FLASH (rx) : ORIGIN = 0x08020000, LENGTH = 896K + * APP的中断向量表设置为: + * define VECT_TAB_OFFSET 0x00020000U + * + * Boot顺序(关联CAN总线2): + * Boot程序总线返回报文ID:0x1FF 类型:标准帧 + * 1. Boot启动,返回报文长度1的报文; + * 2. 延时100ms,期间等待报文0x110标准帧,首字节0x55,如果接收到 进入BootLoader程序 A; + * 3. 如果没有收到进入bootloader请求,返回报文长度3的报文,跳转到APP; + * + * A. 如果进入bootloader程序,返回报文长度2的报文,等待刷写; + * 刷写ID为0x222,逻辑参见“canbootloader.lua” + * B. 如果刷写过程存在失败,返回报文长度4的报文,可以重新尝试运行“canbootloader.lua”进行刷写; + * + * C. 刷写成功,返回报文长度3的报文,进入APP; + * PV 用户可修改数据 + * CV 管理员配置权限,CV中有PV + * GV 机器人数据 + * IV 机器人返回上位机的表征数据 + * + */ +#ifndef INC_BSP_README_H_ +#define INC_BSP_README_H_ + + + +#endif /* INC_BSP_README_H_ */ diff --git a/Bingoo/include/base/robot_move_actions.h b/Bingoo/include/base/robot_move_actions.h new file mode 100644 index 0000000..9b5edba --- /dev/null +++ b/Bingoo/include/base/robot_move_actions.h @@ -0,0 +1,34 @@ +/* + * robot_move_actions.h + * + * Created on: 2026年2月26日 + * Author: bm673 + */ + +#ifndef FSM_INC_ROBOT_MOVE_ACTIONS_H_ +#define FSM_INC_ROBOT_MOVE_ACTIONS_H_ + +#include "BHBF_ROBOT.h" +#include "fsm_state.h" + +extern int s_currentState; +extern int swing_currentState; +/*=========================== 对外接口函数声明 ===========================*/ +/* 基础运动控制 */ +void Robot_Stop(void); +void Manually_Forward(void); +void Manually_Backward(void); +void Turn_Right(void); +void Turn_Left(void); + +/* 状态机驱动函数(需外部调用) */ +void Move_Horizontal_Auto_Sub_Func(void); /* 水平自动运行主状态机 */ +void Move_Horizontal_Auto_Sub_Func(void); +void Change_Road_Func(void); /* 垂直左换道状态机(注意:该函数实际使用换道状态表,需确认命名) */ +void horizontal_forward(void); /* 水平前进(PID控制) */ +void vertical_forward(void); /* 垂直前进(PID控制) */ + +void flag_reset(void); +void Emergency_Stop_Action(void); + +#endif /* FSM_INC_ROBOT_MOVE_ACTIONS_H_ */ diff --git a/Bingoo/include/base/swing_action.h b/Bingoo/include/base/swing_action.h new file mode 100644 index 0000000..ebeb9c7 --- /dev/null +++ b/Bingoo/include/base/swing_action.h @@ -0,0 +1,20 @@ +/* + * swing_action.h + * + * Created on: Mar 4, 2026 + * Author: 42961 + */ + +#ifndef FSM_INC_SWING_ACTION_H_ +#define FSM_INC_SWING_ACTION_H_ + +extern int limit_record; +extern float left_compare_value; +extern float right_compare_value; +extern float left_compare_updata; +extern float right_compare_updata; + +extern void Robot_Swing_Operation_Function(); + + +#endif /* FSM_INC_SWING_ACTION_H_ */ diff --git a/Bingoo/include/base/tcp_server.h b/Bingoo/include/base/tcp_server.h new file mode 100644 index 0000000..8a7e4a4 --- /dev/null +++ b/Bingoo/include/base/tcp_server.h @@ -0,0 +1,49 @@ +/* + * bsp_TCPServer.h + * + * Created on: 2025年8月4日 + * Author: akeguo + */ + +#ifndef BASE_INC_BSP_TCP_SERVER_H_ +#define BASE_INC_BSP_TCP_SERVER_H_ + +//#ifndef TCP_SERVER_H +//#define TCP_SERVER_H + +#include "lwip/tcp.h" +#include + +// 最大客户端连接数 +#define MAX_CLIENTS 8 + +// 客户端连接结构 +typedef struct { + struct tcp_pcb *pcb; // LwIP PCB指针 + uint8_t active; // 连接是否活跃 +} client_conn_t; + +// 服务器初始化 +void tcp_server_init(uint16_t port); + +// 发送数据给所有客户端 +void tcp_send_to_all_clients(const char *data, uint16_t len); + +// 定时器回调声明 +void tcp_server_timer_callback(void); + +typedef struct SendDataNode +{ + uint8_t Tx_Buf[255]; /*发送数据*/ + uint8_t Tx_Count; /*学号*/ + struct SendDataNode * next; /*指向下一个节点的指针*/ +}SendDataNode; +extern void tcp_add_sendList(uint8_t *tx_Buf, uint8_t tx_count); + + + + +//#endif /* TCP_SERVER_H */ + + +#endif /* BASE_INC_BSP_TCP_SERVER_H_ */ diff --git a/Core/Inc/main.h b/Core/Inc/main.h index ea8763e..c14ceb6 100644 --- a/Core/Inc/main.h +++ b/Core/Inc/main.h @@ -7,7 +7,7 @@ ****************************************************************************** * @attention * - * Copyright (c) 2026 STMicroelectronics. + * Copyright (c) 2023 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file @@ -46,7 +46,7 @@ extern "C" { /* Exported macro ------------------------------------------------------------*/ /* USER CODE BEGIN EM */ - + void USART_Dispatch(); /* USER CODE END EM */ /* Exported functions prototypes ---------------------------------------------*/ @@ -121,6 +121,51 @@ void Error_Handler(void); #define E22_AUX_GPIO_Port GPIOE /* USER CODE BEGIN Private defines */ +#define hlpuart1Exit 6 +//#define NewCANSendVersion 1 + +/*******IO***************/ +#define Motor_Power_IO_CTL 0 //K1 +#define PaintGun_IO_CTL 1 /*鍠锋灙K2*/ + + + +/********PINSTATE*********/ +#define K_ON_PaintGun 0 /*鍠锋灙锟???????*/ +#define K_OFF_PaintGun 1 + +#define K_ON_Motor 0 /*椹卞姩鐢垫満*/ +#define K_OFF_Motor 1 + +/*********************************************/ + +/*鎵嬪?*/ +#define Move_Manual 1 //??? +#define Move_Vertical_Move_To_Left 2 //绔栫洿鍚戝乏 +#define Move_Vertical_Move_To_Right 3 //绔栫洿鍚戝彸 + + + + + +typedef enum _Upper_TakeControl_State +{ + Not_Taken_Over = 0, Taken_Over = 1, +} Upper_TakeControl_State; +typedef enum _Button_Reset_State +{ + Has_Reset = 0, Has_Not_Reset = 1, +} Button_Reset_State; +typedef enum _HardWare_Disconnected_State +{ + CONNECTED = 0, DISCONNECTED = 1, +} HardWare_Disconnected_State; +typedef enum _HardWare_ErrorExisted_State +{ + NOT_ErrorExisted = 0, ErrorExisted = 1, +} HardWare_ErrorExisted_State; + + /* USER CODE END Private defines */ #ifdef __cplusplus diff --git a/Core/Src/main.c b/Core/Src/main.c index 3b68146..e86d98e 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -1,20 +1,20 @@ /* USER CODE BEGIN Header */ /** - ****************************************************************************** - * @file : main.c - * @brief : Main program body - ****************************************************************************** - * @attention - * - * Copyright (c) 2026 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" @@ -30,16 +30,48 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ +#include "BHBF_ROBOT.h" +#include "bsp_FDCAN.h" +#include +#include "msp_ground_management.h" +#include "msp_strain_gauge.h" +#include /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ - +void CV_GV_Init(); +void GF_Robot_Init(); +void Debug_Periph_NoFreeze_H7(void); /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ + +#define RS485_1_WaitTime 6 + +#define RS485_2_WaitTime 6 +#define RS485_3_WaitTime 6 +#define RS485_4_WaitTime 6 +#define LTE_7S0_Serial_WaitTime 6 +#define InterCall_DEBUG_WaitTime 6 +#define E28_SBUS_WaitTime 4 +#define LPUART1_UART_WaitTime 6 +#define RS485_1_Dispacher_Time 0 +#define RS485_2_Dispacher_Time 0 +#define RS485_3_Dispacher_Time 0 +#define RS485_4_Dispacher_Time 0 +#define LTE_7S0_Serial_Dispacher_Time 100 +#define InterCall_DEBUG_Dispacher_Time 100 +#define E28_SBUS_Dispacher_Time 100 +#define LPUART1_UART_Dispacher_Time 100 +int can1_sendListPeriod = 10; +int can1_DispacherPeriod = 4; +int can2_sendListPeriod = 10; +int can2_DispacherPeriod = 20; +int SAVE_To_CV = 0; +int dog_flag=0; /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ @@ -50,13 +82,14 @@ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ - +void protobuf_mqtt_setting_test(void); /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MPU_Config(void); /* USER CODE BEGIN PFP */ +char ReadIO[8]; /* USER CODE END PFP */ @@ -73,6 +106,8 @@ int main(void) { /* USER CODE BEGIN 1 */ + // the baud rate of the pressure sensor is 19200 + // tdl720 115200 /* USER CODE END 1 */ /* MPU Configuration--------------------------------------------------------*/ @@ -90,14 +125,20 @@ int main(void) HAL_Init(); /* USER CODE BEGIN Init */ - + // 强制 PF0 内部下拉,消除干扰,防止推杆导致单片机死机 +// __HAL_RCC_GPIOH_CLK_ENABLE(); +// GPIO_InitTypeDef gpio_conf = {0}; +// gpio_conf.Pin = GPIO_PIN_0; +// gpio_conf.Mode = GPIO_MODE_INPUT; +// gpio_conf.Pull = GPIO_PULLDOWN; // 关键:内部下拉 +// HAL_GPIO_Init(GPIOH, &gpio_conf); /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ - + //__HAL_RCC_D2SRAM3_CLK_ENABLE(); /* USER CODE END SysInit */ /* Initialize all configured peripherals */ @@ -121,17 +162,45 @@ int main(void) MX_LWIP_Init(); /* USER CODE BEGIN 2 */ + + SystemTimer_Intialize(); + + Error_Detect_Intialzie(1000); //every 1 seconds + GF_Robot_Init(); + GV.Robot_Move_Speed = 1; + TCP_Client_Init(); + +// GV.Robot_Move_Speed = 1000; +// HardWareErrorController->Add_PCOMHardWare(HardWareErrorController,"ComError_Ultrasonic_Sensor",0,ComError_Ultrasonic_Sensor); +// HardWareErrorController->Add_PCOMHardWare(HardWareErrorController,"ComError_Force_Sensor",0,ComError_Force_Sensor); + //tcp_client_connect(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ - while (1) - { + //HAL_Delay(3000); + //GF_BSP_GPIO_ToggleIO(Wind_IO_CTL); + while (1) + { + HAL_Delay(1); + if(dog_flag==0) + { + //HAL_IWDG_Refresh(&hiwdg1); // 喂狗 + } + + if (SAVE_To_CV == 1) + { + SAVE_To_CV = 0; + //CV写入falsh�?????????????????? + GF_BSP_EEPROM_Set_CV(CV); + CV = GF_BSP_EEPROM_Get_CV(); + //FS_SetZero(); + } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ - } + } /* USER CODE END 3 */ } @@ -203,6 +272,105 @@ void SystemClock_Config(void) /* USER CODE BEGIN 4 */ +void CV_GV_Init() +{ + //Read CV + CV = GF_BSP_EEPROM_Get_CV(); + CV.has_PID_high=true; + CV.has_PID_mid=true; + CV.has_PID_low=true; + + SystemErrorCode = &GV.SystemErrorData.Com_Error_Code; + + //电机绑定 +// LS_Motor[1]=&GV.LeftMotor; +// LS_Motor[2]=&GV.RightMotor; +// LS_Motor[3]=&GV.SwingMotor; +// +// LS_Motor[1]->MotorID=1; +// LS_Motor[2]->MotorID=2; +// LS_Motor[3]->MotorID=3; + + P_MK32 = &GV.P_MK32; + + SP_MSP_RF_TL720D_Parameters_In = &GV.TL720DParameters; + + + +// RobotAngle = &GV.Robot_Angle; + + tempature = &GV.TempatureE_2C; + ground_management_value=&GV.GroundManagementValue; + strainGaugeValue=&GV.Strain_Gauge; + GV.has_GroundManagementValue = true; + + GV.has_P_MK32 = true; + GV.has_LeftMotor = true; + GV.has_RightMotor = true; + GV.has_TL720DParameters = true; + GV.has_IO = true; + GV.has_SystemErrorData = true; + +} +void GF_Robot_Init() +{ + //GF_BSP_MPU_Init(); + //2ms调度 + GF_BSP_EEPROM_Init(); + CV_GV_Init(); + + //初始化encoder + GF_BSP_UARTHandlers_Intialize( + RS485_1_WaitTime, + RS485_2_WaitTime, + RS485_3_WaitTime, + RS485_4_WaitTime, + LTE_7S0_Serial_WaitTime, + InterCall_DEBUG_WaitTime, + E28_SBUS_WaitTime, + LPUART1_UART_WaitTime, + RS485_1_Dispacher_Time, + RS485_2_Dispacher_Time, + RS485_3_Dispacher_Time, + RS485_4_Dispacher_Time, + LTE_7S0_Serial_Dispacher_Time, + InterCall_DEBUG_Dispacher_Time, + E28_SBUS_Dispacher_Time, + LPUART1_UART_Dispacher_Time); + + //is_upper_computer_take_over_control = 0; + DLT_LOG_ENABLE_LEVEL = 0; //7 send all information //0 send nothing + //dLT_Log_intialize(&InterCall_DEBUG_UART_Handler); //huart4 +// dLT_Log_intialize(&InterCall_DEBUG_UART_Handler); + +// tcp_server_init(3490); +// dLT_Log_intialize_udp_tcp(); + + //upper_Computer_UART_Handler_intialize(&RS_485_4_UART_Handler);//send to computer to 485 + ground_management_intialize(&RS_485_4_UART_Handler); + TL720D_intialize(&RS_485_1_UART_Handler); + strain_gauge_intialize(&RS_485_4_UART_Handler);//应变&&推杆 115200 + MK32_Sbus_UART_Handler_intialize(&E28_SBUS_UART_Handler); //huart5 + client_setting_intialize(&LPUART1_UART_Handler); + + //WH_LTE_7S0_intialize(<E_7S0_Serial_UART_Handler);//huart2 + + GF_BSP_FDCAN_Init();//初始化FDCAN + + GF_BSP_CANHandler_Init(can1_sendListPeriod, can1_DispacherPeriod, + can2_sendListPeriod, can2_DispacherPeriod); + + Motor_Controller_intialize(&FD_CAN_1_Handler); + Motor_Controller_intialize_CAN2(&FD_CAN_2_Handler); + +// LS_Motor_Controller_intialize(&FD_CAN_1_Handler); + + Fsm_Init(); + + GF_BSP_TIMER_Init(); //定时器最后启 + + +} /* USER CODE END 4 */ /* MPU Configuration */ @@ -262,11 +430,14 @@ void MPU_Config(void) void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ - /* User can add his own implementation to report the HAL error return state */ - __disable_irq(); - while (1) - { - } + + /* User can add his own implementation to report the HAL error return state */ + __disable_irq(); + while (1) + { + HAL_Delay(1000); + LOGFF(DL_ERROR, "Something Bad Happened, Now in Error_Handler Function"); + } /* USER CODE END Error_Handler_Debug */ }