View Full Version : SerIn2 ASCII Conversion
rwskinner
- 11th February 2008, 23:29
Hello Folks, Been a long time.
I have a program I'd written awhile back that uses modbus RTU and now we need to add the Modbus Ascii to it so either can be used. Of course the protocol is determined at start up by a jumper. RTU is tried and tested, just have to squeeze in the ASCII portion.
The hit list:
On Power Up Check Jumper then Set Protocol Variable
Set Baud Rate, Parity and other Port Settings to proper values for Protocol
Modify HSerIn to decode accordingly
Modify HSerOut to Encode accordingly
Using HSerin2, which is the easiest way to convert ASCII to Decimal values.
I will be placing the values into an array of byte called BufRx.
The incoming Ascii is like this, with out the spaces.
:01 03 00 00 00 05 13 10
When Decoded, after skipping the Colon, and the CRLF I should have this:
BufRX[0] = 1
BufRX[1] = 3
BufRX[2] = 0
BufRX[3] = 0
BufRX[4] = 0
BufRX[5] = 5
Below, I Wait for the Colon, grab 2 char and convert to decimal and store in array until CR LF.
I know there has to be an easier way but I'm way rusty. Not even sure if this is correct.
HSerIn Timeout,Receive,[WAIT(":"),DEC2 BufRX[0], DEC2 BufRX[1], DEC2 BufRX[2], DEC2 BufRX[3], DEC2 BufRX[4], DEC2 BufRX[5],13,10 ]
Thanks,
Richard
Darrel Taylor
- 12th February 2008, 00:06
Hi Richard,
For statements that use square brackets for the parameters, like HSERIN ... The array elements must use Round brackets. Otherwise PBP gets a bit confused.
And the 13,10 on the end isn't needed. They'll be ignored on the next WAIT.
HSerIn Timeout,Receive,[WAIT(":"),DEC2 BufRX(0),DEC2 BufRX(1),DEC2 BufRX(2), _
DEC2 BufRX(3),DEC2 BufRX(4),DEC2 BufRX(5)]
Or, you could do it this way. Not better, just different ...
FieldCount VAR byte
HSerIn Timeout,Receive,[WAIT(":")]
For FieldCount = 0 to 5
HSerIn Timeout,Receive,[DEC2 BufRX(FieldCount)]
Next FieldCount
rwskinner
- 12th February 2008, 00:16
The DEC2 should also be HEX2. Thanks for the tip on the brackets. Didn't remember that.
Anyone remember how to change parity at runtime, not using a define?
rwskinner
- 12th February 2008, 03:01
The DEC2 should also be HEX2. Thanks for the tip on the brackets. Didn't remember that.
Anyone remember how to change parity at runtime, not using a define?
That whole deal went way too easy.
mech962784
- 13th February 2008, 21:06
Dear rwskinner
i am looking for a modbus (RTU) slave sample code for the PIC16F877A,
can you please share your code?
rwskinner
- 14th February 2008, 00:53
Sorry, No. The company will not allow me to post source. However if you can tell us where your having problems at or post your code then maybe we can help.
I found most folks are not willing to help or share code for Industrial Protocols. Mainly because there is lots of money invested in development, or in sales.
Some code and Examples Can be found here:
http://www.modbus.pl/microchip.htm
Some Actual code can be found here on the list...
http://www.picbasic.co.uk/forum/showthread.php?s=&threadid=316
It works but really needs to be doctored up some.
Modbus Specifications and Examples in C can be found here:
http://www.modbus.org/docs/Modbus_over_serial_line_V1.pdf
and
http://www.modbus.org/docs/PI_MBUS_300.pdf
Do yourself a favor and try real hard not to try and do the 3.5 character timeout. If your a slave, look for the 8 byte request, then check the ID, if good then check CRC, then Check FC and Process or Reject with Error Code. So on. Build the packet and ship back off and be done with it.
If your wanting to be the Master then there is a little more to it (not much) but some.
As in the documentation
RTU as follows:
Slave ID 1 byte, Function Code 1 Byte, Start Register 2 Bytes, Number of Regs to Get 2 Bytes, CRC16 2 Bytes
RTU example: 01 03 00 00 00 01 CRCH,CRCL
Ascii as follows:
Start of Message is a colon, Slave ID 1 byte, Function Code 1 Byte, Start Register 2 Bytes, Number of Regs to Get 2 Bytes, LRC 1 Byte, CRLF to end the message.
Ascii is sent as Ascii Hex. :01 03 00 00 00 01 LRC 0D 0A
I prefer to check the Slave ID first so I'm not checking CRC's all day long on other nodes messages.
You can handl ASCII and RTU with all the same routines, except for the following.
When Receiving the Data, you have to decode it a little differently
When Sending the Data, you have to encode it a little differently
LRC or CRC checks depending on the Protocol your using.
Under my Belt so Far.
Modbus RTU
Modbus ASCII
CAN STD and EXT
J1939
Numerous proprietary industrial protocols. Frick, Cat....
Suppose to Start on AB DF1 soon. Arghhhh Not looking forward to it.
Richard
rwskinner
- 15th February 2008, 13:35
As an additional thought, I normally use the HSERIN and grab all 8 bytes of the packet, then compare the Slave ID to my own, if it matchs, then check the CRC/LRC and go from there.
Since I'm having to use SERIN2 without the hardware USART, it might be better it I just check for the correct Slave ID in the Wait portion.
I'm not sure it will actually make any difference would it, if there is a 20ms timeout, its still going to sit there for 20ms waiting for the message regardless right? Ah, but I remove the over head of collecting data and checking the Slave ID each time when there is other traffic on the line.
receive:
Gosub GetADCReadings '8 of them
Serin2 stuff here - Timeout goes back to receive (Wait for : and grab all bytes)
If SlaveID doesn't match go back to receive else
Check CRC if Bad go back to receive
Start processing message
Send Reply
goto Receive
Seems to me, if the Serin2 waits for the Slave ID Byte I end up still in the wait for 20ms, but then I immediately exit back to receive, instead of processing every packet on the line, checking ID then going back to receive. Might make a little difference.
Thoughts
mech962784
- 16th February 2008, 09:25
dear rwskinner
thank you for your reply.
at least can you please give me a working code for generating CRC for modbus RTU (in PICBASIC Pro)
assuming that i have received from the HSERIN these byte
BYTe_1 BYTe_2 BYTe_3 BYTe_4 BYTe_5 BYTe_6 CRC1 CRC2
for example
01 03 00 00 00 0A C5 CD
how to calculate the CRC1 and CRC2
i am using this with PIC16F877A
Best Regards
skimask
- 16th February 2008, 09:38
dear rwskinner
thank you for your reply.
at least can you please give me a working code for generating CRC for modbus RTU (in PICBASIC Pro)
Best Regards
Did you look at your other thread? There's code already there...
rwskinner
- 17th February 2008, 00:49
Yep, it was in the thread that said "working Code"
Here is my method of CRC which I believe came from that thread ???
And my method of LRC which works but could be improved upon.
Notes:
CRC is a WORD, LRC is a Byte
Buf is an array that contains all the bytes.
Len is the number of bytes in the array and you set that depending on what your doing.
When Receiving messages LEN has to be adjusted to Exclude the CRC or LRC Bytes.
CalcCRC:
CRC16=$FFFF
For i = 0 to Len
CRC16=CRC16^Buf[i]
For j = 1 to 8
IF CRC16.Bit0 = 1 Then
CRC16=$A001^(CRC16>>1)
ELSE
CRC16=CRC16>>1
EndIf
Next j
Next i
Return
CalcLRC:
'Procedure Builds LRC value from bytes
LRC = 0
For i = 0 TO Len
LRC = LRC + Buf[i]
Next i
LRC = $100 - LRC
Return
mech962784
- 22nd February 2008, 03:12
by the way: dear rwskinner
which company are you working for?
have you implemented the can or canopen protocol using the picbasic?
can you give me the specification of these two protocols?so i can do the implementation.
best regards
JohnR
- 3rd March 2008, 17:45
Did you finally get a working solution for Modbus ?
I saw a lot of banter and pieces but I need a simple, complete source code in PicBasic and or assembly for PIC16F877A
If so would you share it or where can I get it
Thank You
rwskinner
- 4th March 2008, 21:41
There was actual working code in the links I posted above. These are not my sources but the code works.
Mine doesn't look anything like that however the CRC Routine was borrowed from it.
Also in the thread right next to this one called something like RS485 network
Powered by vBulletin® Version 4.1.7 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.