STM32 use MODBUS protocol in serial communication

  A recent project uses MODBUS protocol, they learn a little, here to do some recording in order to avoid subsequent forget.

  Be sure to use MODBUS protocol must first know MOBUS, where do we turn first to understand the meaning of the agreement.

  What the so-called agreement was? Well that is agreed between each other, let others know if that is the signal. Now to define a new simple protocol.

  For example: Protocol: "A" - "LED off" "B" - "Alarm" "C" - "LED lights."

  Microcontroller receives "A" LED off a control, the MCU receives the "B" control alarm, the microcontroller receives "A" to control a LED light. Then when the received information corresponding to the implementation of the corresponding action, this is the agreement.

  A packet data MODBUS main components are: the length of the device address data function code data CRC 

  First a simple analysis of a MODBUS-RTU messages, such as:

  The packet data means to the device address of the device 0x01, the Executive 0x1f code function, assuming 0x1f code Function code represents the saved data and then Flash, then this packet data, which means that the control 0x01 device, do 0x1f Code function 4-bit data stored back to the MCU Flash, wherein the data length is the size of the number of data bytes behind the last two CRC check is all in addition to the last two preceding CRC arithmetic data out through the CRC check code, with to ensure the accuracy of the data.

  Probably so many content agreement, because it is only a simple application, there is no depth to study, and to know that the use of the STM32 enough, the following are the CRC code (emphasis):

/ * ** 
 Function name: uint16_t Crc (uint8_t Rxbuff [] , uint8_t Rx_len) 
 DESCRIPTION: Modbus protocol CRC check 
 incoming values: RXBUFF [] received by the serial data, the serial received data length len 
 outgoing Value: returns two byte CRC checksum, high front and low at the 
* * / 
uint16_t Crc (uint8_t RXBUFF [], uint8_t Rx_len) 
{ 
    uint8_t len = Rx_len - 2 ; 
    uint16_t crc_Result = 0xFFFF ;
     int crc_num = 0 ;
     int xor_flag = 0 ; 
    for ( int I = 0 ; I <len; I ++ ) 
    { 
        crc_Result = ^ [I] RXBUFF; 
        crc_num= (crc_result&0x0001);
        for(int m=0;m<8;m++)
        {
            if(crc_num==1)
                xor_flag = 1;
            else
                xor_flag = 0;
            crc_result >>= 1;
            if(xor_flag)
                crc_result ^= 0xa001;
            crc_num = (crc_result & 0x0001);
        }
    }
    return crc_result;
}

  The following are examples of code using MODBUS, here I am MODBUS protocol made some changes in the "function code" with between "data length" Added a "read-write flag" , you can do according to their needs project about the actual project modification is understandable:

/ * ** 
 Function name: void modbus (uint8_t Rxbuff [] , uint8_t len) 
 DESCRIPTION: Modbus protocol processing 
 incoming values: RXBUFF [] received by the serial data, the serial received data length len 
 outgoing value: None 
* * / 
void Modbus (uint8_t RXBUFF [], uint8_t len) 
{ 
    uint8_t Read_Robot [ . 1 ] = { 0 }; 
    uint8_t Robot_add = 0x01 ; 
    uint8_t Robot = Get_Robot_Num ();   // Get pre-saved device address 
    uint16_t CRC = Crc (RXBUFF, len ); 
    uint16_t Rx_crc = RXBUFF [len 2 ] << . 8 | RXBUFF [len . 1 ]; 
    IF ((== Robot RXBUFF [ 0] || RXBUFF [ 0 ] == 0xff ) && Rx_crc == crc) // determine the device address is correct, do not know the address of the reserved time, virtual address 0xff, forget prevent the device address, you can modify the virtual address 
    { 
        Switch (RXBUFF [ . 1 ]) 
        { 
            Case  0x01 : // operator ID 
                IF (RXBUFF [ 2 ] == 0x00 ) // read 
                        the read (MCU_Rx_buff, ID_Flash_Add);
                 the else  IF (RXBUFF [ 2 ] == 0x01 ) // write 
                         the Write (RXBUFF, len, ID_Flash_Add);
                 BREAK;
             Case  0x02 : // operation name 
                IF (RXBUFF [ 2 ] == 0x00 ) // read 
                        the Read (MCU_Rx_buff, Name_Flash_Add);
                 the else  IF (RXBUFF [ 2 ] == 0x01 ) // Write 
                         Write (Rxbuff, len, Name_Flash_Add) ;
                 BREAK ;
             Case  0x03 : // operation link 
                IF (RXBUFF [ 2 ] == 0x00 ) // read
                        Read(MCU_Rx_buff,Link_Flash_Add);
                else if(Rxbuff[2]==0x01) //
                         Write(Rxbuff,len,Link_Flash_Add);
                break;
            case 0x04: //操作型号
                if(Rxbuff[2]==0x00) //
                        Read(MCU_Rx_buff,Model_Flash_Add);
                else if(Rxbuff[2]==0x01) //
                         Write(Rxbuff,len,Model_Flash_Add);
            break;
            case 0x05: //操作品牌
                if(Rxbuff[2]==0x00) //
                        Read(MCU_Rx_buff,Brand_Flash_Add);
                else if(Rxbuff[2]==0x01) //
                         Write(Rxbuff,len,Brand_Flash_Add);                
            break;
            case 0x06: //操作行数
                if(Rxbuff[2]==0x00) //
                        Read(MCU_Rx_buff,Linage_Flash_Add);
                else if(Rxbuff[2]==0x01) //
                         Write(Rxbuff,len,Linage_Flash_Add);    
                break;
            case 0x07: //操作幅宽
                if(Rxbuff[2]==0x00) //
                        Read(MCU_Rx_buff,Wite_Flash_Add);
                else if(Rxbuff[2]==0x01) // Write 
                         the Write (RXBUFF, len, Wite_Flash_Add);    
                 BREAK ;
             Case  0x08 : // operating height 
                IF (RXBUFF [ 2 ] == 0x00 ) // read 
                        the Read (MCU_Rx_buff, Hight_Flash_Add);
                 the else  IF (RXBUFF [ 2 ] == 0x01 ) // write 
                         the write (RXBUFF, len, Hight_Flash_Add);                    
                 BREAK ;
             Case  0x09 : // operating horsepower 
                if(Rxbuff[2]==0x00) //
                        Read(MCU_Rx_buff,Soup_Flash_Add);
                else if(Rxbuff[2]==0x01) //
                         Write(Rxbuff,len,Soup_Flash_Add);                    
                break;
            case 0x0a: //操作合作社ID
                if(Rxbuff[2]==0x00) //
                        Read(MCU_Rx_buff,Artel_Flash_Add);
                else if(Rxbuff[2 ] == 0x01 ) // write 
                         the Write (RXBUFF, len, Artel_Flash_Add);                    
                 BREAK ;
             Case  0x21 : // change the baud rate 
                IF (RXBUFF [ 2 ] == 0x00 ) // read 
                { 
                        Get_Boud_num (); 
                } 
                the else  IF (RXBUFF [ 2 ] == 0x01 ) // write 
                { 
                      Boud_Set (RXBUFF); 
                        HAL_UART_Transmit (huart1 &, RXBUFF, len, 0x1000 );                     
                } 
                BREAK ;
             Case  0x22 : // operating device address 
                IF (RXBUFF [ 2 ] == 0x00 ) // read 
                { 
                        Read_Robot [ 0 ] = Get_Robot_Num (); 
                      HAL_UART_Transmit ( & huart1, Read_Robot, . 1 , 0x1000 ); 
                } 
                the else  IF (RXBUFF [ 2 ] == 0x01 ) // write
                {
                    Robot_add=Rxbuff[5]; 
                    Robot_Num_Init(Robot_add);
                    HAL_UART_Transmit(&huart1,Rxbuff,len,0x1000);
                }                    
                break;
        }
    }
}

  The last function is to direct the call to the serial port receive MODBUS handler, the code is as follows:

/ * ** 
 Function name: void Usart_RX (void) 
 Description: The received data processing 
 incoming values: None 
 Outgoing: none 
* * / 
void Usart_RX ( void ) 
{ 
    IF (Rx_End_flag == . 1 )         
  {        
      Modbus (RX_BUFFER, Rx_len) ;     // call the MODBUS protocol handler                 
      Memset (RX_BUFFER, 0 , the sizeof (RX_BUFFER)); // empty array 
      Rx_len = 0 ; 
      Rx_End_flag = 0 ; // Clear the receive end flag 
   } 
    HAL_UART_Receive_DMA ( &huart1,Rx_buffer,BUFFER_SIZE);
}

  As long as a result of these steps, you can simply use the MODBUS protocol on the STM32, in fact, MODBUS protocol that is hard, it just like we usually similar to their own definition of serial communication protocol, the data header, data content, data tail, but more nothing more scientific and standardized.

 

Guess you like

Origin www.cnblogs.com/xingboy/p/11388731.html