瑞萨单片机论坛
直播中

mameng

13年用户 377经验值
擅长:嵌入式技术
私信 关注
[经验]

【CPKCOR-RA8D1】基于CPKCOR-RA8D1的GNSS RTK系统设计

  GNSS RTK(Global Navigation Satellite System Real-Time Kinematic,全球导航卫星系统实时动态差分)是一种高精度定位技术,通过基站与流动站的协同工作,可实现厘米级甚至毫米级的实时定位精度,广泛应用于测绘、精准农业、自动驾驶、工程施工等领域 。 基于瑞萨RA8D1微控制器设计GNSS RTK接收机,依靠瑞萨RA8D1单片机的高性能处理能力、丰富外设接口及低功耗特性,搭配GNSS模组(如UM982)实现实时动态差分定位。
  
一、系统设计目标
    支持RTK差分定位(固定解精度达厘米级)。实现基站与流动站数据交互(如RTCM数据传输)。支持RS232,RS485,CAN,RJ45多种输出,支持ROS系统。具备高效数据处理、存储及外设扩展能力。满足低功耗、小型化及工业级可靠性要求。
二、硬件架构设计
      设计框图:


1. 核心控制器:CPKCOR-RA8D1基于瑞萨RA8D1高性能单片机。
      核心优势:基于ARM CortexM85内核(最高240MHz主频),支持单精度浮点运算(FPU),适合RTK解算辅助处理;内置丰富外设(UART、SPI、Ethernet、CAN、ADC等),满足多模组互联需求;支持安全加密(TrustZoneM),适合户外设备安全防护。支持单 / 双精度 FPU 和 DSP 指令,可辅助 RTK 解算中的浮点运算(如载波相位差分、基线解算),可以快速解析复杂的 RTCM3.x 帧结构。RA 系列内置多达 8 个 UART 接口,支持硬件流控(RTS/CTS)和 IrDA 模式,可直接通过外部电平转换芯片(如 MAX232/MAX485)实现 RS232/RS485 通信。UART 波特率最高可达 3Mbps,满足 RTK 差分数据(如 RTCM3.2)的高速传输需求;支持中断 / DMA 接收,避免数据丢包(关键于 RTK 固定解稳定性)。内置 2-6 个 CAN FD 控制器(兼容传统 CAN 2.0),支持最高 8Mbps 速率,具备错误检测、自动重传功能,适合工业环境下的多节点通信(如车载 RTK 与自动驾驶系统互联)。内置 10/100Mbps 以太网 MAC+PHY,支持 IEEE 1588 PTP 精确时间同步,可通过 TCP/UDP 协议传输海量差分数据(如基站向多个流动站广播 RTCM)。
2. GNSS模组接口(以UM982为例)
   通信接口:   主UART(如UART0):连接UM982的TX/RX,传输原始观测数据(如UBX格式)和配置指令,波特率设为115200bps。  PPS同步:UM982的PPS(秒脉冲)输出连接RA8D1的GPIO(如P100),用于时间同步,确保基站与流动站时钟对齐 (  RTK解算关键)。  
  天线接口:UM982外接高增益GNSS天线(支持多星座:GPS、北斗、GLONASS、Galileo),通过SMA接口连接,需匹配低噪声放大器(LNA)减少信号损耗。
  3. 差分数据传输模块
基站→流动站数据链路:  
   无线传输:若为移动场景,通过RA8D1的UART1连接4G/5G模组(如移远EC20)或LoRa模组(如Semtech SX1276),传输RTCM3.2差分数据(波特率9600115200bps)。  
   有线传输:固定场景可通过RA8D1的Ethernet接口(内置MAC+PHY)连接局域网,基于TCP/UDP协议传输差分数据。  
接口保护:在UART/Ethernet接口处添加TVS管(如SMBJ6.5A)和ESD保护电路,增强户外抗干扰能力。

4. 存储模块
数据记录:通过SPI1连接NOR Flash(W25Q128)存储配置参数、日志及历史定位数据;或通过SDIO接口连接SD卡,存储大容量原始观测数据(供后处理分析)。  
  实时时钟(RTC):外接低功耗RTC芯片,在GNSS信号丢失时提供时间基准,通过I2C接口与RA8D1通信。
5. 电源与外围电路
宽压输入:支持9-36V直流输入(适应车载/工业电源),通过DC-DC转换器(如LM2596)转换为5V,再经LDO输出3.3V给RA8D1、GNSS模组等。  
指示灯:通过RA8D1的GPIO控制LED,指示系统供电、GNSS信号强度、RTK固定解状态(如固定解时绿灯常亮,浮点解时闪烁)。  


三、软件系统设计
1. 开发环境与底层驱动
开发工具:使用瑞萨e² studio IDE,基于FreeRTOS实时操作系统(RA8D1官方支持),实现多任务调度。  
外设驱动:  
   配置UART中断接收GNSS数据(UM982的UBX/RTCM帧),通过DMA减少CPU占用。  
   实现SPI/I2C驱动,控制Flash、RTC等外设。  
   开发网络驱动(Ethernet/LoRa/4G),封装TCP/UDP协议栈(如lwIP)用于差分数据传输。
  1. #include "hal_data.h"
  2. #include "FreeRTOS.h"
  3. #include "task.h"
  4. #include "queue.h"
  5. #include
  6. #include
  7. // 宏定义
  8. #define UART_GNSS_BAUDRATE     115200    // UM982通信波特率
  9. #define UART_DIFF_BAUDRATE     115200    // 差分数据传输波特率
  10. #define MAX_GNSS_BUF_LEN       512       // GNSS数据缓冲区大小
  11. #define RTK_FIXED_STATE        3         // 固定解状态码(参考UM982手册)
  12. #define PPS_GPIO_PORT          BSP_IO_PORT_01    // PPS信号引脚(示例)
  13. // UM982 UBX帧结构(简化)
  14. typedef struct {
  15.     uint8_t class;       // 消息类(如0x01=NAV)
  16.     uint8_t id;          // 消息ID(如0x02=POSLLH)
  17.     uint16_t len;        //  payload长度
  18.     uint8_t payload[256];// 数据载荷
  19.     uint16_t checksum;   // 校验和
  20. } ubx_frame_t;
  21. // RTK状态信息
  22. typedef struct {
  23.     uint8_t rtk_stat;    // 0=单点解, 1=浮点解, 3=固定解
  24.     double lat;          // 纬度(度)
  25.     double lon;          // 经度(度)
  26.     double alt;          // 高程(米)
  27. } rtk_info_t;
  28. // 全局变量
  29. QueueHandle_t g_gnss_queue;       // GNSS数据队列
  30. rtk_info_t g_rtk_info = {0};      // RTK状态全局变量
  1. void hardware_init(void) {
  2.     // 初始化GPIO(PPS信号输入)
  3.     R_IOPORT_Open(&g_ioport_ctrl, g_ioport.p_cfg);
  4.     R_IOPORT_PinCfg(&g_ioport_ctrl, PPS_GPIO_PORT, IOPORT_CFG_PORT_DIRECTION_INPUT);
  5.     // 初始化GNSS UART(连接UM982)
  6.     g_uart0.p_api->open(g_uart0.p_ctrl, g_uart0.p_cfg);
  7.     g_uart0.p_api->baudSet(g_uart0.p_ctrl, UART_GNSS_BAUDRATE, NULL);
  8.     // 初始化差分数据UART(传输RTCM)
  9.     g_uart1.p_api->open(g_uart1.p_ctrl, g_uart1.p_cfg);
  10.     g_uart1.p_api->baudSet(g_uart1.p_ctrl, UART_DIFF_BAUDRATE, NULL);
  11.     // 创建FreeRTOS队列(用于传递GNSS数据)
  12.     g_gnss_queue = xQueueCreate(10, MAX_GNSS_BUF_LEN);
  13.     if (g_gnss_queue == NULL) {
  14.         // 队列创建失败处理
  15.         while(1);
  16.     }
  17. }

2. GNSS数据处理流程
数据解析:在FreeRTOS任务中解析UM982输出的UBX格式数据(如导航电文、原始伪距、载波相位),提取卫星信息、时间戳、位置初值。  
RTK解算辅助:  
   若作为基站:RA8D1接收UM982的原始数据,结合已知基站坐标生成RTCM3.2差分电文(如1005、1077帧),通过传输模块发送给流动站。  
   若作为流动站:接收基站RTCM数据,与本地UM982的观测数据融合,通过RA8D1的FPU加速差分算法(或调用UM982内置RTK解算功能,直接获取固定解结果)。  
解状态判断:解析UM982的RTK状态帧(如UBXNAVRTK),获取解类型(固定解/浮点解/单点解),通过LED或串口上报。
  1. // UART0中断回调(接收UM982输出的UBX/RTCM数据)
  2. void uart0_callback(uart_callback_args_t *p_args) {
  3.     static uint8_t gnss_buf[MAX_GNSS_BUF_LEN] = {0};
  4.     static uint16_t buf_idx = 0;
  5.     if (p_args->event == UART_EVENT_RX_CHAR) {
  6.         // 接收单字节数据
  7.         gnss_buf[buf_idx++] = (uint8_t)p_args->data;
  8.         // 缓冲区满或检测到UBX帧尾(0x1B)时,发送到队列
  9.         if (buf_idx >= MAX_GNSS_BUF_LEN || gnss_buf[buf_idx-1] == 0x1B) {
  10.             xQueueSendFromISR(g_gnss_queue, gnss_buf, NULL);
  11.             buf_idx = 0;
  12.             memset(gnss_buf, 0, MAX_GNSS_BUF_LEN);
  13.         }
  14.     }
  15. }
[code]// 校验UBX帧校验和
static bool ubx_checksum_valid(ubx_frame_t *frame) {
    uint8_t ck_a = 0, ck_b = 0;
    // 计算校验和(覆盖class、id、len、payload)
    ck_a += frame->class;
    ck_b += ck_a;
    ck_a += frame->id;
    ck_b += ck_a;
    ck_a += (frame->len >> 8) & 0xFF;
    ck_b += ck_a;
    ck_a += frame->len & 0xFF;
    ck_b += ck_a;
    for (int i=0; ilen; i++) {
        ck_a += frame->payload;
        ck_b += ck_a;
    }
    // 对比帧中校验和
    return (ck_a == (frame->checksum >> 8)) && (ck_b == (frame->checksum & 0xFF));
}

// 解析UBX-NAV-RTK帧(获取RTK状态)
static void parse_ubx_nav_rtk(uint8_t *data, uint16_t len) {
    if (len < 4) return; // 最小长度检查
    // RTK状态码位于payload第3字节(参考UM982手册)
    g_rtk_info.rtk_stat = data[3];
    // 打印状态(调试用)
    switch(g_rtk_info.rtk_stat) {
        case 0: printf("RTK状态:单点解\n"); break;
        case 1: printf("RTK状态:浮点解\n"); break;
        case 3: printf("RTK状态:固定解\n"); break;
        default: printf("RTK状态:未知\n");
    }
}

// 解析UBX-NAV-POSLLH帧(获取经纬度)
static void parse_ubx_nav_posllh(uint8_t *data, uint16_t len) {
    if (len < 28) return; // 确保数据完整
    // 纬度(1e-7度):payload[8-11]为int32_t
    int32_t lat_raw = *(int32_t*)(data + 8);
    g_rtk_info.lat = lat_raw / 1e7;
    // 经度(1e-7度):payload[12-15]
    int32_t lon_raw = *(int32_t*)(data + 12);
    g_rtk_info.lon = lon_raw / 1e7;
    // 高程(毫米):payload[20-23]
    int32_t alt_raw = *(int32_t*)(data + 20);
    g_rtk_info.alt = alt_raw / 1000.0;
    printf("位置:%.8f, %.8f, %.2f米\n", g_rtk_info.lat, g_rtk_info.lon, g_rtk_info.alt);
}

// 主解析函数
void parse_gnss_data(uint8_t *buf, uint16_t len) {
    ubx_frame_t frame;
    // 查找UBX帧头(0xB5, 0x62)
    for (int i=0; i
附件: 您需要登录才可以下载或查看附件。没有帐号?注册

更多回帖

×
20
完善资料,
赚取积分