cancel
Showing results for 
Search instead for 
Did you mean: 

STM32_modbus issues

sreedharan1196
Associate II

Can anyone suggest me what the issues in the below code, i had generated the Modbus data frame and also checked the CRC function with Modbus- CRC calculator, I am able to transmit the data and also i am also waiting for the data to receive on interrupt mode. I am not able to receive any of the response, is that any other issues in the above code.

5 REPLIES 5
sreedharan1196
Associate II
#include "main.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE int __io_getchar(void)
#define MODBUS_SLAVE_ID 0x01
#define MODBUS_FUNCTION_READ_HOLDING_REGISTERS 0x03

uint8_t uart2_tx_data[8];
uint8_t uart2_rx_data[256];
uint16_t recv_data[2];

#define DATA_REGISTER_START_POSITIVE 115  // Positive accumulator value
#define DATA_REGISTER_START_NEGATIVE 117  // Negative accumulator value
#define DATA_REGISTER_START_NET      119  // Net accumulator value

int REGISTERS_TO_READ = 0x02;    // Number of registers to read

UART_HandleTypeDef hlpuart1;
UART_HandleTypeDef huart3;

PUTCHAR_PROTOTYPE
{
    HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
    return ch;
}

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART3_UART_Init(void);
static void MX_LPUART1_UART_Init(void);

void modbusPreTransmission(void);
void modbusPostTransmission(void);
uint16_t crc16(uint8_t *data, uint16_t length);
void sendModbusRequest(uint8_t *request, uint8_t len);
void ultrasonic_value(int DATA_REGISTER_START, int REGISTERS_TO_READ);

void modbus_tx_data()
{

	    uint8_t slaveAddress = MODBUS_SLAVE_ID;
	    uint8_t functionCode = MODBUS_FUNCTION_READ_HOLDING_REGISTERS;
	    uint16_t startAddress = DATA_REGISTER_START_POSITIVE - 1;
	    uint8_t numRegistersHigh = 0x00;
	    uint8_t numRegistersLow = REGISTERS_TO_READ;

	    uart2_tx_data[0] = slaveAddress;
	    uart2_tx_data[1] = functionCode;
	    uart2_tx_data[2] = startAddress >> 8;
	    uart2_tx_data[3] = startAddress & 0xFF;
	    uart2_tx_data[4] = numRegistersHigh;
	    uart2_tx_data[5] = numRegistersLow;

	    uint16_t crc = crc16(uart2_tx_data, 6);
	    uart2_tx_data[6] = crc & 0xFF;
	    uart2_tx_data[7] = (crc >> 😎 & 0xFF;

	    printf("The Uart_tx buffer: ");
	    for (int i = 0; i < 8; ++i)
	    {
	        printf("%02X ", uart2_tx_data[i]);
	    }
	    printf("\r\n");

    sendModbusRequest(uart2_tx_data, 8);
}

void modbusPreTransmission()
{
    printf("Data pin enabled...\r\n");
    HAL_GPIO_WritePin(data_enable_GPIO_Port, data_enable_Pin, GPIO_PIN_SET);
    HAL_Delay(10);
}

void modbusPostTransmission()
{
    printf("Data pin disabled...\r\n");
    HAL_GPIO_WritePin(data_enable_GPIO_Port, data_enable_Pin, GPIO_PIN_RESET);
    HAL_Delay(10);
}

void sendModbusRequest(uint8_t *request, uint8_t len)
{
	printf("Sending Modbus request...\r\n");
    modbusPreTransmission();
    if (HAL_UART_Transmit(&huart3, request, len, HAL_MAX_DELAY) == HAL_OK)
    {
        printf("\nSuccess: UART transmit done\r\n\n");
    }
    else
    {
        printf("Error: UART transmit failed\r\n");
        return;
    }
    modbusPostTransmission();

    printf("Waiting for response...\r\n");
    HAL_Delay(100);

    if (HAL_UART_Receive(&huart3, uart2_rx_data, 7 + (2 * REGISTERS_TO_READ), 2000) == HAL_OK)
    {
        printf("\nReceived data from Modbus: ");
        for (int i = 0; i < (7 + 2 * REGISTERS_TO_READ); ++i)
        {
            printf("%02X ", uart2_rx_data[i]);
        }
        printf("\r\n");
    }
    else
    {
        printf("\nError: UART receive failed\r\n\n");
    }
}

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
  if (huart->Instance == USART3)
  {
    if (uart2_rx_data[1] == MODBUS_FUNCTION_READ_HOLDING_REGISTERS)
    {
      for (int i = 0; i < REGISTERS_TO_READ; i++)
      {
        recv_data[i] = (uart2_rx_data[3 + 2 * i] << 😎 | uart2_rx_data[4 + 2 * i];
      }
      float data = *(float *)(&recv_data);

      printf("Received Modbus Data: %.2f\r\n", data);
    }
    else
    {
      printf("Received unexpected Modbus data.\r\n");
    }

    HAL_UART_Receive_IT(&huart3, uart2_rx_data, sizeof(uart2_rx_data));
  }
}

uint16_t crc16(uint8_t *data, uint16_t length)
{
  uint16_t crc = 0xFFFF;

  for (uint16_t i = 0; i < length; i++)
  {
    crc ^= data[i];
    for (uint8_t j = 0; j < 8; j++)
    {
      if (crc & 0x0001)
      {
        crc = (crc >> 1) ^ 0xA001;
      }
      else
      {
        crc >>= 1;
      }
    }
  }

  return crc;
}

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART3_UART_Init();
  MX_LPUART1_UART_Init();
  printf("Welcome to stm32.......\r\n");
  HAL_Delay(2000);
  HAL_UART_Receive_IT(&huart3, uart2_rx_data, sizeof(uart2_rx_data));
  while (1)
  {
     modbus_tx_data();
     HAL_Delay(5000);
  }
}
static void MX_LPUART1_UART_Init(void)
{
  hlpuart1.Instance = LPUART1;
  hlpuart1.Init.BaudRate = 115200;
  hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
  hlpuart1.Init.StopBits = UART_STOPBITS_1;
  hlpuart1.Init.Parity = UART_PARITY_NONE;
  hlpuart1.Init.Mode = UART_MODE_TX_RX;
  hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  hlpuart1.FifoMode = UART_FIFOMODE_DISABLE;
  if (HAL_UART_Init(&hlpuart1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&hlpuart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&hlpuart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&hlpuart1) != HAL_OK)
  {
    Error_Handler();
  }
}
static void MX_USART3_UART_Init(void)
{
  huart3.Instance = USART3;
  huart3.Init.BaudRate = 115200;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart3.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart3, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart3, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
}

 

While you receive data in the UART interrupt, why do you call sendModbusRequest?  set a flag in the interrupt when the data is fully received. Then use that flag in the main to print the data and send the request again.  Did you check the CRC is as per the example given in the programming manual? It may be better to get one character in the interrupt, if you are expecting different length of data for different Modbus requests, else you will not get the interrupt complete interrupt. I guess you have to re trigger the UART_ReceiveIT again in your send function

That is being said what is happening at the end, did you get a response or not?

 

My guess would be the 10ms delay between the end of transmission and flipping the transceiver to receive mode, then a 100ms delay before receiving.

With the device I'm working on, the response would have been sent within the initial 10ms, before your transceiver had been flipped, causing two devices to be on the bus at the same time.

The 100ms delay is exceedingly generous. I suspect that if you probe your A and B signals, you'll find that the responses were sent before you were listening.

Does your processor have RS485 mode on the UART? If so, have the hardware control the transceiver.

I created a raw data frame and trying to send the raw data to the Modbus,  i am getting hal_ok for usart tranmsit ,but  when i connect the modbus software , i cannot see the tranmsitted data from the controller to the modbus simluator, what the issues i am facing her

 

Chek if your rs485 card has DS+RD tied together.  In the pc you can open any software like putty and chek if the usb to rs485 port receives data. If you receive data on putty and if the modbus software do not show means crc or slave I'd not correct.

You can connect the uart tx and rx to usb to ttl converter rx and tx respectively.