Modbus Master and Slave on STM32F103 and UNO

Generic boards that are not Maple or Maple mini clones, and don't contain the additional USB reset hardware
tyro
Posts: 10
Joined: Thu Jan 19, 2017 3:44 pm

Re: Modbus Master and Slave on STM32F103 and UNO

Postby tyro » Sun Jan 29, 2017 12:27 pm

messaf wrote:Hi guys!
I added a little library for working with STM32F103 (Library :: ModbusMaster Author :: Doc Walker), I hope he will not swear. :D
Everything is working very well now. I checked on two boards Arduino (slave) and Blue Pill Stm32F103 (master). Here are links to files:
ModbusMaster_STM32_RS-485
ModbusSlave_ArduinoUNO_RS-485


Great!!! I have just tested Master on Maple Mini. I had to replace "node.begin" from old style to new one and everything started to work. I didn't tester responses are cached well, but message Maple is sending from Serial1 is well formatted. You made really big job for people working with modbus protocol and switching to STM32 on Arduino IDE :)

stevestrong
Posts: 883
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: Modbus Master and Slave on STM32F103 and UNO

Postby stevestrong » Sun Jan 29, 2017 3:42 pm

Can you tell us what exactly was the problem, how did you solve it?

messaf
Posts: 7
Joined: Wed Jan 18, 2017 10:55 am

Re: Modbus Master and Slave on STM32F103 and UNO

Postby messaf » Mon Jan 30, 2017 2:54 am

stevestrong wrote:Can you tell us what exactly was the problem, how did you solve it?


The main problem was waiting for the end of transmission UART STM32 data. That is, in the standard library function Arduino Serial.flush () carries the expectation of the end of transmission and treatment of data send buffer. While the STM32 for the above function only cleared buffer, so data is transferred not in full (Serial.write ();). In ModbusMaster library has been added to the function "bool ModbusMaster :: waitWriteSerial (void)", which is as follows:

Code: Select all

/**
Modbus Wait Write Serial.

@param
@return
*/
bool ModbusMaster::waitWriteSerial(void)
{
  if(_serialPort == STM32_USART1)
  {
    usart_reg_map *regs = USART1->regs;
    while ( !(regs->SR & USART_SR_TC) ); // Wait for Transmission Complete to set
    return true;   
  }
  else if(_serialPort == STM32_USART2)
  {     
    usart_reg_map *regs = USART2->regs;
    while ( !(regs->SR & USART_SR_TC) ); // Wait for Transmission Complete to set
    return true;
  }
  else if(_serialPort == STM32_USART3)
  {                 
    usart_reg_map *regs = USART3->regs;
    while ( !(regs->SR & USART_SR_TC) ); // Wait for Transmission Complete to set 
    return true;
  }
  else return false;
}

As you can see from the code in the function there waiting solution for three interfaces UART (USART1 - USART3). Calling this function is carried out in the library functions (ModbusMaster) "uint8_t ModbusMaster :: ModbusMasterTransaction (uint8_t u8MBFunction)", it is a place where data is transmitted:

Code: Select all

uint8_t ModbusMaster :: ModbusMasterTransaction (uint8_t u8MBFunction)
{
...
...
  // transmit request
  if (_preTransmission)
  {
    _preTransmission();
  }
  for (i = 0; i < u8ModbusADUSize; i++)
  {
    _serial->write(u8ModbusADU[i]);
  }
  waitWriteSerial(); // Wait for Transmission Complete to set  // Modified Egor Orlenok
   
  u8ModbusADUSize = 0;
 
  _serial->flush(); 
 
  delayMicroseconds(T3_5); // Modified Egor Orlenok

  if (_postTransmission)
  {
    _postTransmission();
  }
  ...
  ...
  }


Also, if you notice in the code above is present there is a delay "delayMicroseconds (T3_5);", which forms the interval of "silence" of 3.5 characters at the current exchange rate. The value of the interval is initialized (calculated) based on the exchange rate in the transmitted Functions "void ModbusMaster :: begin (uint8_t slave, uint8_t serialPort, uint32_t baud)" argument "uint32_t baud":

Code: Select all

*/
void ModbusMaster::begin(uint8_t slave, uint8_t serialPort, uint32_t baud)
{
//  txBuffer = (uint16_t*) calloc(ku8MaxBufferSize, sizeof(uint16_t));
  _u8MBSlave = slave;
  _u8TransmitBufferIndex = 0;
  u16TransmitBufferLength = 0;
  _serialPort = serialPort;

  //----- Modified Egor Orlenok -----
  if (baud > 19200)
  {
    T1_5 = 750;
    T3_5 = 1750;
  }
  else
  {
    T1_5 = 15000000UL/baud; // 1T * 1.5 = T1.5
    T3_5 = 35000000UL/baud; // 1T * 3.5 = T3.5
  }
 
  switch(serialPort)
  {
    case STM32_USART1: _serial = &Serial1; Serial1.begin(baud);    break;       
    case STM32_USART2: _serial = &Serial2; Serial2.begin(baud);    break;
    case STM32_USART3: _serial = &Serial3; Serial3.begin(baud);    break;   
  }
  //----- End Modified ---------------
 
#if __MODBUSMASTER_DEBUG__
  pinMode(__RED_LED_A__, OUTPUT);
  pinMode(__GREEN_LED_B__, OUTPUT);
#endif
}


Another addition was made in "word.h" file. This alternative implementation functions "word ()", with the project for the assembly on the STM32 Arduino IDE compiler to issue the error described earlier in this topic. Supplement is as follows (an alternative function for the STM32) "MakeWord (uint8_t h, uint8_t l)":
And the place of the call to "ModbusMaster.cpp" file:

Code: Select all

...
...
static inline uint16_t MakeWord(uint8_t h, uint8_t l)
{
  return (h << 8) | l;
}
// Modified Egor Orlenok
static inline uint16_t MakeWord(uint8_t w)
{
  return w;
}

And the place of the call to "ModbusMaster.cpp" file:

Code: Select all

...
...
void ModbusMaster::send(uint8_t data)
{
  send(MakeWord(data));
}
...
          if (i < ku8MaxBufferSize)
          {
            _u16ResponseBuffer[i] = MakeWord(u8ModbusADU[2 * i + 4], u8ModbusADU[2 * i + 3]);
          }
...
          if (i < ku8MaxBufferSize)
          {
            _u16ResponseBuffer[i] = MakeWord(0, u8ModbusADU[2 * i + 3]);
          }
 ...
 ...
 


The source files of the original library (ModbusMaster - Author :: Doc Walker)
Files edited and examples I posted in the previous post:
messaf wrote: Here are links to files:
ModbusMaster_STM32_RS-485
ModbusSlave_ArduinoUNO_RS-485

stevestrong
Posts: 883
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: Modbus Master and Slave on STM32F103 and UNO

Postby stevestrong » Mon Jan 30, 2017 7:18 am

The best would be to share the code on github, rather than in a zip package.

messaf
Posts: 7
Joined: Wed Jan 18, 2017 10:55 am

Re: Modbus Master and Slave on STM32F103 and UNO

Postby messaf » Tue Jan 31, 2017 2:26 am

stevestrong wrote:The best would be to share the code on github, rather than in a zip package.

Yes, of course it would be easy, but I'll do it later, as will be free time.

messaf
Posts: 7
Joined: Wed Jan 18, 2017 10:55 am

Re: Modbus Master and Slave on STM32F103 and UNO

Postby messaf » Tue Jan 31, 2017 2:30 am

I am interested in this question (although it is not in this thread): How to configure Pligin Arduino for Eclipse that would use all the libraries for STM32 boards, many did not try to set up - I have nothing turns out ... Prompt please, or may have some sort of already ready manul on this topic?

stevestrong
Posts: 883
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: Modbus Master and Slave on STM32F103 and UNO

Postby stevestrong » Tue Jan 31, 2017 8:07 am


messaf
Posts: 7
Joined: Wed Jan 18, 2017 10:55 am

Re: Modbus Master and Slave on STM32F103 and UNO

Postby messaf » Tue Jan 31, 2017 10:53 am

stevestrong wrote:Here is a possibility: http://wiki.stm32duino.com/index.php?ti ... th_Eclipse

Thank you! :D


Return to “Generic STM32F103”

Who is online

Users browsing this forum: No registered users and 3 guests