NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Modbus Master

November 10, 2011
by doughowlett
doughowlett's Avatar

I'm trying to write a Modbus master routine for the Nerdkit and interface it with other Modbus Slaves. I'm using the USART TX and RX pins with my setup given below. As a first attempt I'm piecing together a known array of bytes and sending them to a plc, requesting that one register be sent back. This string works fine from Modbus Poll on a PC. The request is sent and the PLC returns the information back to the PC. So I know the bytes being sent and the bytes being received. When I try to send this from the Nerdkit the string appears to be ok on a scope, but the TX com line is set to an idle "high" state which is different from the output I observed from the PC and ModPoll. I don't know if this is a problem but I'm not getting anything returned from the PLC. Therefore I'm assuming the PLC is not getting the data correctly. Both the USART and PLC setup is for 19,200 8N1. Does anyone have any Modbus experience or any suggestions.

  void uart_init() {
    // set baud rate
    UBRR0H = 0;
    UBRR0L = 47;    // for 19,200bps with 14.7456MHz clock
    // enable uart RX and TX
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
    // set 8N1 frame format
    UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);


// Send Byte Subroutine
void SendByte(uint8_t c) {  //Subroutine to send a byte to the UART
    // Syntax is SendByte(#);  where # is any number
    while (!(UCSR0A & (1<<UDRE0))); // Wait until you are able to send a byte
    UDR0 = c;  // pass the value of the c variable into the UDR , which in turn sends the byte out the UART

      query[0] = 1;       /* plc address */
      query[1] = 3;       /* function code to read holding register */
      query[2] = 0;       /* base address of register table Hi byte */
      query[3] = 101;     /* base address of register table lo byte */
      query[4] = 0;       /* num of registers to read hi byte       */  
      query[5] = 1;       /* num of registers to read lo byte       */
      query[6] = 148;  /* crc_hi  */
      query[7] = 21;     /* crc_lo */

      for(i = 0; i < 8; i++)

      uint8_t c = query[i];


Post a Reply

Please log in to post a reply.

Did you know that you can follow NerdKits on Facebook, YouTube, and Twitter? Learn more...