RS485

#ifndef __RS485_H
#define __RS485_H    
#include "sys.h"

#include "stdio.h"    

#define SLAVE_ADDR  0x01
#define RX_BUF_SIZE 64
#define RS485_TX_EN()   GPIO_SetBits(GPIOB, GPIO_Pin_7)
#define RS485_RX_EN()   GPIO_ResetBits(GPIOB, GPIO_Pin_7)

void UART5_RS485_Init(uint32_t baud);

void RS485_Send(uint8_t *buf, uint16_t len);

void Modbus_Slave_Poll(void);

extern uint16_t Modbus_CRC16(uint8_t *buf, uint16_t len);


extern volatile uint8_t rx_buf[RX_BUF_SIZE];
extern volatile uint8_t rx_len ;
extern uint16_t HoldingReg[10];

#endif 

 

 

#include "RS485.h"
#include "sys.h"



uint16_t Modbus_CRC16(uint8_t *buf, uint16_t len);

volatile uint8_t rx_buf[RX_BUF_SIZE];
volatile uint8_t rx_len = 0;
uint16_t HoldingReg[10] = {
    3300,   // 40001:电压 mV
    123,    // 40002:示例数据
};


void UART5_IRQHandler(void)
{
    if(USART_GetITStatus(UART5, USART_IT_RXNE))
    {
        if(rx_len < RX_BUF_SIZE)
            rx_buf[rx_len++] = USART_ReceiveData(UART5);
    }
}


void UART5_RS485_Init(uint32_t baud)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB2PeriphClockCmd(
        RCC_APB2Periph_GPIOB |
        RCC_APB2Periph_GPIOC |
        RCC_APB2Periph_GPIOD |
        RCC_APB2Periph_AFIO, ENABLE);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);

    /* TX PC12 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    /* RX PD2 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    /* DE PB7 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    RS485_RX_EN();

    USART_InitStructure.USART_BaudRate = baud;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

    USART_Init(UART5, &USART_InitStructure);
    USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);
    USART_Cmd(UART5, ENABLE);

    NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

void RS485_Send(uint8_t *buf, uint16_t len)
{
    RS485_TX_EN();
    for(uint16_t i = 0; i < len; i++)
    {
        USART_SendData(UART5, buf[i]);
        while(USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET);
    }
    while(USART_GetFlagStatus(UART5, USART_FLAG_TC) == RESET);
    RS485_RX_EN();
}

uint16_t Modbus_CRC16(uint8_t *buf, uint16_t len)
{
    uint16_t crc = 0xFFFF;
    for(uint16_t i = 0; i < len; i++)
    {
        crc ^= buf[i];
        for(uint8_t j = 0; j < 8; j++)
        {
            if(crc & 1) crc = (crc >> 1) ^ 0xA001;
            else crc >>= 1;
        }
    }
    return crc;
}


void Modbus_Slave_Poll(void)
{
    if(rx_len < 8) return;

    uint16_t crc_calc = Modbus_CRC16((uint8_t*)rx_buf, rx_len-2);
    uint16_t crc_recv = rx_buf[rx_len-2] | (rx_buf[rx_len-1]<<8);

    if(crc_calc != crc_recv) goto clear;
    if(rx_buf[0] != SLAVE_ADDR) goto clear;

    if(rx_buf[1] == 0x03)
    {
        uint16_t start = (rx_buf[2]<<8) | rx_buf[3];
        uint16_t num   = (rx_buf[4]<<8) | rx_buf[5];

        uint8_t tx[64], idx = 0;
        tx[idx++] = SLAVE_ADDR;
        tx[idx++] = 0x03;
        tx[idx++] = num * 2;

        for(uint16_t i=0;i<num;i++)
        {
            tx[idx++] = HoldingReg[start+i] >> 8;
            tx[idx++] = HoldingReg[start+i] & 0xFF;
        }

        uint16_t crc = Modbus_CRC16(tx, idx);
        tx[idx++] = crc & 0xFF;
        tx[idx++] = crc >> 8;

        RS485_Send(tx, idx);
    }

clear:
    rx_len = 0;
}

 

posted @ 2026-01-17 09:17  多多和羊羊  阅读(3)  评论(0)    收藏  举报