簡體   English   中英

STM32F4接口與RS485

[英]STM32F4 interface with RS485

我正在嘗試使用 RS485 到 TTL 轉換器從儀表讀取數據到STM32f407VG 我的設備從 ID 是 121,波特率是 9600。我想讀取holdingRegistersInputRegisters

我正在為 STM32 HAL 庫嘗試這個 FreeMODBUS RTU 端口

我已將我的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;  

我需要做哪些改變?

DE&RE pin to GND

DE 和 RE 引腳用於啟用和禁用轉換后的輸入和輸出。 你應該:

  • 發送時設置DE=1和RE=0
  • 接收時設置DE=0,RE=1
  • (extra) 在不使用設備時設置 DE=0 和 RE=0(這取決於收發器,但通常都設置為低可以節省大量能量)

在通過rs485發送每個字符之前,需要設置DE=1,RE=0,然后寫入字符,然后變回接收模式,然后接收數據。

仔細檢查收發器的數據表。 如果你使用,例如。 MAX485 (但實際上,它們通常都是一樣的),您在第 7 頁看到:

在此處輸入圖像描述

有關三態邏輯的更多信息,請參見 ex。 維基上。

將 RE 設置為 GND 時,門將永遠不會打開,因此您將始終在 RO 引腳上保持高阻抗並且永遠不會接收到任何數據。 反過來,你永遠不會發送任何數據,因為 DE 會很低,我相信你需要在開始傳輸之前向儀表發送 smth。

您應該將 uart TX 連接到 DI,將 uart RX 連接到 RO。 在您的情況下,如果轉換器反轉 RE/DE 引腳之一(通常 RE 反轉,如上所述),您可以將兩者連接到同一引腳。

@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)

Github代碼比較亂,建議按照這里提到的UART通信流程

  1. 如果您能夠使用 UART 與 stm32f4x 板進行通信,請首先使用串行終端進行檢查。
  2. 使用 modbus 通信協議來實現您的寄存器讀取邏輯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM