带有RS485的STM32F4接口

时间:2018-12-07 10:28:40

标签: c stm32f4 rs485

我正在尝试使用RS485到TTL转换器到STM32f407VG的仪表读取数据。我的设备从设备ID是121,波特率是9600。我想读取holdingRegistersInputRegisters

我正在尝试FreeMODBUS RTU port for STM32 HAL library

我已将DI引脚连接到PA_2(Tx)R0引脚连接到PA_3(Rx)DE&RE引脚连接到GND。但是我没有任何数据。

这是我的代码:

#include "stm32f4xx_hal.h"
#include "cmsis_os.h"

#include "mb.h"
#include "mbport.h"

#define REG_INPUT_START 30005
#define REG_INPUT_NREGS 8

static USHORT usRegInputStart = REG_INPUT_START;
static USHORT usRegInputBuf[REG_INPUT_NREGS];

 void ModbusRTUTask(void const * argument)  
 { 
    /* ABCDEF */
   usRegInputBuf[0] = 11;
    usRegInputBuf[1] = 22;
    usRegInputBuf[2] = 33;
    usRegInputBuf[3] = 44;
    usRegInputBuf[4] = 55;
    usRegInputBuf[5] = 66;
    usRegInputBuf[6] = 77;
    usRegInputBuf[7] = 88;  

  eMBErrorCode eStatus = eMBInit( MB_RTU, 121, 3, 9600, MB_PAR_NONE );
  eStatus = eMBEnable();


while(1) {
    eMBPoll();           
  }
 }

eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
eMBErrorCode    eStatus = MB_ENOERR;
int             iRegIndex;

if( ( usAddress >= REG_INPUT_START )
   && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
{
   iRegIndex = ( int )( usAddress - usRegInputStart );
   while( usNRegs > 0 )
            {
      *pucRegBuffer++ =
         ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
     *pucRegBuffer++ =
        ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
       iRegIndex++;
       usNRegs--;
    }

        HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
    }
    else
    {
         HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
    eStatus = MB_ENOREG;            
    }

    return eStatus;
    }

    eMBErrorCode
    eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,
             eMBRegisterMode eMode )
    {
    return MB_ENOREG;
     }


    eMBErrorCode
    eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
           eMBRegisterMode eMode )
    {
    return MB_ENOREG;
    }

      eMBErrorCode
       eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT 
        usNDiscrete)
       {
       return MB_ENOREG;
      }

为什么要使用这些变量?

usRegInputBuf[0] = 11;
usRegInputBuf[1] = 22;
usRegInputBuf[2] = 33;
usRegInputBuf[3] = 44;
usRegInputBuf[4] = 55;
usRegInputBuf[5] = 66;
usRegInputBuf[6] = 77;
usRegInputBuf[7] = 88;  

我需要进行哪些更改?

3 个答案:

答案 0 :(得分:1)

DE&RE pin to GND

DE和RE引脚用于启用和禁用转换后的输入和输出。您应该:

  • 发送时设置DE = 1,RE = 0
  • 接收时将DE = 0设置为RE = 1,
  • (不使用)不使用设备时(额外)设置DE = 0和RE = 0(这取决于收发器,但通常都设置为Low可以节省大量能量)

在通过rs485发送每个字符之前,您需要设置DE = 1,RE = 0,然后写入字符,然后变回接收模式,然后接收数据。

非常仔细地检查收发器的数据表。如果您使用,例如。 MAX485(但实际上,它们通常一样),请参见第7页:

enter image description here

例如,可以找到有关三种状态逻辑的更多信息。在wiki上。

在RE设置为GND的情况下,栅极永远不会打开,因此您将始终具有高阻抗 在RO引脚上,从不接收任何数据。反之,您将永远不会发送任何数据,因为DE会很低,而且我相信您需要先向仪表发送smth,然后再开始传输。

您应该将uart TX连接到DI,将uart RX连接到RO。在您的情况下,如果转换器将RE / DE引脚之一反相(通常如上所述,RE反相),则可以将它们都连接到同一引脚。

答案 1 :(得分:1)

@kamilcuk接近,但是在所有RS485收发器上,DE为高电平有效,而RE为低电平有效。将DE和RE设置为低电平将创建无法发送的通用接收器。

最简单的“半双工” RS485是将RE和DE连接到单个GPIO引脚。将这个信号驱动为高电平(在HAL语言中为GPIO_PIN_SET)以发送并设置为低电平(在HAL语言中为GPIO_PIN_RESET)以进行接收。

如果您将RE和DE连接到了不同的GPIO引脚,那就可以了,只需将它们同时设置为相同的值即可。我使用了两个宏来执行此操作,因此不必总是考虑逻辑。

然后只需在CubeMX编辑器中相应地命名引脚即可。

// RS485_DE Data Enable, Active High
// RS485_RE Receive En, Active Low
#define ENABLE_TRANSMIT() do { \
    /* Disable Receiver */ \
    HAL_GPIO_WritePin(RS485_RE_GPIO_Port, RS485_RE_Pin, GPIO_PIN_SET); \
    /* Enable Transmitter */ \
    HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_SET); \
    } while(0)

#define ENABLE_RECEIVE() do { \
    /* Enable Receiver */ \
    HAL_GPIO_WritePin(RS485_RE_GPIO_Port, RS485_RE_Pin, GPIO_PIN_RESET); \
    /* Disable Transmitter */ \
    HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_RESET); \
    } while(0)

答案 2 :(得分:0)

Github代码混乱,我建议您遵循here

的UART通信过程
  1. 首先使用串行终端检查是否可以通过UART与stm32f4x板进行通信。
  2. 使用modbus通信协议来实现您的寄存器读取逻辑。