??? 12/31/04 07:10 Read: times |
#84158 - Modbus Responding to: ???'s previous message |
Normally the hub would be dumb - it has no microprocessor. My normal application using a PC would have an ethernet to modbus converter by Advantech or Moxa. These can be dispensed with if you use a FTDI usb->serial chip , a handful of 75176's(or max485...) a 74hc30 and 74hc04. The FTDI chip has an output that goes high when it wants to send - this takes care of the rx/tx direction without any special software - the FTDI chip 'knows' when it sends. The FTDI tx output goes to all the 75176 tx inputs, the 75176 rx lines go through the 74hc30 nand gate and then through a 74hc04 inverter to put the x signal the right way then into the FTDI rx input. The direction output from the FTDI chip goes to pin 2 & 3 of all the 75176's. This gives you a RS485 hub and interface in one (and powered by the USB port!). Modbus ascii is easier to implement on the PC side as it doesn't rely on end of packet timing which can be hard to achieve on a PC. Because Modbus is a polled system, there is no concept of high priority interrupts - a slave waits until it is polled. Obviously, the more slaves there is the slower a complete poll cycle will take. You can have an intelligent hub if you wish - the Modbus protocol doesn't cover such things. Your intelligent hub would use modbus to talk to the slaves and use another modbus like to connect to the PC - the hub software would make the link whichever way you would like. Because modbus is half duplex - when you send a message to a slave you either get a response from the slave or you timeout after a period. It's up to your software to do this. Here is some sample interrupt code to send/receive modbus - it is not complete and uses the second serial port -easy enough to change for serial port1 <pre> void SCON1_int(void) interrupt 7 { static char a; /* Modbus RTU comms is strange that the end of packet is delimited by a timeout. After X character times we expect the packet is complete. So for each character we receive we load timer2 with the timeout value. When timer2 fires we check the crc of the received packet If the CRC fails we reject the packet and look for another */ if (RI_1 ==1) { a = SBUF1; //get the rx char RI_1 = 0; if (modbus_type == ASCII) { if (serial_rx_pkt !=0 ) return; //we haven't finished processing the previous pkt! if (a == ':') { serial_rx_cksm = 0; serial_rx = modbus_buf; serial_rx_count = 0; serial_rx_state = 1; } else { switch(serial_rx_state) { case 0: break; case 1: if ((a >=0x30 ) && ( a <= 0x39)) { a -=0x30; *serial_rx = a<<4; serial_rx_state = 2; } else if ((a >= 0x41) && (a <= 0x46)) { a -=0x37; *serial_rx = a<<4; serial_rx_state = 2; } else if ( a == CR ) //carriage return (end of packet) { if (serial_rx_cksm == 0) //if the checksum was good { serial_rx_state = 0; if ((modbus_buf[0] == modbus_addr) && (serial_rx_count >= 6)) // if ((serial_rx_count >= 6)) { serial_rx_pkt=serial_rx_count; } serial_rx = modbus_buf; serial_rx_count=0; } } else { serial_rx_state = 0; //illegal character } break; case 2: if ((a >= '0' ) && ( a <= '9')) { a -=0x30; *serial_rx |= a; serial_rx_cksm += *serial_rx++; //accumulate the checksum serial_rx_count++; serial_rx_state = 1; } else if ((a >= 'A') && (a <= 'F')) { a -=0x37; *serial_rx |= a; serial_rx_cksm += *serial_rx++; //accumulate the checksum serial_rx_count++; serial_rx_state = 1; } else { serial_rx_state = 0; //illegal character! reject the packet } break; }//end switch } }//end modbus ascii else { if ((serial_rx_pkt == 0) && (serial_rx_count < sizeof(modbus_buf) ) ) { *serial_rx++ = a; /* store the rx char */ serial_rx_count++; /* char count ++ */ TR2=0; /* reload the end of packet timeout */ TH2=0xf9; TL2=0x99; /* 3 character times at 19200 baud*/ TR2=1; } } }//end rx interrupt if (TI_1 == 1) { /* transmit interrupt? */ if (modbus_type == ASCII) { TI_1 = 0; switch(serial_tx_state) { case 0: //send the high nibble a = *serial_tx; //get the data to send serial_tx_cksm += a; //accumulate the checksum SBUF1 = ascii_xlate[a>>4]; serial_tx_state = 1; //send low nibble next break; case 1: //send the low nibble a = *serial_tx; //get the data to send SBUF1 = ascii_xlate[a & 0x0f]; serial_tx++; //-> next byte serial_tx_count --; serial_tx_state = 0; //default the next state if (serial_tx_count == 1) //checksum?? { *serial_tx = 0-serial_tx_cksm; //store the checksum } if (serial_tx_count == 0) { serial_tx_state = 2; //end of the packet, send the CR next } break; case 2: //send the CR SBUF1 = CR; serial_tx_state = 3; break; case 3: //send the LF SBUF1 = LF; serial_tx_state = 4; break; case 4: //do nothing! wait for other code to reset us default: break; }//end switch }//end modbus ascii tx else //Modbus RTU { TI_1 = 0; /* reset the int flag */ /* check for message complete */ if (serial_tx_count==0) ENB485=1; else { /* continue sending */ SBUF1 = *serial_tx++; /* send next character */ --serial_tx_count; /* dec count of characters */ } } }//end tx interrupt } /* If timer2 times out, we expect to find a MODBUS packet in our buffer. Check for address and size then alert the comms task */ void T2_int(void) interrupt 5 { TR2=0; /* stop timer 2 running */ TF2=0; /* clear the overflow flag */ if ((modbus_buf[0] == modbus_addr) && (serial_rx_count > 6)) { serial_rx_pkt = serial_rx_count; //setting serial_rx_pkt to non-zero activates the comms task } serial_rx = modbus_buf; serial_rx_count=0; } (/pre> |
Topic | Author | Date |
Control system | 01/01/70 00:00 | |
buses for industrial | 01/01/70 00:00 | |
CAN or RS-485 | 01/01/70 00:00 | |
one way of master slave | 01/01/70 00:00 | |
RS485 | 01/01/70 00:00 | |
Control system | 01/01/70 00:00 | |
Modbus | 01/01/70 00:00 | |
modbus or not | 01/01/70 00:00 | |
rs-485 | 01/01/70 00:00 | |
Rs485 vs CAN | 01/01/70 00:00 | |
CAN | 01/01/70 00:00 | |
rs-485,high speed? | 01/01/70 00:00 | |
UART speed | 01/01/70 00:00 | |
Speed | 01/01/70 00:00 | |
Go Speed Racer! | 01/01/70 00:00 | |
comments on speed and the above | 01/01/70 00:00 | |
Daisy chain | 01/01/70 00:00 | |
Daisy,Daisy..... | 01/01/70 00:00 | |
no repeat | 01/01/70 00:00 | |
Modbus | 01/01/70 00:00 | |
Modbus | 01/01/70 00:00 | |
Hub ? | 01/01/70 00:00 | |
Modbus | 01/01/70 00:00 | |
Modbus | 01/01/70 00:00 | |
More modbus | 01/01/70 00:00 | |
Modbus | 01/01/70 00:00 | |
failed links![]() | 01/01/70 00:00 |