基于GD32F4XX串口环形缓冲区,北斗2.1协议,RD模块数据解析代码

以下是基于GD32F4XX串口,使用sscanf函数、strstrstrcmp,并结合环形缓冲区在中断中写数据,主函数处理发送接收的代码示例:

串口初始化与环形缓冲区定义

c 复制代码
#include <gd32f4xx.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define BUF_SIZE 256 // 环形缓冲区大小

// 环形缓冲区结构体
typedef struct {
    uint8_t buffer[BUF_SIZE];
    uint16_t write_idx;
    uint16_t read_idx;
} RingBuffer;

RingBuffer rx_ring_buf;

// 初始化串口
void usart_init(uint32_t baudrate) {
    rcu_periph_clock_enable(RCU_USART0);
    rcu_periph_clock_enable(RCU_GPIOA);

    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);

    usart_deinit(USART0);
    usart_baudrate_config(USART0, baudrate);
    usart_word_length_config(USART0, USART_WL_8BIT);
    usart_stop_bit_config(USART0, USART_SBT_1BIT);
    usart_parity_config(USART0, USART_PM_NONE);
    usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);
    usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);

    // 开启中断
    usart_interrupt_enable(USART0, USART_INT_RBNE);
    nvic_priority_group_config(NVIC_PRIORITY_GROUP_2);
    nvic_irq_enable(USART0_IRQn, 0, 0);
}

// 初始化环形缓冲区
void ring_buffer_init(RingBuffer *ring_buf) {
    ring_buf->write_idx = 0;
    ring_buf->read_idx = 0;
}

// 写入环形缓冲区
void ring_buffer_write(RingBuffer *ring_buf, uint8_t data) {
    ring_buf->buffer[ring_buf->write_idx] = data;
    ring_buf->write_idx = (ring_buf->write_idx + 1) % BUF_SIZE;
}

// 从环形缓冲区读取数据
uint8_t ring_buffer_read(RingBuffer *ring_buf) {
    uint8_t data = ring_buf->buffer[ring_buf->read_idx];
    ring_buf->read_idx = (ring_buf->read_idx + 1) % BUF_SIZE;
    return data;
}

// 环形缓冲区是否为空
uint8_t ring_buffer_is_empty(RingBuffer *ring_buf) {
    return (ring_buf->read_idx == ring_buf->write_idx);
}

串口接收中断处理

c 复制代码
// 串口中断服务函数
void USART0_IRQHandler(void) {
    if (usart_flag_get(USART0, USART_FLAG_RBNE) != RESET) {
        uint8_t received_data = usart_data_receive(USART0);
        ring_buffer_write(&rx_ring_buf, received_data);
    }
}

北斗协议解析与发送

c 复制代码
// 北斗协议解析函数
void parse_bds_sentence() {
    static char sentence_buf[256];
    static uint8_t sentence_idx = 0;
    char *token;

    while (!ring_buffer_is_empty(&rx_ring_buf)) {
        uint8_t data = ring_buffer_read(&rx_ring_buf);
        sentence_buf[sentence_idx++] = data;

        if (data == '\n' || sentence_idx >= sizeof(sentence_buf)) {
            sentence_buf[sentence_idx] = '\0';
            sentence_idx = 0;

            // 找到开头的$符号
            char *start_pos = strstr(sentence_buf, "$");
            if (start_pos) {
                // 提取指令关键字
                char command[16];
                sscanf(start_pos, "$%[^,*]", command);

                // 判断指令类型并进行解析
                if (strcmp(command, "BDICI") == 0) {
                    parse_bds_card(start_pos);
                } else if (strcmp(command, "BDBSI") == 0) {
                    parse_bds_signal(start_pos);
                } else if (strcmp(command, "BDDWR") == 0) {
                    parse_bds_position(start_pos);
                } else if (strcmp(command, "BDTXR") == 0) {
                    parse_bds_message(start_pos);
                }
            }
        }
    }
}

// 解析北斗卡号
void parse_bds_card(char *sentence) {
    char card_number[16];
    sscanf(sentence, "$BDICI,%[^,]", card_number);
    printf("Beidou Card Number: %s\n", card_number);
}

// 解析信号状态
void parse_bds_signal(char *sentence) {
    char signal_values[50];
    sscanf(sentence, "$BDBSI,%4s,%4s,%[^,*]", NULL, NULL, signal_values);
    printf("Signal Values: %s\n", signal_values);
}

// 解析定位信息
void parse_bds_position(char *sentence) {
    char time[16], latitude[16], longitude[16], altitude[16];
    sscanf(sentence, "$BDDWR,%*[^\r\n],%[^,],%[^,],%[^,],%[^,],%[^,],", time, latitude, longitude, altitude);
    printf("Position - Time: %s, Latitude: %s, Longitude: %s, Altitude: %s\n", time, latitude, longitude, altitude);
}

// 解析接收到的消息
void parse_bds_message(char *sentence) {
    char message_content[100];
    sscanf(sentence, "$BDTXR,%*[^,],%*[^,],%[^,]", message_content);
    printf("Received Message: %s\n", message_content);
}

主函数与发送功能

c 复制代码
//送 发北斗指令
void send_bds_sentence(const char *sentence) {
    uint8_t len = strlen(sentence);
    for (uint8_t i = 0; i < len; i++) {
        usart_data_transmit(USART0, sentence[i]);
        while (usart_flag_get(USART0, USART_FLAG_TBE) == RESET);
    }
}

// 主函数
int main(void) {
    rcu_clock_prescale_config(RCU_APB2_RTCPrescale, 1);
    rcu_clock_configuration();
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_USART0);
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_AF);

    // 初始化串口
    usart_init(9600);

    // 初始化环形缓冲区
    ring_buffer_init(&rx_ring_buf);

    while (1) {
        // 解析接收到的数据
        parse_bds_sentence();

        // 发送北斗指令示例
        static uint8_t send_flag = 0;
        send_flag++;
        if (send_flag > 100) { // 模拟发送频率控制
            send_flag = 0;
            // 发送读取卡号指令
            send_bds_sentence("$CCICA,0,00*7B\r\n");
            delay_1ms(100); // 简单延时函数
        }
    }
}

异或校验字节计算

c 复制代码
// 计算异或校验字节
char calculate_checksum(const char *sentence) {
    char *start = strstr(sentence, "$") + 1;
    char *end = strstr(start, "*");
    if (!end) return 0x00;

    uint8_t checksum = 0;
    while (start < end) {
        checksum ^= *start++;
    }
    return checksum;
}

说明

  1. 本代码示例适用于GD32F4XX系列MCU,需要根据具体型号调整引脚和时钟配置。
  2. 环形缓冲区大小可以根据实际应用需求调整。
  3. sscanf函数用于解析北斗协议中的字段,strstrstrcmp用于指令识别。
  4. 在实际应用中,需要添加有效的延时函数delay_1ms和错误处理机制。
  5. 异或校验字节在发送指令时需要正确计算,可调用calculate_checksum函数。
  6. 根据需求,可以扩展解析和发送更多类型的北斗短报文协议指令。
相关推荐
数据智能老司机3 分钟前
构建一个 DeepSeek 模型——通过键值缓存(Key-Value Cache, KV Cache)解决推理瓶颈
架构·llm·deepseek
王哈哈^_^16 分钟前
【完整源码+数据集】草莓数据集,yolov8草莓成熟度检测数据集 3207 张,草莓成熟度数据集,目标检测草莓识别算法系统实战教程
人工智能·算法·yolo·目标检测·计算机视觉·视觉检测·毕业设计
油泼辣子多加1 小时前
【实战】自然语言处理--长文本分类(3)HAN算法
算法·自然语言处理·分类
码界奇点1 小时前
解密AI语言模型从原理到应用的全景解析
人工智能·语言模型·自然语言处理·架构
Shinom1ya_1 小时前
算法 day 46
数据结构·算法
Msshu1231 小时前
PD快充诱骗芯片 XSP15 支持获取快充电压可与外部MCU共用D+D-网络与电脑传输数据
单片机·嵌入式硬件
brave and determined2 小时前
MCU学习Day24——STM32G030多路ADC DMA采集深度解析:完全可配置序列器与不完全可配置序列器的陷阱与抉择
stm32·单片机·嵌入式硬件·dma·adc·hal·多通道采集
夏鹏今天学习了吗2 小时前
【LeetCode热题100(64/100)】搜索旋转排序数组
算法·leetcode·职场和发展
d111111111d2 小时前
通过操作地址,来进行STM32的写入GPIO端口值
stm32·单片机·嵌入式硬件
奔跑吧邓邓子2 小时前
【C语言实战(77)】STM32实战:解锁传感器数据采集的C语言奥秘
c语言·stm32·开发实战·传感器数据采集