protocolV1_1.c 23.9 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
/*
 * @Date: 2023-11-22 17:32:04
 * @LastEditTime: 2024-03-15 16:34:03
 * @FilePath: \A1_IMU_Control_Board_FreeRTOSd:\JZ_LJL_ESP32_WORKSPACE\STM32_DEV\Three-Axis_MES_BLDC_Gimbal\WorkSpace_ALL\ThreeAxisGimbal_Cre231213\Ext_Common\Communication\protocolV1.c
 * @Description:
 */
#include "protocolV1_1.h"
#include "Motor_Manage.h"
#include "BMCL.h"
#include "motor.h"
#include "T_SpeedShape.h"
#include "BMCL_ParaLoadF1.h"
#include "buzzer.h"
#include "upgrade.h"
#include <string.h>

extern float PlanTarget;
extern TRAP_CURVE_s rollANGPlan;
extern float rollANGPlan_Time ;
extern TimeRec_s rollANGPlan_TimeS ;
#define PROTOCOL_REPLY_TXBUFF_LEN 14

uint8_t protocol_reply_TXBuff[PROTOCOL_REPLY_TXBUFF_LEN] = {0};
uint8_t protocol_reply_payload[128] = {0};

//==============Protocol reception result area==============
Pro_data current_axis_data = {0};
Pro_data target_axis_data = {0};

Pro_data Gen_dataResult = {0};

Pro_data YawMot_dataResult = {0};
Pro_data RollMot_dataResult = {0};

uint8_t paraIndex = 0;
uint8_t commSequence = 0;

uint8_t frameTypePer = 0x00;  // 识别到的帧类型
uint8_t frameSRPer = 0x00;    // 识别到的子路由
uint8_t targetAxisPer = 0x00; // 目标电机
uint8_t indexPer = 0x00; // 参数索引
uint8_t commSequencePer = 0x00;
uint8_t generalResult = 0; //通用回复检测结果
uint8_t CalibrationCmplete = 0; //校准完成标志位
uint8_t operationResult = 0; //操作回复检测结果

//___________________________PROTOCOL COMPONENT___________________________

/**
 * @brief 协议传输帧的生成
 * @param frameType 帧类型 - 该类型只是用来标识该数据帧,不会对传输的数据做特殊处理
 * @param frameSR   子路由类型 - 该类型只是用来标记该数据帧,不会对传输的数据做特殊处理
 * @param verify 校验开关
 * @param buff 输出缓存区地址
 * @param buff_len 输出缓冲区长度
 * @param data 传输的数据(与选择的帧类型相关,会根据帧类型进行数据指针的转换,要确保要传输数据的正确写入)
 * @param fun1 附加功能1 的 数据 uint8类型,在24P
 * @return
 */
int protocol_frame_make(uint8_t type,PROTOCOL_F_FUNCTION_1 function_1, PROTOCOL_F_FUNCTION_2 function_2,uint8_t ask, PROTOCOL_F_COMMSQR frameSequence,\
uint8_t *buff,uint16_t buff_len,void const *data,uint16_t data_len)
{
    uint8_t sum = 0, i;
    const Pro_data *data_t;
    Pro_data *buff_t;
    uint8_t *buff_p;

    if (buff_len <= PROTOCOL_LEN) // 缓冲区长度不够,退
        return -1;

    if(type)
    {
        buff[PROTOCOL_P_HEAD_0] = PROTOCOL_CONTENT_HEAD_0; // 写入帧头
        buff[PROTOCOL_P_HEAD_1] = PROTOCOL_CONTENT_HEAD_1;
        buff[PROTOCOL_P_HEAD_2] = PROTOCOL_CONTENT_HEAD_2;
    }else
    {
        buff[PROTOCOL_P_HEAD_0] = PROTOCOL_CONTENT_RETHEAD_0; // 写入回复帧头
        buff[PROTOCOL_P_HEAD_1] = PROTOCOL_CONTENT_RETHEAD_1;
        buff[PROTOCOL_P_HEAD_2] = PROTOCOL_CONTENT_RETHEAD_2;
    }


    buff[PROTOCOL_P_LEN_H] = data_len>>8;
    buff[PROTOCOL_P_LEN_L] = data_len&0xff;

    buff[PROTOCOL_P_ASK] = ask;
    buff[PROTOCOL_P_SEQUENCE] = frameSequence;
    buff[PROTOCOL_P_FUNCTION_1] = function_1;
    buff[PROTOCOL_P_FUNCTION_2] = function_2;

    if (data_len == 0x0C)
    {
        data_t = (Pro_data*)data;
        buff[PROTOCOL_P_DATA] = data_t->rawdata_8t[0];
    }else if (data_len == 0x0D)
    {
        data_t = (Pro_data*)data;
        for (i = 0; i < 2; i++)
        {
          buff[PROTOCOL_P_DATA+i] = data_t->rawdata_8t[i];
        }
    }else if (data_len == 0x0E)
    {
        data_t = (Pro_data*)data;
        buff_t = (Pro_data*)&buff[PROTOCOL_P_DATA];
        buff_t->rawdata.symbol = data_t->rawdata.symbol;
        buff_t->rawdata.dataH = data_t->rawdata.dataH;
        buff_t->rawdata.dataL = data_t->rawdata.dataL;
    }else if (data_len > 0x0E)
    {
        buff_p = (uint8_t*)data;
        for (i = 0; i < data_len-10; i++)
        {
            buff[PROTOCOL_P_DATA + i] = buff_p[i];
        }
    }

    buff[data_len-2] = PROTOCOL_CONTENT_TAIL_0; // 写入帧尾
    buff[data_len-1] = PROTOCOL_CONTENT_TAIL_1;

    return 0;
}

/**
 * @brief 协议帧处理函数(只处理一帧),将缓存中的数据进行解析存放并输出结果
 * @param buff 需要处理的数据头指针
 * @param buff_len 需要处理的数据长度
 * @return ( >0 )处理成功:(PROTOCOL_F_TYPE)返回处理的数据帧类型;
 *         ( <0 )处理失败:PROTOCOL_PARSE_STATUS
 */
Pro_Parse_Result protocol_frame_parse(uint8_t *buff, uint32_t buff_len)
{
    uint32_t do_point = 0;                          // 当前处理点
    uint16_t datalen = 0;	                        //数据长度
    Pro_data *temp;                                 // 映射用变量
    float data,CurAngle;
    Pro_Parse_Result result = {0};                        // 返回结果,结果包含:错误信息,帧类型,子路由能
		uint8_t ret = 0;

    if (buff_len < PROTOCOL_LEN){
        result.error = PROTOCOL_P_STATUS_NOFRAME;
        goto PROTOCOL_PARSE_END;  // 接收到的数据非法 - 长度太小,不足以容纳一个帧
    }    
    while (do_point <= buff_len - PROTOCOL_LEN) // 帧头检测  注意:防止越界和漏算
    {
        if (buff[do_point] == 0x5A||buff[do_point] == 0x6A) // 帧头预检测
        {
            if ((buff[do_point + 1] == 0x5A || buff[do_point + 1] == 0x6A) && (buff[do_point + 2] == 0x77)) // 帧头检测
            {
                datalen = buff[do_point + 3]  * 256 + buff[do_point + 4];//数据长度

                if (buff[datalen - 2] == 0x00 && buff[datalen - 1] == 0x23) // 帧尾检查
                {
                    buff = &(buff[do_point]); // 得到当前操作的位置,注意已经覆写了buff指针,该位置即是帧头位置

                    temp = (Pro_data *)&buff[PROTOCOL_P_DATA]; // buff重映射

                    // 帧类型识别并处理
                    switch (buff[PROTOCOL_P_FUNCTION_1])
                    {
                    case PROTOCOL_F_FUNCTION_1_0XFF: // 功能:工厂模式
                        switch (buff[PROTOCOL_P_FUNCTION_2])
                        {
                        case PROTOCOL_F_FUNCTION_2_0XA1:
                            workMode = WORK_MODE_3;
                            BMCL_Genseamp_give(&bmcl_Music, Enter);
                            Operation_Reply(PROTOCOL_F_FUNCTION_2_0X01);
                            break;
                        case PROTOCOL_F_FUNCTION_2_0XA0:
                            workMode = WORK_MODE_1;
                            BMCL_Genseamp_give(&bmcl_Music, Enter);
                            Operation_Reply(PROTOCOL_F_FUNCTION_2_0X01);
                            break;
                        default:
                            break;
                        }
                        break;
                    case PROTOCOL_F_FUNCTION_1_0X50: // 功能:连接请求,返回设备号
//												if(buff[PROTOCOL_P_FUNCTION_2]== PROTOCOL_F_FUNCTION_2_0X51)
//												{
													BMCL_Genseamp_give(&bmcl_Music, Connect);
													temp = (Pro_data *)&protocol_reply_payload[0]; // 帧Payload重映射
//													temp->rawdata_8t[0] = 0x11;
													temp->rawdata_8t[0] = 0x4C;//单轴云台
													protocol_frame_make(0x00, PROTOCOL_F_FUNCTION_1_0X50, PROTOCOL_F_FUNCTION_2_0X51, 0x00, PROTOCOL_F_COMMSQR_00, protocol_reply_TXBuff, PROTOCOL_REPLY_TXBUFF_LEN, (void *)protocol_reply_payload, 0x0C);
													Uart1_Send_DMA_StartBuff((uint8_t *)protocol_reply_TXBuff, (uint16_t)(sizeof(uint8_t) * 12));
//													printf("连接帧\r\n");
													devConnetState = 1;	
//												}
                        break;
                    case PROTOCOL_F_FUNCTION_1_0X64: // 功能:云台俯仰控制
                        switch (buff[PROTOCOL_P_FUNCTION_2])
                        {
                        case PROTOCOL_F_FUNCTION_2_0X51: // 功能:云台俯仰目标角度
                            data = (float)(temp->rawdata.dataH << 8|temp->rawdata.dataL)/10.0f;
                            if (temp->rawdata.symbol == 0xFF)
                            {
                                data = -data;
                            }
                           
                            data = constrain(data,motor_GetDownLimit(),motor_GetUpLimit());
                            // trap_Curve_SetTarget(&rollANGPlan, data);
                            PlanTarget = data;

                            // 当前角度回复
                            
                            // CurAngle = motor_obs.actual_Angle*57.2957795130f;
                            CurAngle = PlanTarget;
                            temp = (Pro_data *)&protocol_reply_payload[0]; // 帧Payload重映射
                            if (CurAngle < 0)
                            {
                                temp->rawdata.symbol = 0xFF;
                                CurAngle = -CurAngle;
                            }else
                            {
                                temp->rawdata.symbol = 0x00;
                            }
                            uint16_t dataRet = (uint16_t)(CurAngle * 10);
                            temp->rawdata.dataH = dataRet>>8;
                            temp->rawdata.dataL = dataRet&0xFF;
                            // 回复帧
                            protocol_frame_make(0x00, PROTOCOL_F_FUNCTION_1_0X64, PROTOCOL_F_FUNCTION_2_0X51, 0x00, PROTOCOL_F_COMMSQR_00, protocol_reply_TXBuff, PROTOCOL_REPLY_TXBUFF_LEN, (void *)protocol_reply_payload, 0x0E);
                            Uart1_Send_DMA_StartBuff((uint8_t *)protocol_reply_TXBuff, (uint16_t)(sizeof(uint8_t) * 14));
                            break;
                        case PROTOCOL_F_FUNCTION_2_0X52: // 功能:云台俯仰加减微调
 
                            break;
                        default:
                            break;
                        }
                        break;
                    case PROTOCOL_F_FUNCTION_1_0X6F://角度查询
                        switch (buff[PROTOCOL_P_FUNCTION_2])
                        {
                        case PROTOCOL_F_FUNCTION_2_0X54: // 功能:角度查询
                            // 当前角度回复
                            CurAngle = motor_obs.actual_Angle*57.2957795130f;
                            temp = (Pro_data *)&protocol_reply_payload[0]; // 帧Payload重映射
                            if (CurAngle < 0)
                            {
                                temp->rawdata.symbol = 0xFF;
                                CurAngle = -CurAngle;
                            }
                            else
                            {
                                temp->rawdata.symbol = 0x00;
                            }
                            uint16_t dataRet = (uint16_t)(CurAngle * 10);
                            temp->rawdata.dataH = dataRet >> 8;
                            temp->rawdata.dataL = dataRet & 0xFF;
                            // 回复帧
                            protocol_frame_make(0x00, PROTOCOL_F_FUNCTION_1_0X64, PROTOCOL_F_FUNCTION_2_0X51, 0x00, PROTOCOL_F_COMMSQR_00, protocol_reply_TXBuff, PROTOCOL_REPLY_TXBUFF_LEN, (void *)protocol_reply_payload, 0x0E);
                            Uart1_Send_DMA_StartBuff((uint8_t *)protocol_reply_TXBuff, (uint16_t)(sizeof(uint8_t) * 14));
                            break;
                        default:
                            break;
                        }
                        break;
                    case PROTOCOL_F_FUNCTION_1_0X69: // 功能: 云台最大值、最小值、零度设置
                        switch (buff[PROTOCOL_P_FUNCTION_2])
                        {
                        case PROTOCOL_F_FUNCTION_2_0X51: // 功能:设置当前位置为零度
                            CurAngle =  motor_obs.actual_Angle;
                            mge_Set_abOffset(mge_Get_abOffset()+CurAngle);
                            motor_SetUpLimit(150.0f); //只要重新设置了零度,就将云台限位角度最大值、最小值置为-150 —— +150
                            motor_SetDownLimit(-150.0f); //以便重新调整限位角度

                            memset(&rollANGPlan_TimeS,0x00,sizeof(TimeRec_s));//重新初始化速度规划
                            memset(&rollANGPlan,0x00,sizeof(TRAP_CURVE_s));
                            rollANGPlan_Time += TimeFlash(&rollANGPlan_TimeS);
                            trap_Curve_Init(&rollANGPlan, 400.0f, 800.0f, rollANGPlan_Time, TRAP_CURVE_CYCMODE_OFF, 0);
                            PlanTarget = 0;

                            BMCL_PL_WriteAll2ParaMge();
                            paraMge_SaveALL();

                            BMCL_Genseamp_give(&bmcl_Music, Enter);
                            Operation_Reply(PROTOCOL_F_FUNCTION_2_0X01);
                            break;
                        case PROTOCOL_F_FUNCTION_2_0X52: // 功能:云台最大值、最小值
                            CurAngle = motor_obs.actual_Angle;
                            if (temp->rawdata_8t[1] == 0xFF) // 设置当前位置为最大值
                            {
                                if (CurAngle > 0)
                                {
                                    PlanTarget = CurAngle;
                                    motor_SetUpLimit(CurAngle * 57.2957795130f); // 弧度转角度
                                    BMCL_PL_WriteAll2ParaMge();
                                    paraMge_SaveALL();

                                    BMCL_Genseamp_give(&bmcl_Music, Enter);
                                    Operation_Reply(PROTOCOL_F_FUNCTION_2_0X01);
                                }
                                else
                                {
                                    BMCL_Genseamp_give(&bmcl_Music, Quit);
                                    Operation_Reply(PROTOCOL_F_FUNCTION_2_0XFF); // 操作失败
                                }
                            }
                            else if (temp->rawdata_8t[1] == 0x00) // 设置当前位置为最小值
                            {
                                if (CurAngle < 0)
                                {
                                    PlanTarget = CurAngle;
                                    motor_SetDownLimit(CurAngle * 57.2957795130f); // 弧度转角度
                                    BMCL_PL_WriteAll2ParaMge();
                                    paraMge_SaveALL();

                                    BMCL_Genseamp_give(&bmcl_Music, Enter);
                                    Operation_Reply(PROTOCOL_F_FUNCTION_2_0X01);
                                }
                                else
                                {
                                    BMCL_Genseamp_give(&bmcl_Music, Quit);
                                    Operation_Reply(PROTOCOL_F_FUNCTION_2_0XFF); // 操作失败
                                }
                            }
                            break;
                        default:
                            break;
                        }
                        break;
                    case PROTOCOL_F_FUNCTION_1_0X05: // 电机基本校准
                        if (workMode == WORK_MODE_3)
                        {
                            switch (buff[PROTOCOL_P_FUNCTION_2])
                            {
                            case PROTOCOL_F_FUNCTION_2_0X01: // 进入校准&操作成功
                                BMCL_Genseamp_give(&bmcl_Music, Enter);
                                Operation_Reply(PROTOCOL_F_FUNCTION_2_0X01);
                                break;
                            case PROTOCOL_F_FUNCTION_2_0X00: // 功能:退出校准
                                BMCL_Genseamp_give(&bmcl_Music, Enter);
                                Operation_Reply(PROTOCOL_F_FUNCTION_2_0X01);
                                break;
                            case PROTOCOL_F_FUNCTION_2_0X02: // 开始指定轴校准&当前指定轴状态
                                switch (temp->rawdata_8t[0])
                                {
                                case __PARAMGE_INDEX_MOT_P:
                                    if (motor_Calibration_Status == __PARAMGE_DEF_MOT_CALI_STA_CALIBRATING||motor_Calibration_Status == __PARAMGE_DEF_MOT_CALI_STA_GOOD)
                                    {
                                        
                                    }else
                                    {
                                        motor_Calibration_Stop = 0 ;//重新校准时清零
                                        BMCL_Genseamp_give(&bmcl_Calibration, 0x00);
                                        BMCL_Genseamp_give(&bmcl_Music, Enter);
                                    }
                                    temp = (Pro_data *)&protocol_reply_payload[0]; // 帧Payload重映射
                                    temp->rawdata_8t[0] = motor_Calibration_Status;
                                    // 回复帧
                                    protocol_frame_make(0x00, PROTOCOL_F_FUNCTION_1_0X05, PROTOCOL_F_FUNCTION_2_0X02, 0x00, PROTOCOL_F_COMMSQR_00, protocol_reply_TXBuff, PROTOCOL_REPLY_TXBUFF_LEN, (void *)protocol_reply_payload, 0x0C);
                                    Uart1_Send_DMA_StartBuff((uint8_t *)protocol_reply_TXBuff, (uint16_t)(sizeof(uint8_t) * 12));
                                    break;
                                default:
                                    break;
                                }
                                break;
                            case PROTOCOL_F_FUNCTION_2_0X03: // 功能:保存指定轴校准数据
                                if (motor_Calibration_Stop)//如果校准时被退出指令中断了,不保存相关参数
                                {
                                    BMCL_Genseamp_give(&bmcl_Music, Quit);
                                    Operation_Reply(PROTOCOL_F_FUNCTION_2_0XFF);
                                }
                                else
                                {
                                    switch (temp->rawdata_8t[0])
                                    {
                                    case __PARAMGE_INDEX_MOT_P:
                                        BMCL_PL_PreLoadALL();
                                        motor_Set_ZeroEAngleOffset(zeroElectricAngleOffset_Temp);
                                        mge_Set_direction(mge_direction_Temp);
                                        mge_Set_abOffset(offset_Temp);
                                        if (motor_Calibration_Status != __PARAMGE_DEF_MOT_CALI_STA_GOOD) // flash只保存成功和失败两种情况
                                        {
                                            motor_Calibration_Status = __PARAMGE_DEF_MOT_CALI_STA_BAD;
                                        }
                                        BMCL_mot_Calibration = motor_Calibration_Status;
                                        BMCL_PL_WriteAll2ParaMge();
                                        paraMge_SaveALL();

                                        BMCL_Genseamp_give(&bmcl_Music, Enter);
                                        Operation_Reply(PROTOCOL_F_FUNCTION_2_0X01);
                                        break;
                                    default:
                                        BMCL_Genseamp_give(&bmcl_Music, Quit);
                                        Operation_Reply(PROTOCOL_F_FUNCTION_2_0XFF);
                                        break;
                                    }
                                }
                                break;
                            case PROTOCOL_F_FUNCTION_2_0X04: // 功能:退出指定轴校准
                                switch (temp->rawdata_8t[0])
                                {
                                case __PARAMGE_INDEX_MOT_P:
                                    BMCL_Genseamp_give(&bmcl_Music, Enter);
                                    motor_Calibration_Status = 0 ;//退出时状态清零以保证下次校准
                                    Operation_Reply(PROTOCOL_F_FUNCTION_2_0X01);
                                    break;
                                default:
                                    BMCL_Genseamp_give(&bmcl_Music, Quit);
                                    Operation_Reply(PROTOCOL_F_FUNCTION_2_0XFF);
                                    break;
                                }
                                break;
                            default:
                                break;
                            }
                        }
                        else
                        {
                            BMCL_Genseamp_give(&bmcl_Music, Quit);
                            Operation_Reply(PROTOCOL_F_FUNCTION_2_0XFF);  
                        }
                        break;

                    case PROTOCOL_F_FUNCTION_1_0XA1: // 串口升级
                        switch (buff[PROTOCOL_P_FUNCTION_2])// 判断功能位
                        {
                        case 0x01:
                        { // 准备串口升级
														workMode = WORK_MODE_4;
                            ret = UpgradePreparation();
                            if (ret != 0)
                            {
                                AnswerUpgradeFrame(0x01, 0x01);
                            }
                        }
                        break;

                        case 0x02:
                        { // 固件校验MD5校验码
                            printf("固件校验MD5校验码\r\n");
                            UpgradeFileMD5Code_Get(buff, datalen);
                        }
                        break;

                        case 0x03:
                        { // 开始发送文件
                            printf("开始发送文件\r\n");
                            AnswerUpgradeFrame(0x03, 0x00);
                        }
                        break;

                        case 0x04:
                        { // 结束文件传输
                            printf("结束文件传输\r\n");

                            AnswerUpgradeFrame(0x04, 0x00);
                            UpgradeFile_MD5Create();
                        }
                        break;

                        case 0xF1:
                        { // 定长文件数据
                            printf("定长文件数据\r\n");
                            ret = UpgradeFile_Write(buff, datalen);
//                            if (ret != 0) // 传输出错,提前结束文件传输
//                            {
//                                printf("传输出错\r\n");
//                            }
                        }
                        break;
                        default:
                            break;
                        }
                        break;
                    }
                        // result.fType = frameType;
                        // result.sRoute = sRouteType;
                        // result.readPoint = do_point + PROTOCOL_LEN - 1;
                        goto PROTOCOL_PARSE_END;
                        break;
                    }
            }
        }
        do_point++;
    }
    result.error = PROTOCOL_P_STATUS_NOFRAME;

PROTOCOL_PARSE_END:
    return result;
}

void Operation_Reply(PROTOCOL_F_FUNCTION_2 operation_Result)
{
    memset(protocol_reply_payload,0x00,128);

    protocol_frame_make(0x00,PROTOCOL_F_FUNCTION_1_0X51,operation_Result,0x00,PROTOCOL_F_COMMSQR_00,protocol_reply_TXBuff,PROTOCOL_REPLY_TXBUFF_LEN,(void *)protocol_reply_payload,0x0C);
    Uart1_Send_DMA_StartBuff((uint8_t *)protocol_reply_TXBuff, (uint16_t)(sizeof(uint8_t) * 12));
}

void AnswerUpgradeFrame(uint8_t func, uint8_t data)
{
    memset(protocol_reply_payload,0x00,128);
		protocol_reply_payload[0] = data ;

    protocol_frame_make(0x00,PROTOCOL_F_FUNCTION_1_0XA1,func,0x00,PROTOCOL_F_COMMSQR_00,protocol_reply_TXBuff,PROTOCOL_REPLY_TXBUFF_LEN,(void *)protocol_reply_payload,0x0C);
    Uart1_Send_DMA_StartBuff((uint8_t *)protocol_reply_TXBuff, (uint16_t)(sizeof(uint8_t) * 12));
}