|
|
View previous topic :: View next topic |
Author |
Message |
fobi
Joined: 26 Feb 2015 Posts: 15 Location: BG
|
Hardware uart parity |
Posted: Thu Feb 26, 2015 1:28 pm |
|
|
Hello,
I'm new to " C for microcontrollers ". I read what i found about parity in this forum, but it seems not so clear for me.
I know what is PIC and PIC_UART , but i am puzzled from compiler.
My question is why this not works with HW uart ?
Code: |
#use rs232(uart2, baud=9600, bits =8, parity=o, stop =1, stream=str2 )
#use rs232(uart1, baud=9600, bits =8, parity=o, stop =1, stream=str1 )
...
fprintf(str2,"whatever here\n\r");
|
May be will work with software uart ... ? Anyway i need the 2 uarts on 18f23k22 with interrupts and 9600-8-ODD-1.
After little surfing around, i wrote this:
Code: |
#use rs232(uart2, baud=9600, bits =9, parity=n, stop =1, stream=str2 )
#use rs232(uart1, baud=9600, bits =9, parity=n, stop =1, stream=str1 )
...
int8 getParity (char p) {
p = p ^ (p >> 4 | p << 4);
p = p ^ (p >> 2);
p = p ^ (p >> 1);
return p & 1;
}
...
void out_chr( char c ) {
// if(getParity(c)==1)
// TX9D2 = TRUE;
// else
// TX9D2 = FALSE;
TX9D2 = getParity(c); // even this works ? Nice :)
while(!TXSTA2_TRMT);
TXREG2 = c;
}
...
out_chr("whatever here\n\r");
|
... which works fine.
My question is do i really need to go this way or there is a way to "#use rs232" (and associated puts and gets) somehow ?
Thanks |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Thu Feb 26, 2015 1:40 pm |
|
|
OK I'm curious..
I have to ask WHAT device are you connecting to that need 8 bits, ODD parity? I haven't seen any 'normal' device needing parity for 2 decades.
Ever since UARTs become a 40 pin device instead of a handful of 7400 chips, there's been very little reason to have 'parity'.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Thu Feb 26, 2015 1:48 pm |
|
|
The hardware UART on chips like PIC16's/18's, does not support parity.
You can generate it by using the 9bit option, and setting the 9th bit to the required parity. Efficient code to do this, has been posted here. On some compiler versions, the compiler will attempt to simulate parity this way. It sounds as if your compiler version is one that doesn't...
Look at the code at the end of:
<http://www.ccsinfo.com/forum/viewtopic.php?t=21363>
Which generates parity efficiently. |
|
|
fobi
Joined: 26 Feb 2015 Posts: 15 Location: BG
|
|
Posted: Thu Feb 26, 2015 3:00 pm |
|
|
thanks!
temtronic, the device is Wincor Nixdorf LCD, controlled by VT100 (which i haven't seen from 3.14 decades :))
I need to capture 2 displays, interpret the commands and send the data to DVR as one stream. I almost wrote it in asm, but it seems to me a good task to learn a little C. Not so hard or easy task ....
Ttelmah, i know the PIC hardware well, now i know that #use depends of compiler version.
Thanks for the link, i will check it. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Thu Feb 26, 2015 3:04 pm |
|
|
as a comment, remember you can just have your 'putc_with_parity' function defined, and call this from things like printf, with:
printf(putc_with_parity,"format",values);
Makes it tidier. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Thu Feb 26, 2015 6:57 pm |
|
|
I googled 'Wincor Nixdorf LCD' and downloaded a manual for the BA73A and didn't see anything that said '8 bit + parity' rather lots of info to hookup to a PC, and I don't think PC com ports use 8 bits + parity.
Maybe you've got a 'special' display, it's just 'uncommon' to have 8+Parity.
Now the VT100 is 'new' to me as I used to fix the VT52s when they first came out...then again I was also fixing ASR33s then too.....
Jay |
|
|
fobi
Joined: 26 Feb 2015 Posts: 15 Location: BG
|
|
Posted: Thu Feb 26, 2015 11:05 pm |
|
|
h**p://www.wincor-nixdorf.com/internet/cae/servlet/contentblob/49002/publicationFile/76133/BA63_Display_Operating_Manual_english.pdf
The jumpers sets on page 18 do not depend on me.
In fact i did 1 channel VT100 to ESC/p about 6 years ago for GeoVisison. They still working good. But now i have to merge 2 displays, because the DVR do not allow 2 overlays from 2 streams to one camera window.
I will post some pictures later today.
Ttelmah, this didn't work for me
Code: |
#use rs232(uart2, baud=9600, bits =8, parity=o, stop =1, stream=cash2 )
#use rs232(uart1, baud=9600, bits =8, parity=o, stop =1, stream=cash1 )
...
void fput_chr( char d ) {
fputc(d,cash2);
}
...
fput_chr("whatever here\n\r")
|
Any attempt to use 'parity=o' crashes. Even worst, sometimes i got message that 'interrupts will be disabled at line ...' but the line number do not exist in my code ...
I will be happy to see part of working code. Otherwise i will fire the #use RS232 and i will write my own |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Fri Feb 27, 2015 2:24 am |
|
|
You misunderstand.
You'd have to have a function like:
Code: |
#use rs232(uart1, baud=9600, bits =9, stop =1, ERRORS, stream=str1)
int8 find_parity(int8 data)
{
#asm
swapf data, W
xorwf data, F
rrf data, W
xorwf data, F
btfsc data, 2
incf data, F
movf data, W
andlw 1
movwf _return_
#endasm
}
void fput_chr( char data)
{
//add 9th bit as parity to the data
if (find_parity(data))
bit_clear(RS232_ERRORS,7);
else
bit_set(RS232_ERRORS,7);
fputc(data,str1);
}
//Then you can just use
printf(fput_chr,"What you want to send/n");
//and 9bit data will automatically be sent, and efficiently. :)
|
I haven't checked whether that will give even or odd. You may need to reverse the set/clear if I've got this the wrong way round. Think I've got it right.... |
|
|
fobi
Joined: 26 Feb 2015 Posts: 15 Location: BG
|
|
Posted: Fri Feb 27, 2015 3:43 am |
|
|
i see ...
this 90% answers my question, thank you. I came up with similar solution
Code: |
void out_chr( char c ) {
TX9D2 = getParity(c); // however calculated
while(!TXSTA2_TRMT);
TXREG2 = c;
}
/////////////////////////////////
out_chr("whatever here\n\r");
|
The rest 10% question is how to distinguish RS232_ERRORS variable for 2 HW uarts ?
If i can not do that, the gets(), puts() and fprints() become useless, so either #USE RS232 . I can set uarts by SFRs instead loading library that i'll never use.
As i said, i'm new to C, may be i'm wrong.
Thanks for you help.
http://oi57.tinypic.com/bhn4pk.jpg
old and the new box, bad photo |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Fri Feb 27, 2015 4:37 am |
|
|
You seem to be determined to find a reason for not doing this in C... Just specify "errors" in the use rs232 and let the compiler deal with them. There is no "library" as such, and SFRs are rarely needed to be used in CCS C.
Regardless of that, while that document doesn't explicitly state it, I'll wager it DOES NOT need 8 bit data plus odd parity - 8. O, 1. It's almost certainly straight ASCII, which is seven bit, and therefore like most serial devices uses 7 bit data plus odd parity - 7, O, 1 - no need for nine bit data. When parity is turned off, it'll use 8 bit data with the last bit zero - 8, N, 1. Nine bit serial data is rare. It always was rare; not unheard or but certainly unusual, so much so that if it seems to be needed, then check the spec, and check it again, as it probably isn't 9 bit at all. As you've seen, the PIC hardware doesn't generate or check it (and I suspect the POS unit won't check it either!). That's not because parity is difficult to generate in hardware - its trivial, just a few exclusive or gates, and far easier than in software, which isn#t exactly hard - its because parity was already essentially obsolete when the first PIC appeared.
Generating parity in software is straightforward enough. There are several methods, and you've already got one. Bear in mind that ASCII data is seven bit, while chars are eight bit. So just get that working to generate the *eighth* bit, rather than ninth, and you should be good.
For such a receive-only device (while the spec. talks of "full-duplex" operation,I couldn't see anywhere where it sends anything back) as this, you could let the compiler use a software UART. That will sort out parity for you, but remember you only need to send it. As there is nothing coming from the unit, there is no need to check parity. Even if there was parity on incoming data, I'd strongly suggest you simply ignore it, treating the ASCII data as eight bit and masking out the top bit. Also send-only operation doesn't need interrupts. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Fri Feb 27, 2015 7:56 am |
|
|
Like my cat ,curiosity got the better of me, so I downloaded the VT100 manuals(couldn't find mine)...and the serial interface is based on the Intel 8251A so 8 bits and Parity is a valid setup. Now finding PARTS for one could be 'fun'.
It's be easy to confirm the setup though, turn it over, check the dip switches. We always used 8-none and I used to make RS232-current loop adapters to go the distance( 1/2 mile) to the BOF.
I really doubt it's 8+parity though...
Jay |
|
|
fobi
Joined: 26 Feb 2015 Posts: 15 Location: BG
|
|
Posted: Fri Feb 27, 2015 8:11 am |
|
|
Hi RF,
The device surely uses 9600 8-ODD-1. I solved this task for one LCD to overlay in 2010. I did that with hw uart to receive and software uart to transmit with PIC16F88. And ofcourse, i set receiving to 9 bits and didn't care for parity . The output stream was 19200-8-N-1. I had no loss of symbols.
Now i have to merge 2 LCDs to one ESC/P stream. In my expirience software serial routines waits a byte to be received. I can not wait because i don't know which one is receiving. So i'm using hw uarts and interrupts. Well, (i guess) i can check kbhit(stream1) and kbhit(stream1) in loop and deal without interrupts with getc(). Or using getc() in interrupts. ok
So far my receive routines looks like this.
Code: |
#int_RDA
void RDA_isr(void)
{
tmo_A = 0; // clear timeout
rxA = RCREG1;
switch(cmd_A){ // command in progress flag
case TRUE:
cmb_A ++; // command byte counter
parse_cmd_A();
break;
case FALSE:
if(rxA==0x1B){ // new command start
cmd_A = TRUE;
}
else{ // receive data here
buff_A[cnA] = rxA;
cnA++;
}
break;
}
}
|
I am receiving somewhat as this : ESC [ Py ; Px10 Px01 H {DATA}
Because the streams are 2 and i need to merge them, it is good idea to use at least twice faster output. I can use one of the uarts to transmit. But on PIC i can not set different speed for receive and transmit. So i am afraid that i could lost characters if i am doing that. The same apply to software output, because i have to switch off the interrupts during transmit. There is competitions everywhere! So my block diagram become like this:
RS232 (1,2) ->[VT100 to ESC/P] ->SPI->[SPI to UART]-> [TTL to 485], with PIC18F23K22 and PIC12F1822.
In my hardware i have option to use uart to transmit bypassing [SPI to UART]. Just to see if it is possible to receive and transmit with one speed. In addition, i can use this out as console out to monitor commands.
About C i'm learninig, this is my first attempt and my code looks like ASM written in C. I know
I have to say, that you all helped me a lot to figure out how to make the code more C-like. For the first time i got 110% answer
a bit better picture. Empty slot for SPI to UART chip.
http://oi58.tinypic.com/1ow2mf.jpg
Old working units with 9600-8-ODD-1
http://oi58.tinypic.com/rirjhl.jpg
PS: I am not on the picture
Last edited by fobi on Fri Feb 27, 2015 8:39 am; edited 2 times in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Fri Feb 27, 2015 8:35 am |
|
|
RS232_ERRORS, has the value from the last getc met, or is used for the next putc met.
So if you set it in the routine like I show, this applies to the next fputc, whichever stream this involves. If you read a character with fgetc, then RS232_ERRORS contains the status and 9th bit from that read, until you do another one.
So you can use exactly the same code for two UARTs, by just having a second copy of the fput_chr routine, called perhaps fput_chr2 (for the second UART), and using the stream for this UART in it.
The point is of course that written like this the parity calculation is massively quicker, and of course you can use the formatting abilities of printf.
As a comment though, just put a jumper on JP2 of the display. This turns parity off.
Makes everything a lot simpler. |
|
|
fobi
Joined: 26 Feb 2015 Posts: 15 Location: BG
|
|
|
fobi
Joined: 26 Feb 2015 Posts: 15 Location: BG
|
|
Posted: Fri Feb 27, 2015 8:49 am |
|
|
[quote= ...
As a comment though, just put a jumper on JP2 of the display. This turns parity off.
Makes everything a lot simpler.[/quote]
I have to write 1kg paper (in German) with explanations to get permission to pull in the jumper. And i have to be persuasive ... |
|
|
|
|
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
|