没志青年
发布于 2025-08-02 / 16 阅读
0

串口数据处理

单缓冲区 + 接收中断

单缓冲区 + 空闲中断

双缓冲区 + 空闲中断

环形缓冲区 + 空闲中断

自定义串口协议

串口数据解析:

/**
 * 计算数据校验和
 * 从帧类型开始(包括帧类型),累加到最后一个数据,后取低8位
 */
uint8_t mid_tp_check_sum(uint8_t *p_data, uint8_t length)
{
    uint8_t check_sum = 0;
    for (uint8_t i = 0; i < length; i++)
    {
        check_sum += p_data[i];
    }
    return check_sum;
}


void mid_tp_state_machine(void)
{
    uint8_t rec_buffer = 0, check_sum = 0;
    static mid_tp_frame_format_t rec_frame;
    static uint32_t timeout = 0;
    static uint8_t count = 0;
    if (CircularBufferGetDataSize(uart_receive_buffer) > 0)
    {
        // 刷新计时器
        timeout = HAL_GetTick();
        CircularBufferPop(uart_receive_buffer, 1, &rec_buffer);
        switch (step)
        {
        case 0: // 解析帧头
            if (rec_buffer == MID_TP_FRAME_HEAD_F)
            {
                step = 1;
            }
            break;
        case 1: // 解析帧头
            if (rec_buffer == MID_TP_FRAME_HEAD_S)
            {
                step = 2;
            }
            else
            {
                step = 0;
            }
            break;
        case 2: // 解析帧类型
            rec_frame.frame_type = rec_buffer;
            if ((rec_buffer == MID_TP_FRAME_TYPE_SET) || (rec_buffer == MID_TP_FRAME_TYPE_GET))
            {
                count = 0;
                step = 3;
            }
            else
            {
                printf("rec frame_type error\r\n");
                memset(&rec_frame, 0, sizeof(mid_tp_frame_format_t));
                step = 0;
            }
            break;
        case 3: // 解析数据长度
            rec_frame.frame_length = rec_buffer;
            step = 4;
            break;
        case 4: // 解析数据
            rec_frame.frame_payload[count++] = rec_buffer;
            // printf("frame_payload[%d] = 0x%x\r\n", count, rec_buffer);
            if (count == rec_frame.frame_length)
            {
                step = 5;
            }
            // printf("count = %d, rec_frame.frame_length = %d\r\n", count, rec_frame.frame_length);
            break;
        case 5: // 解析校验和
            rec_frame.frame_check_sum = rec_buffer;
            check_sum = mid_tp_check_sum((uint8_t *)&rec_frame.frame_type, rec_frame.frame_length + 2);
            if (rec_frame.frame_check_sum == check_sum) // 校验成功
            {
                switch (rec_frame.frame_type)
                {
                case MID_TP_FRAME_TYPE_SET: // 设置
                    switch (rec_frame.frame_payload[0])
                    {
                    case MID_TP_DATA_FUNC_VOLTAGE:
                        printf("set voltage = %d\r\n", rec_frame.frame_payload[1] << 8 | rec_frame.frame_payload[2]);
                        g_commu_data.target_voltage = rec_frame.frame_payload[1] << 8 | rec_frame.frame_payload[2];
                        mid_tp_ack(MID_TP_FRAME_TYPE_ACK, MID_TP_DATA_FUNC_VOLTAGE);
                        break;
                    case MID_TP_DATA_FUNC_CURRENT:
                        printf("set current = %d\r\n", rec_frame.frame_payload[1] << 8 | rec_frame.frame_payload[2]);
                        g_commu_data.target_current = rec_frame.frame_payload[1] << 8 | rec_frame.frame_payload[2];
                        mid_tp_ack(MID_TP_FRAME_TYPE_ACK, MID_TP_DATA_FUNC_CURRENT);
                        break;
                    default:
                        break;
                    }
                    break;
                case MID_TP_FRAME_TYPE_GET: // 获取
                    switch (rec_frame.frame_payload[0])
                    {
                    case MID_TP_DATA_FUNC_STATUS:
                        mid_tp_ack(MID_TP_FRAME_TYPE_GET, MID_TP_DATA_FUNC_STATUS);
                        break;
                    default:
                        break;
                    }
                    break;
                default:
                    break;
                }
            }
            else
            {
                printf("rec frame_check_sum error, rec_frame.frame_check_sum = 0x%x, check_sum = 0x%x\r\n", rec_frame.frame_check_sum, check_sum);
            }
            memset(&rec_frame, 0, sizeof(mid_tp_frame_format_t));
            step = 0;
            break;
        }
    }
    if (step != 0) // 超时检测,比如收到了开头或是中间部分,但是后续的部分没收到
    {
        if (HAL_GetTick() - timeout > 500)
        {
            printf("timeout current step = %d\r\n", step);
            memset(&rec_frame, 0, sizeof(mid_tp_frame_format_t));
            step = 0;
        }
    }
}

发送数据:

static void mid_tp_ack(uint8_t frame_type, uint8_t data_func)
{
    uint8_t send_buffer[20] = {0};
    send_buffer[0] = 0xA5;
    send_buffer[1] = 0x5A;
    send_buffer[2] = MID_TP_FRAME_TYPE_ACK;
    send_buffer[3] = 3;
    send_buffer[4] = data_func;
    switch (data_func)
    {
    case MID_TP_DATA_FUNC_VOLTAGE: // 发送电压
        send_buffer[5] = g_commu_data.target_voltage >> 8;
        send_buffer[6] = g_commu_data.target_voltage & 0xFF;
        send_buffer[7] = mid_tp_check_sum(send_buffer + 2, 5);
        break;
    case MID_TP_DATA_FUNC_CURRENT: // 发送电流
        send_buffer[5] = g_commu_data.target_current >> 8;
        send_buffer[6] = g_commu_data.target_current & 0xFF;
        send_buffer[7] = mid_tp_check_sum(send_buffer + 2, 5);
        break;
    case MID_TP_DATA_FUNC_STATUS: // 发送状态
        send_buffer[3] = 7;
        send_buffer[5] = MID_TP_STA_MODE_CV; // 模式
        send_buffer[6] = g_commu_data.current_voltage >> 8;
        send_buffer[7] = g_commu_data.current_voltage & 0xFF;
        send_buffer[8] = g_commu_data.current_current >> 8;
        send_buffer[9] = g_commu_data.current_current & 0xFF;
        send_buffer[10] = MID_TP_STA_ERROR_NONE; // 错误信息
        send_buffer[11] = mid_tp_check_sum(send_buffer + 2, 9);
        break;
    default:
        break;
    }
    HAL_UART_Transmit(&huart3, send_buffer, send_buffer[3] + 5, 0xFFFF);
}