CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

#use rs232 and its effect on parity

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
MrColin



Joined: 05 Sep 2014
Posts: 13

View user's profile Send private message

#use rs232 and its effect on parity
PostPosted: Fri Dec 12, 2014 10:20 am     Reply with quote

Compiler: v4.121
PIC: 16F1960

Hi. My code is doing something a little unexpected and I'm hoping you can clear up why.

My device has to be able to support RS232 with and without parity. At the start of my software I have:

Code:
#use rs232(baud=57600, UART1, PARITY=N, BITS=8, ERRORS, STOP=1, DISABLE_INTS, stream=UART_NO_PARITY)
#use rs232(baud=57600, UART1, PARITY=O, BITS=8, ERRORS, STOP=1, DISABLE_INTS, LONG_DATA, stream=UART_PARITY)


And when the device needs to reconfigure itself I update my serial settings:

Code:
     
if (serial_setup.parity){
  setup_uart(57600, UART_PARITY);
}
else{
  setup_uart(57600, UART_NO_PARITY);
}


Then, when reading data on an ISR I use:

Code:

if(serial_setup.parity){
  long_c = fgetc(UART_PARITY);
  c = (uint8_t)(long_c&0x00FF);
  p_bit = ((long_c&0x0100) == 0x0100);
else{
   c = fgetc(UART_NO_PARITY);
}


The problem I am seeing though is that when I'm reading back data which has no parity, and the device is reading using the UART_NO_PARITY stream, it is reading the data incorrectly unless I have parity enabled on the device it is talking to. It does not use the NO_PARITY stream.

However, when writing everything works as expected.

If I flip the order of my '#use rs232' directives (ie. declare NO_PARITY last) then my reading operations work as expected, but my write operations are broken.

Here is my write operation:
Code:

if(serial_setup.parity){
  long_c = parity_bit(c, serial_setup.parity);
  long_c <<= 8;
  long_c |= c;
  fputc(long_c, UART_PARITY);
}
else{
  fputc(c, UART_NO_PARITY);
}


Am I missing something critical here? Thanks for your time.
jgschmidt



Joined: 03 Dec 2008
Posts: 184
Location: Gresham, OR USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Fri Dec 12, 2014 10:45 am     Reply with quote

Since both #use statements refer to UART1, only the last one will actually be used. You won't end up with two different streams pointing to the same UART.

What you're trying to do may be possible by manually changing some register values - I've never tried this so I don't know if you can change them "on the fly".
_________________
Jürgen
www.jgscraft.com
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Dec 12, 2014 11:23 am     Reply with quote

Quote:
Compiler: v4.121
PIC: 16F1960

I don't know what PIC you have, since that one doesn't exist.

I compiled the following test program with vs. 5.032 and vs. 4.121.
I then compared the two .LST files with ExamDiff (vs. 1.9).
http://www.prestosoft.com/edp_examdiff.asp
Code:

#include <16F886.h>
#fuses INTRC_IO, NOWDT
#use delay(clock=4M)

#use rs232(baud=57600, UART1, PARITY=N, BITS=8, ERRORS, STOP=1, DISABLE_INTS, stream=UART_NO_PARITY)
#use rs232(baud=57600, UART1, PARITY=O, BITS=8, ERRORS, STOP=1, DISABLE_INTS, LONG_DATA, stream=UART_PARITY)
//======================
void main()     
{
int16 long_c;
int8 c;

setup_uart(57600, UART_PARITY);
long_c = fgetc(UART_PARITY);
fputc(long_c, UART_PARITY);

setup_uart(57600, UART_NO_PARITY);
c = fgetc(UART_NO_PARITY);
fputc(c, UART_NO_PARITY);

while(TRUE);           
}
 


Here is the .LST file for the two setup lines for vs. 4.121:
Code:
.................... setup_uart(57600, UART_PARITY); 
008E:  BSF    STATUS.RP0
008F:  BSF    BAUDCTL.BRG16
0090:  MOVLW  10
0091:  BCF    STATUS.RP1
0092:  MOVWF  SPBRG
0093:  MOVLW  00
0094:  MOVWF  SPBRGH
0095:  MOVLW  E6
0096:  MOVWF  TXSTA
.................... 
.................... setup_uart(57600, UART_NO_PARITY);
00A2:  BSF    STATUS.RP0
00A3:  BSF    STATUS.RP1
00A4:  BSF    BAUDCTL.BRG16
00A5:  MOVLW  10
00A6:  BCF    STATUS.RP1
00A7:  MOVWF  SPBRG
00A8:  MOVLW  00
00A9:  MOVWF  SPBRGH
00AA:  MOVLW  A6
00AB:  MOVWF  TXSTA


Here is the .LST file for vs. 5.032. Notice that it configures the RCSTA
register for parity/no parity, but your version does not:
Code:
.................... setup_uart(57600, UART_PARITY); 
008F:  BSF    STATUS.RP0
0090:  BSF    BAUDCTL.BRG16
0091:  MOVLW  10
0092:  BCF    STATUS.RP1
0093:  MOVWF  SPBRG
0094:  MOVLW  00
0095:  MOVWF  SPBRGH
0096:  MOVLW  E6
0097:  MOVWF  TXSTA
0098:  MOVLW  D0     <== *** vs. 5.032 puts 0xD0 in RCSTA
0099:  BCF    STATUS.RP0
009A:  MOVWF  RCSTA
.................... 
.................... setup_uart(57600, UART_NO_PARITY);
00A5:  BSF    STATUS.RP0
00A6:  BSF    STATUS.RP1
00A7:  BSF    BAUDCTL.BRG16
00A8:  MOVLW  10
00A9:  BCF    STATUS.RP1
00AA:  MOVWF  SPBRG
00AB:  MOVLW  00
00AC:  MOVWF  SPBRGH
00AD:  MOVLW  A6
00AE:  MOVWF  TXSTA
00AF:  MOVLW  90    <== *** vs. 5.032 puts 0x90 in RCSTA
00B0:  BCF    STATUS.RP0
00B1:  MOVWF  RCSTA


You could fix this manually with a #byte statement to define RCSTA
and then write to it directly in your program. Example:
Code:

#byte RCSTA = getenv("SFR:RCSTA")
.
.
.
if (serial_setup.parity){
  setup_uart(57600, UART_PARITY);
  RCSTA = 0xd0;  // Fix for vs. 4.121
}
else{
  setup_uart(57600, UART_NO_PARITY);
  RCSTA = 0x90;  // Fix for vs. 4.121
}



Quote:
If I flip the order of my '#use rs232' directives

That's because the last #use rs232() statement is the one used by
the compiler to configure the UART setup code at the start of main().
If you flip the statements, you change the initial setup code.
This setup code can be seen in the .LST file.

In your case, the parity stream is the last one, so RCSTA is setup for
parity. Your problem then occurs because of a bug in setup_uart() in
vs. 4.121, where it fails to setup RCSTA. So RCSTA stays setup for
parity, when you wanted it to change it to no parity.
MrColin



Joined: 05 Sep 2014
Posts: 13

View user's profile Send private message

PostPosted: Mon Dec 15, 2014 4:34 am     Reply with quote

Wow. Thanks for that incredibly full answer. Setting that bit-flag worked straight away! Parity is now restored.

Also, it was the PIC16F690. Dyslexic fingers said it was a 960.

Thanks again!
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Mon Dec 15, 2014 5:22 am     Reply with quote

Hmm, you're probably aware of all this stuff, but just in case, and for others reading the thread who may not be so sure, its probably worth talking a bit about parity and data bits in async comms.

I'm not sure about parity on CCS C comms, but generally the parity bit is separate from the data bits. So 8N1 is eight data bits, no parity and one stop bit, so, including the start bit, that's ten in all. 8O1 would be one start, eight data bits, one parity bit and one stop bit, so eleven bits in all.

ASCII is, or was for much of its life, a seven bit code, often with even parity, one or two stop bits, i.e. 7E1 or 7E2. Two stop bits was often only needed on mechanical terminals, such as the classic ASR33. VDUs generally were often fast enough to be able to cope with just one stop bit. Parity was often ignored, and so over time people tended to use what would be the parity bit for data giving eight bits of useful data, but without parity, i.e. the familiar 8N1. The equivalent of 8N1 with odd parity is 7O1, not 8O1, which gives a longer, and incompatible frame. Of course, if the parity is to be generated by software rather than hardware, then seven bits plus parity and one stop bit can be transmitted with hardware set to 8N1.

I'm not sure what the CCS code/Microchip hardware does - I've not had to write code to transmit and receive async comms with parity for a decade or more - I do everything 8N1. I do use Modbus, but I use the CCS drivers for that, and it deals with the issue by having a fixed 8 (RTU) or 7 (ASCII) data field and one stop bit if there's parity e.g. 8E1, and two if there's not, e.g. 8N2. But for a given mode, ASCII or RTU, the data frames are always the same length regardless of whether parity is used or not.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group