View previous topic :: View next topic |
Author |
Message |
Mrinmoy Dey
Joined: 23 Jan 2018 Posts: 44
|
Stop bit 2 problem |
Posted: Tue Jan 23, 2018 1:40 am |
|
|
Hi,
I am trying to communicate with a ModBus-RTU of a Load Cell using my controller using PIC18F46K80. According to the documents from the Load Cell vendor company stop bit must be 2 and parity should 'None'. But this specification is not working.Compiler showing the error - Internal Error - Contact CCS PR-CODE at 9 SCR=1048.. My ccs version is 5.025. Please anyone having solution of that must reply. whole project stuck due to this. Thanks in advance.
Mrinmoy |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19222
|
|
Posted: Tue Jan 23, 2018 3:50 am |
|
|
This is a limitation of the PIC hardware.
The problem is the PIC hardware can't generate 2 stop bits.
Very few things actually need two stops.
However it is relatively easy to 'bodge' round.
Remember a stop bit, is just a bit sent with the TTL output 'idle' (high).
So assuming the data is 8bit (you don't say?), the key is to send 9bit data with the extra bit set high.
So, if you set your RS232 to use bits=9, and 'long_data', then:
Code: |
#USE RS232(UART1, BAUD=9600, PARITY=N, LONG_DATA, bits=9, STREAM=DEMO)
//Obviously using the right UART, and baud rate
//Then have a encapsulated output function as:
void send_two(char chr)
{
int16 to_send=0;
//amended - must be zero to start
to_send=chr | 0x100; //turn on bit 9
fputc(to_send,DEMO);
}
//Then you can print to this like
printf(send_two, "This is sent with two stop bits\n");
|
On receive, the low 8 bits will contain the data as normal. There will just be an extra 9th bit containing a '1', which can be ignored.
Last edited by Ttelmah on Tue Jan 23, 2018 5:11 am; edited 2 times in total |
|
![](templates/subSilver/images/spacer.gif) |
Mrinmoy Dey
Joined: 23 Jan 2018 Posts: 44
|
|
Posted: Tue Jan 23, 2018 4:13 am |
|
|
Thank you Ttelmah!!
It will almost fix the problem I think but there is a little confusion.
As per your demo code then there will not be any stop bit in #use ()block??
and what is meant by LONG_DATA??It is not cleared to me
please help in that and thanks once again. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19222
|
|
Posted: Tue Jan 23, 2018 5:10 am |
|
|
Synchronous serial always has a stop of some sort. The default is one stop bit. So by adding an extra bit high, I generate two.
'long_data' allows you to send and receive more than 8bits. So what I'm doing is saying that getc, and putc, will return and accept an int16, instead of an int8. This then allows me to set bit9.
There is a fault, that I need to initialise the variable to 0. Have amended this. Duh... ![Embarassed](images/smiles/icon_redface.gif) |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9107 Location: Greensville,Ontario
|
|
Posted: Tue Jan 23, 2018 6:14 am |
|
|
hmm, don't use Modbus, but couldn't you just add a small delay(equal to a bit width) after sending the data ?
it seems a cleaner,simpler approach though I've only had 1 coffee...
Jay |
|
![](templates/subSilver/images/spacer.gif) |
Mrinmoy Dey
Joined: 23 Jan 2018 Posts: 44
|
|
Posted: Tue Jan 23, 2018 6:18 am |
|
|
Now it is all clear to me.@Ttelmah
Thank you!!
![Smile](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Mrinmoy Dey
Joined: 23 Jan 2018 Posts: 44
|
|
Posted: Tue Jan 23, 2018 6:26 am |
|
|
@temtronic
I have to use Modbus. Its a vendor's module where Modbus is in-built,
and I have already added that delay after sending the data but this is not the solution for stop bit problem. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19222
|
|
Posted: Tue Jan 23, 2018 7:39 am |
|
|
The delay will do it, but you have to remember it needs to be after every byte. Problem is that if using the hardware UART, and something like printf, you won't get it between the bytes. Even using putc, you will have to wait for the transmit shift register to empty, and then add the delay....
Some of the later more sophisticated PIC's, like PIC24's do allow two stops. |
|
![](templates/subSilver/images/spacer.gif) |
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Tue Jan 23, 2018 7:41 am |
|
|
Use the CCS Modbus code. See the example ex_modbus_master.c. it sorts everything out for you.
While yes, the hardware only generates one stop bit, all stop bits are are the line is held in the space state, which is where it is when nothing is being sent. So, as Ttelmah and Temtronic have already said, all you need to do is make sure you do not try to send anything within two bit periods of the end of the previous character. Be careful, however, as the timing of the transmit interrupt is NOT at the end of the stop bit, and in any case putting delays in ISR code is a very bad idea. In any case, Modbus requires careful timing, and its easier to let the CCS code do it for you than reinventing the wheel by sorting it out yourself.
Historically extra stop bits were needed by electromechanical devices such as printers and teletypes, including the near-ubiquitous ASR-33, that couldn't buffer characters or deal with them with only one bit's worth of time between characters. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19222
|
|
Posted: Tue Jan 23, 2018 9:37 am |
|
|
I must admit I just saw the title, and thought I'll give how to send two stop bits, without thinking 'Modbus', just use the CCS code.... |
|
![](templates/subSilver/images/spacer.gif) |
Mrinmoy Dey
Joined: 23 Jan 2018 Posts: 44
|
|
Posted: Wed Jan 24, 2018 12:33 am |
|
|
@Ttelmah
Yes! my hardware comprises of RS485 and as I am using fputc , I have used a 100 ms delay after transmitting all data bytes. |
|
![](templates/subSilver/images/spacer.gif) |
Mrinmoy Dey
Joined: 23 Jan 2018 Posts: 44
|
|
Posted: Wed Jan 24, 2018 12:44 am |
|
|
@RF_Developer
CCS code helps a lot..ex_modbus_master.c is very helpful.
But I can't understand some of your words. you have said that - "as Ttelmah and Temtronic have already said, all you need to do is make sure you do not try to send anything within two bit periods of the end of the previous character." Its not clear to me. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19222
|
|
Posted: Wed Jan 24, 2018 2:41 am |
|
|
Key to understand is that when you use putc, assuming the chip is not already sending, the character is loaded into the transmit buffer, _and then starts transmitting_. The call returns as soon as this happens. Now from this point the character takes then one bit time for start. 8 bit times for the data, and another bit time for the hardware stop, before it'll actually finish sending. This is the point from which another bit of delay is needed. So assuming 8 bit data, you'd actually have to delay for 11 bit times after you load each character, to ensure 2 stops (1+8+2). It is the fact that putc returns while the character is still 'in transit', that makes the timing more difficult.... |
|
![](templates/subSilver/images/spacer.gif) |
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Wed Jan 24, 2018 5:36 am |
|
|
I was saying that you don't need to send two stop bits in hardware. You can send one stop bit as long as you wait for at least one extra bit's worth of time after the character before sending another character.
Another way of thinking about this is that stop bits are the gaps between characters. When you send 8 bits data and one start bit, then the stop bits are the minimum time in between characters. With one stop bit, the minimum time between the last data bit of a character and the start bit of the next character is one bit time. In other words with one stop bit the minimum time between characters is one bit. With two stop bits, there must be at least two bits between characters. There can be more, of course, but there always has to be at least the required number of stop bits between characters.
So, sending one stop bit in hardware and then waiting one bit time in code is the same as sending two stop bits in hardware.
The problem is knowing when the character has been sent. As Ttelmah says, putc will return as soon as it has put the character in the hardware buffer. The TRMT (transmit interrupt) will trigger when the last data bit has been sent, in other words during the stop bit.
Receiving two stop bit data is simple with one stop bit hardware: just read it. It works fine with no issues. All that happens is that one bit time is wasted.
But all this is interesting but not very practical as the CCS Modbus driver sorts it out for you and you do not have to worry about stop bits and Modbus timing (some older versions need modification above 20MHz). They will set up the UART hardware and do all the timing, the CRCs, RS485 half-duplex control, and provide a framework (example code) for command decoding and response formatting. |
|
![](templates/subSilver/images/spacer.gif) |
Mrinmoy Dey
Joined: 23 Jan 2018 Posts: 44
|
|
Posted: Wed Jan 24, 2018 11:55 pm |
|
|
@Ttelmah & @RF_Developer
Thanks!! Its clear now.
No confusion about stop bits. |
|
![](templates/subSilver/images/spacer.gif) |
|