【测评】ICeasy商城新出的雷达CEM5811,与vw553通讯

分享作者:F888
作者昵称:我爱小易
评测品牌:萤火工场
评测型号:CEM5881-M11
发布时间:2026-04-16 15:23:09
0
概要
这次实现的重点不是网页界面本身,而是把雷达模块输出的串口数据稳定接收下来,完成解析后,再通过 HTTP 接口送到网页端显示。
开源口碑分享内容

1. 串口接收雷达原始数据

1.1 硬件配置

串口端口:UART2

波特率:115200

数据格式v=0.25 km/h, str=1748

1.2 初始化代码

    int radar_uart_init(uint32_t uart_port, uint32_t baudrate) {
    g_radar_raw_data[0] = '\0';
    g_radar_temp_data[0] = '\0';
    g_data_ready = 0;
    g_rx_index = 0;

    uart_driver_init();
    uart_config(uart_port, baudrate, 0, false, false);
    usart_interrupt_enable((uint32_t)uart_port, USART_INT_RBNE);
    uart_irq_callback_register(uart_port, radar_uart_rx_callback);

    printf("Radar UART initialized on port=%d, baud=%lu\n", uart_port, baudrate);
    return 0;
}

1.3 中断接收回调

static void radar_uart_rx_callback(uint32_t uart_port) {
    char ch;

    while (usart_flag_get((uint32_t)uart_port, USART_FLAG_RBNE) != RESET) {
        ch = (char)usart_data_receive((uint32_t)uart_port);

        if (ch == '\n' || ch == '\r') {
            if (g_rx_index > 0) {
                g_rx_buffer[g_rx_index] = '\0';
                radar_publish_frame(g_rx_buffer);
                g_rx_index = 0;
                g_rx_buffer[0] = '\0';
            }
            continue;
        }

        if (g_rx_index < sizeof(g_rx_buffer) - 1) {
            g_rx_buffer[g_rx_index++] = ch;
            g_rx_buffer[g_rx_index] = '\0';
        } else {
            printf("RADAR_RX overflow, dropping frame\n");
            g_rx_index = 0;
            g_rx_buffer[0] = '\0';
        }
    }
}

2. 数据帧解析

2.1 数据格式说明

雷达输出数据格式:

  v=0.25 km/h, str=1748

v:目标速度,单位km/h

str:信号强度

2.2 数据结构定义

typedef struct {
    float velocity;          // 速度值(浮点)
    int32_t velocity_x100;   // 速度值放大100倍(整数)
    int16_t signal_str;      // 信号强度
    bool valid;              // 数据有效性标志
    uint32_t timestamp;      // 时间戳
} radar_data_t;

2.3 解析函数实现

bool radar_parse_line(const char* line, radar_data_t* data) {
    float velocity = 0.0f;
    long signal = 0;
    char* signal_end = NULL;
    const char* p = line;

    if ((line == NULL) || (data == NULL)) {
        return false;
    }

    // 校验前缀 v=
    if (!((*p == 'v') || (*p == 'V')) || (*(p + 1) != '=')) {
        return false;
    }

    p += 2;
    if (!parse_signed_fixed_2(p, &velocity, &p)) {
        return false;
    }

    // 校验单位 km/h
    while (*p == ' ') {
        p++;
    }
    if (strncmp(p, "km/h", 4) != 0) {
        return false;
    }
    p += 4;

    // 跳过分隔符
    while (*p == ' ' || *p == ',') {
        p++;
    }

    // 校验 str=
    if (!((p[0] == 's' || p[0] == 'S') && (p[1] == 't' || p[1] == 'T') &&
          (p[2] == 'r' || p[2] == 'R') && p[3] == '=')) {
        return false;
    }
    p += 4;

    // 解析信号强度
    signal = strtol(p, &signal_end, 10);
    if (signal_end == p) {
        return false;
    }

    // 保存解析结果
    data->velocity = velocity;
    data->velocity_x100 = (int32_t)(velocity * 100.0f);
    data->signal_str = (int16_t)signal;
    data->valid = true;
    data->timestamp = sys_current_time_get();
    return true;
}

3. 数据缓存管理

3.1 双缓冲机制

采用双缓冲设计避免中断与HTTP访问冲突:

写入缓冲区:g_radar_temp_data(UART中断写入)

读取缓冲区:g_radar_raw_data(HTTP接口读取)

结构化数据:g_latest_radar_data

3.2 数据获取接口

void radar_get_raw_data(char* buffer, size_t buffer_size) {
    if (buffer == NULL || buffer_size == 0) {
        return;
    }

    if (g_data_ready) {
        strncpy(g_radar_raw_data, g_radar_temp_data, sizeof(g_radar_raw_data) - 1);
        g_radar_raw_data[sizeof(g_radar_raw_data) - 1] = '\0';
        g_data_ready = 0;
    }

    strncpy(buffer, g_radar_raw_data, buffer_size - 1);
    buffer[buffer_size - 1] = '\0';
}

bool radar_get_latest_data(radar_data_t* data) {
    if (data == NULL || !g_latest_radar_data.valid) {
        return false;
    }

    *data = g_latest_radar_data;
    return true;
}

4. HTTP接口设计

4.1 API接口

URL:/api/radar

方法:GET

返回格式:JSON

4.2 接口实现

if (strncmp(buffer, "GET /api/radar", 14) == 0) {
    printf("[HTTP] Processing radar API\n");
    char radar_json[320];
    char raw_data[256] = {0};
    radar_data_t radar_data = {0};
    uint8_t has_data = 0;
    char velocity_text[24];
    char threshold_text[24];

    radar_get_raw_data(raw_data, sizeof(raw_data));
    has_data = radar_get_latest_data(&radar_data) ? 1 : 0;

    if (raw_data[0] == '\0') {
        strncpy(raw_data, "无数据", sizeof(raw_data) - 1);
        raw_data[sizeof(raw_data) - 1] = '\0';
    }

    format_fixed_2(velocity_text, sizeof(velocity_text), has_data ? radar_data.velocity_x100 : 0);
    format_fixed_2(threshold_text, sizeof(threshold_text), threshold_to_x100(g_radar_speed_threshold));

    if (g_auto_mode) {
        snprintf(radar_json, sizeof(radar_json),
                 "{\"raw_data\":\"%s\",\"velocity\":%s,\"str\":%d,\"valid\":%s,\"led_status\":\"%s\",\"threshold\":%s,\"mode\":\"%s\"}",
                 raw_data,
                 velocity_text,
                 has_data ? radar_data.signal_str : 0,
                 has_data ? "true" : "false",
                 led_is_on() ? "on" : "off",
                 threshold_text,
                 get_mode_text());
    } else {
        snprintf(radar_json, sizeof(radar_json),
                 "{\"raw_data\":\"%s\",\"velocity\":%s,\"str\":%d,\"valid\":%s,\"led_status\":\"%s\",\"mode\":\"%s\"}",
                 raw_data,
                 velocity_text,
                 has_data ? radar_data.signal_str : 0,
                 has_data ? "true" : "false",
                 led_is_on() ? "on" : "off",
                 get_mode_text());
    }

    send_response(conn_fd, "application/json", radar_json);
    close(conn_fd);
    return;
}

5. 网页端显示

具体实现思路可以参考之前我写的另外一篇帖子: 帖子

6. 结果

源代码可以群里联系这里不能上传C文件

全部评论
暂无评论
0/144