[研电赛技术支持] GD32的485指令发送和回复数据转发

[复制链接]
1228|0
磨砂 发表于 2025-9-9 11:50 | 显示全部楼层 |阅读模式
RS-485总线是一种串行通信标准,支持多点通信,传输距离远、抗干扰能力强,常用于工业自动化和楼宇控制。我们在用GD32做项目的时候经常会碰到连接各类485传感器的情况。GD32和485连接一般需要3个脚,TX、RX、控制脚。以GD32的串口2为例,串口2接485电路。将串口2接收到的数据发送到串口1。串口1发送指令后串口2就会发送485指令,然后将串口2接收到的数据发送到串口1上,方便调试。
  ![在这里插入图片描述](#pic_center)

图中左边给串口1发送指令sh20test。右边可以显示串口2发送的数据。然后串口2设置了定时发送数据,串口1每条数据都可以收到。


以下是串口2的h文件
#ifndef USART2_H_
#define USART2_H_
#include “gd32f30x.h”

#define U2_485_DR GPIO_PIN_7
#define U2_485_Recedata gpio_bit_reset(GPIOB, GPIO_PIN_7);
#define U2_485_trandata gpio_bit_set(GPIOB, GPIO_PIN_7)
extern uint8_t sh20test_flag;

void init_usart2(uint32_t baudRate);
void usart2_send_byte(uint8_t byte);
void usart2_send_bytes(uint8_t *bytes,int len);
void usart2_send_string(char *string);
#endif

以下是串口2的C文件

#include "usart2.h"
#include "Sys_Config.h"
#if MD_USD_SALVE
#include "MDS_RTU_Serial.h"
#else
#include "MDM_RTU_Serial.h"
#include "MD_RTU_SysInterface.h"
#include "MDM_RTU_Fun.h"
#endif

extern uint8_t sh20test_flag=0;
#define USART2_RX_BUF_SIZE  128  // 串口2接收缓冲区大小
#define HEX_STR_BUF_SIZE    384  // 十六进制字符串缓冲区大小(每个字节转2个字符+空格)

uint8_t usart2_rx_buf[USART2_RX_BUF_SIZE];  // 串口2接收缓冲区
uint16_t usart2_rx_len = 0;                 // 串口2接收数据长度
uint8_t usart2_rx_complete = 0;             // 串口2接收完成标志
void usart1_send_hex_data(uint8_t *data, uint16_t len);
void hex_to_string(uint8_t *hex_buf, uint16_t hex_len, char *str_buf);
void usart2_send_hex(uint8_t *hex_buf, uint16_t len);

//uint8_t send_hex_485_memsdata[] = {0x01,0x03,0x00,0x04,0x00,0x01,0xC5,0xCB};  //MEMS传感器指令
uint8_t send_hex_485_sh20tdata[] = {0x01, 0x04, 0x00, 0x01, 0x00, 0x01, 0x60 ,0x0A};  //Sh20温度指令

void RS485RWConvInit(void)
{
        //收发引脚配置
        rcu_periph_clock_enable(RCU_GPIOB);       
        gpio_init(GPIOB,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,U2_485_DR);       
        gpio_bit_reset(GPIOB,U2_485_DR);
}

//串口1配置
void init_usart2(uint32_t baudRate)
{
        /* Enable GPIO clock */
        rcu_periph_clock_enable(RCU_USART2);
        rcu_periph_clock_enable(RCU_GPIOB);       
        gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10);//
    gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ,GPIO_PIN_11);//
               
        usart_baudrate_set(USART2,baudRate);
        usart_word_length_set(USART2,USART_WL_8BIT);
        usart_stop_bit_set(USART2,USART_STB_1BIT);
        usart_parity_config(USART2,USART_PM_NONE);
        usart_hardware_flow_cts_config(USART2,USART_CTS_DISABLE);
        usart_hardware_flow_rts_config(USART2,USART_RTS_DISABLE);
        usart_transmit_config(USART2,USART_TRANSMIT_ENABLE);
        usart_receive_config(USART2,USART_RECEIVE_ENABLE);       
                /* Configure USARTz */
        usart_interrupt_enable(USART2,USART_INT_RBNE);
        nvic_irq_enable(USART2_IRQn,0,0);
        usart_enable(USART2);
       
        RS485RWConvInit();
}
void usart2_send_byte(uint8_t byte)
{
        while(usart_flag_get(USART2,USART_FLAG_TC )==RESET);       
        usart_data_transmit(USART2,byte);
        while(usart_flag_get(USART2,USART_FLAG_TC )==RESET);       
}
void usart2_send_bytes(uint8_t *bytes,int len)
{
        int i;
        for(i=0;i<len;i++){
                usart2_send_byte(bytes);
        }
}

void usart2_send_string(char *string)
{
        while(*string)
        {
                usart2_send_byte(*string++);
        }   
}

void usart2_485run()
{
        if(sh20test_flag==1)
        {
                U2_485_trandata;
                usart2_send_hex(send_hex_485_sh20tdata,8);
                sh20test_flag=0;
                U2_485_Recedata;
        }
       
                 if(usart2_rx_complete)
        {
            //usart1_send_string("收到数据:");           
            // 将十六进制数据以字符串形式发送到串口1
            usart1_send_hex_data(usart2_rx_buf, usart2_rx_len);                 
            // 重置接收缓冲区和标志
            memset(usart2_rx_buf, 0, USART2_RX_BUF_SIZE);
            usart2_rx_len = 0;
            usart2_rx_complete = 0;         
            usart_interrupt_enable(USART2, USART_INT_RBNE);
        }
        }

// 十六进制数据转字符串(如0x1A转为"1A ")
void hex_to_string(uint8_t *hex_buf, uint16_t hex_len, char *str_buf)
{
    if(hex_buf == NULL || str_buf == NULL || hex_len == 0)
        return;

    const char hex_digits[] = "0123456789ABCDEF";
    uint16_t str_idx = 0;

    for(uint16_t i = 0; i < hex_len && str_idx < HEX_STR_BUF_SIZE - 3; i++)
    {
        // 高4位
        str_buf[str_idx++] = hex_digits[(hex_buf >> 4) & 0x0F];
        // 低4位
        str_buf[str_idx++] = hex_digits[hex_buf & 0x0F];
        // 空格分隔
        str_buf[str_idx++] = ' ';
    }
    // 字符串结束符
    str_buf[str_idx] = '\0';
}

// 将十六进制数据转换为字符串形式发送
void usart1_send_hex_data(uint8_t *data, uint16_t len)
{
    if(data == NULL || len == 0)
        return;

    char hex_str[HEX_STR_BUF_SIZE];
    hex_to_string(data, len, hex_str);
    usart1_send_string(hex_str);
}


void usart2_send_hex(uint8_t *hex_buf, uint16_t len)
{
    if (hex_buf == NULL || len == 0)
        return; // 空指针或长度为0时直接返回,避免错误

    for (uint16_t i = 0; i < len; i++)
    {
        // 等待发送缓冲区为空(TBE:Transmit Buffer Empty)
        while (RESET == usart_flag_get(USART2, USART_FLAG_TBE));

        // 发送1字节16进制数据(直接写入硬件发送寄存器)
        usart_data_transmit(USART2, hex_buf);
    }
    // 可选:等待最后1字节发送完成(TC:Transmission Complete)
    while (RESET == usart_flag_get(USART2, USART_FLAG_TC));
}

void USART2_IRQHandler(void)
{
        uint8_t data;

    // 接收非空中断
    if(usart_interrupt_flag_get(USART2, USART_INT_FLAG_RBNE) != RESET)
    {
        // 读取接收的数据
        data = usart_data_receive(USART2);

        // 检查缓冲区是否已满
        if(usart2_rx_len < USART2_RX_BUF_SIZE)
        {
            usart2_rx_buf[usart2_rx_len++] = data;

            // 接收完成条件: 接收到10个字节或检测到0xAA作为结束符
            // 可根据实际需求修改
            if(usart2_rx_len >= 7 || data == 0xAA)
            {
                usart2_rx_complete = 1;
                // 暂时关闭接收中断, 避免数据覆盖
                usart_interrupt_disable(USART2, USART_INT_RBNE);
            }
        }
        else
        {
            // 缓冲区已满, 置位完成标志
            usart2_rx_complete = 1;
            usart_interrupt_disable(USART2, USART_INT_RBNE);
        }
        usart_interrupt_flag_clear(USART2, USART_INT_FLAG_RBNE);
    }
}


具体的实现可以看下下面的链接
https://download.csdn.net/download/c781918946/91888414
————————————————
版权声明:本文为CSDN博主「-黑起-」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/c781918946/article/details/151262652

您需要登录后才可以回帖 登录 | 注册

本版积分规则

121

主题

4363

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部