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

18f45j11 and 2 UARTs
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

18f45j11 and 2 UARTs
PostPosted: Sat Aug 28, 2010 9:52 pm     Reply with quote

Hi,
I have a little problem and I wonder what am I doing wrong?
Basically I have 2 UARTs and they mostly are chaotic, they work and then not and one time I have nice comms and in another time I have rubbish on ports like this:

...command received from eth:
SSÿSÿSÿSÌÌ (it should be TEXT captured from UART2, but in next minute it will work well and then stop again)
EOL

I use Xport to talk to PIC on UART2 and RS485 on UART1.

It looks to me like I do not initiate something on ports and they go to sleep or IRQ fires up too late and collects rubbish from port.

This is my main program:
Code:

#include <18F45J11.h>
#device adc=10
#DEVICE HIGH_INTS=TRUE
#include <ctype.h>
#include <stddef.h>
#include <string.h>

//=========DEFINE====================
#define Rx_In         PIN_C7
#define Tx_Out         PIN_C6
#define Tx_On         PIN_B1
//===================================
//===================================

#use delay (clock=10M)

#FUSES WDT2048
#FUSES HS
#FUSES H4_SW
#FUSES STVREN
#FUSES NOPROTECT
#FUSES FCMEN
#FUSES PRIMARY
#FUSES NOWPCFG
#FUSES WPBEG
#FUSES WPDIS
#FUSES LPT1OSC
#FUSES T1DIG
#FUSES MSSPMSK7
#FUSES DSWDT2147483648
#FUSES DSWDT
#FUSES DSBOR
#FUSES RTCOSC_T1
#FUSES DSWDTOSC_INT
#FUSES NOCPUDIV
#FUSES WPFP

#pin_select U2TX = PIN_C5
#pin_select U2RX = PIN_C4

#use rs232(uart1,SAMPLE_EARLY,baud=115200,xmit=Tx_Out,rcv=Rx_In,parity=N,bits=8,stop=1,stream=bus,restart_wdt,errors,DISABLE_INTS,TIMEOUT=5)
#use rs232(uart2,SAMPLE_EARLY,baud=115200,parity=N,bits=8,stop=1,stream=eth,restart_wdt,errors,DISABLE_INTS,TIMEOUT=5)

and irq:
Code:

#int_RDA2 HIGH

void comms_eth(void) {

char capture;
int next_ind = 0;
int strn_temp_eth[],a;

   do {
         capture = fgetc(eth);
         strn_temp_eth[next_ind] = capture;
         next_ind++;
         } while (strn_temp_eth[next_ind] != 0x0D);

            for (a=0;a<next_ind;a++) {
                rx_eth[a] = strn_temp_eth[a];
            }
} //void

Thnx for help.
_________________
Help "d" others and then you shell receive some help from "d" others.
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Sat Aug 28, 2010 10:29 pm     Reply with quote

Code:
#int_RDA2 HIGH

void comms_eth(void) {
char capture;
int next_ind = 0;
int strn_temp_eth[],a;

   do {
      capture = fgetc(eth);
      strn_temp_eth[next_ind] = capture;
      next_ind++;
   } while (strn_temp_eth[next_ind] != 0x0D);

   for (a=0;a<next_ind;a++) {
      rx_eth[a] = strn_temp_eth[a];
   }
} //void



You can't do this this way.

You want to get your char (or more if there's a FIFO) and add them to your string (using a static pointer) and then exit.

If you sit in the ISR like you are with the DO {} While();

the rest of your program will suffer.

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Sat Aug 28, 2010 10:38 pm     Reply with quote

Oh,

and I just looked... but it appears from the datasheet that there is no high-priority for UART1 or UART2. Only standard priority.

Feel free to verify in the .LST file.

I also don't think "SAMPLE EARLY" has effect with hardware UARTs.

A getc() normally samples data in the middle of a bit time. This option causes the sample to be at the start of a bit time. May not be used with the UART

I think "DISABLE_INTs" is also not needed with hardware UARTs either.

Will cause interrupts to be disabled when the routines get or put a character. This prevents character distortion for software implemented I/O and prevents interaction between I/O in interrupt handlers and the main program when using the UART.



Lastly, RESTART_WDT probably isn't needed on UART2 because you're doing interrupts. So you don't sit and spin on getc(); waiting for a char. You only try to get them when the interrupt signals there's something worth getting.

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D


Last edited by bkamen on Sat Aug 28, 2010 10:43 pm; edited 2 times in total
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Sat Aug 28, 2010 10:40 pm     Reply with quote

thnx

by the way, what is the other way to collect data from buffer when it is ready?
how d I get this data without using do and loading it from buffer into string or var?
_________________
Help "d" others and then you shell receive some help from "d" others.
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Sat Aug 28, 2010 10:48 pm     Reply with quote

Linuxbuilders wrote:
thnx

by the way, what is the other way to collect data from buffer when it is ready?
how d I get this data without using do and loading it from buffer into string or var?


You only get a few (if more than one, depending on the PIC) chars at a time before an IRQ gets serviced. In your case (similar to one I had for GPS) you're looking for a CR or LF.

Do you have a max string length? is there an STX char of some sort (like the NMEA's $ char?)

If so, you can build a state machine that starts when it sees the first "$" (as an example) or maybe an STX come in...
From there, the state machine then gathers chars into the string until the string max size is hit or the ETX (or CR|LF) comes through.

Then the ISR raises a flag to tell the rest of your program there's data ready.

From there, you can have the ISR wait for the processing occur (depends on the types of packets if you will need a ring buffer or just something that operates packet by packet (or sentence like NMEA).

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Sat Aug 28, 2010 11:10 pm     Reply with quote

thnx,
To be more specific, what would you use to replace
Code:

do {
     } while

loop?

In my application I limit amount of chars to X by
Code:

} while ((strn_temp_eth[next_ind] != 0x0D) || (next_ind < X));

This way I break loop if my string is more than X chars. From my understanding you say that do {} is not right way to get data from buffer? Do I understand it properly?

thnx
_________________
Help "d" others and then you shell receive some help from "d" others.
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Sat Aug 28, 2010 11:34 pm     Reply with quote

This has fixed instability:
Code:

#use rs232(uart1,SAMPLE_EARLY,baud=115200,xmit=Tx_Out,rcv=Rx_In,parity=N,bits=8,stop=1,stream=bus,restart_wdt,errors,DISABLE_INTS,TIMEOUT=5)
#use rs232(uart2,SAMPLE_EARLY,baud=115200,parity=N,bits=8,stop=1,stream=eth,restart_wdt,errors,DISABLE_INTS,TIMEOUT=5)
#use fixed_io(A_outputs=PIN_A1,PIN_A2,PIN_A3,PIN_A5)
#use fixed_io(B_outputs=PIN_B2,PIN_B3,PIN_B4,PIN_B5,PIN_B6,PIN_B7)
#use fixed_io(C_outputs=PIN_C0,PIN_C1,PIN_C2,PIN_C3)
#use fixed_io(D_outputs=PIN_D0,PIN_D1,PIN_D2,PIN_D3,PIN_D4,PIN_D5,PIN_D6,PIN_D7)
#use fixed_io(E_outputs=PIN_E0,PIN_E1,PIN_E2)

It looks like if all pins are not mapped to a function then somehow multiplexer affects operation of C4/C5.

thnx
_________________
Help "d" others and then you shell receive some help from "d" others.
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Sun Aug 29, 2010 1:15 am     Reply with quote

Linuxbuilders wrote:
thnx,
To be more specific, what would you use to replace
Code:

do {
     } while

loop?

In my application I limit amount of chars to X by
Code:

} while ((strn_temp_eth[next_ind] != 0x0D) || (next_ind < X));

This way I break loop if my string is more than X chars. From my understanding you say that do {} is not right way to get data from buffer? Do I understand it properly?




What I'm saying is:

You have to enter the ISR, get the chars in the RCREG (if the PIC supports more than 1) then exit the ISR.

What you have waits for the char to == 0x0D. The || next_ind < X is new and I don't know what other code is in there.

Anyway... you can't sit in the ISR while waiting for some char to == 0x0D.

Let say your PIC only supports 1 char and has no FIFO.

you'd enter the ISR, get the char, save it, exit the ISR whether the char is 0x0D or not.

Now, you also want to check to make sure you don't save a char past the end of your string -1 (to save room for the NULL if important).

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Sun Aug 29, 2010 4:37 am     Reply with quote

Thnx, man
I didn't think about it this way. It makes a lots of sense, I will redesign IRQ routine. It makes so much sense that I can't believe that I did not think about it before.

thank you very much for this post. When I get it written I will post some code for some blokes like me lost in time and space.

thank you very much.
_________________
Help "d" others and then you shell receive some help from "d" others.
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Sun Aug 29, 2010 10:33 am     Reply with quote

No problem,

Good luck!

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Mon Aug 30, 2010 2:44 am     Reply with quote

Quick question:

When I receive CHAR on UART1 then CCS is turning off IRQs by default as per:

#use rs232(uart1,SAMPLE_EARLY,baud=115200,xmit=Tx_Out,rcv=Rx_In,parity=N,bits=8,stop=1,stream=bus,restart_wdt,errors,DISABLE_INTS,TIMEOUT=5)
#use rs232(uart2,SAMPLE_EARLY,baud=115200,parity=N,bits=8,stop=1,stream=eth,restart_wdt,errors,DISABLE_INTS,TIMEOUT=5)

So when I am receiving data on UART1 then my UART2 is not working? Do I understand it properly? So if it is the case, how do I make both UARTs working independently in the same time?

thnx


another question:

do I really need IRQ RDA? I think that with 40MHz pic I could easily sample data with kbhit according to this:

##################
Function: If the RS232 is under software control this function returns TRUE if the start
bit of a character is being sent on the RS232 RCV pin. If the RS232 is
hardware this function returns TRUE if a character has been received and is
waiting in the hardware buffer for getc() to read. This function may be used to
poll for data without stopping and waiting for the data to appear. Note that in
the case of software RS232 this function should
##################

and just load buffer with data as it goes and process whole strings? Right?
Like this:

void comms_from_bus(void) {
if (kbhit(bus)) {
capture_bus[next_in_bus] = fgetc(bus);
next_in_bus++;
}
} //void
_________________
Help "d" others and then you shell receive some help from "d" others.
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Aug 30, 2010 6:44 am     Reply with quote

Linuxbuilders wrote:
Quick question:

When I receive CHAR on UART1 then CCS is turning off IRQs by default as per:

#use rs232(uart1,SAMPLE_EARLY,baud=115200,xmit=Tx_Out,rcv=Rx_In,parity=N,bits=8,stop=1,stream=bus,restart_wdt,errors,DISABLE_INTS,TIMEOUT=5)
#use rs232(uart2,SAMPLE_EARLY,baud=115200,parity=N,bits=8,stop=1,stream=eth,restart_wdt,errors,DISABLE_INTS,TIMEOUT=5)

So when I am receiving data on UART1 then my UART2 is not working? Do I understand it properly? So if it is the case, how do I make both UARTs working independently in the same time?



I think those are for software UARTs only. You don't need them (and I think I already mentioned that), I think you should delete that in both #use rs232 statements.

I use a PIC46J11 with both UARTS running.
UART1 is a control console and UART2 is a GPS at 4800bps.

-- with no problems.

Also, "sample early" doesn't help you for hardware UARTS either. You could get rid of those too.


Quote:


another question:

do I really need IRQ RDA? I think that with 40MHz pic I could easily sample data with kbhit according to this:

##################
Function: If the RS232 is under software control this function returns TRUE if the start
bit of a character is being sent on the RS232 RCV pin. If the RS232 is
hardware this function returns TRUE if a character has been received and is
waiting in the hardware buffer for getc() to read. This function may be used to
poll for data without stopping and waiting for the data to appear. Note that in
the case of software RS232 this function should
##################

and just load buffer with data as it goes and process whole strings? Right?
Like this:

void comms_from_bus(void) {
if (kbhit(bus)) {
capture_bus[next_in_bus] = fgetc(bus);
next_in_bus++;
}
} //void


That all depends. Do you think your main loop always has enough processing cycles to NEVER miss a char?

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
Ttelmah



Joined: 11 Mar 2010
Posts: 19337

View user's profile Send private message

PostPosted: Mon Aug 30, 2010 9:05 am     Reply with quote

Add to the above.
It is not missing a 'character', but missing a _bit_.
When using a 'software UART', you _must_ sample the incoming data line _more often_ than twice per bit time. At 115200bps, this means you must be waiting in a getc, or calling kbhit, at intervals no greater than every 4uSec. Even at 10MIPS, this only gives 40 instruction times between calls....

Seriously, the whole 'point' of UART hardware, is because it is hard to reliably receive/transmit serial data _ especially at high speed_, using software alone. Using the CCS software UART, comms are 'half duplex' (only one direction at a time), and 'mono stream' (only one software stream operating at any one time). It is possible to implement 'better' software UART's, to get round these limitations, but only by using timer interrupts being called at frequencies above twice the serial rate - as such 'not possible' at 115200bps.
You will not get two simultaneous serial streams at 115200bps, without using the hardware UARTs, and if you want operations to be going on without interfering with each other, using the IRQ's is the way to go.

Best Wishes
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Aug 30, 2010 9:54 am     Reply with quote

Yup.

What he said.

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Mon Aug 30, 2010 3:33 pm     Reply with quote

Thnx guys, I did my home work yesterday with pdfs and got an understanding of this relations between soft/hard uart.

Now my problem is as follows:

When I receive a string on one port U1 and then process it and then print some message on another port U2 I am missing incoming data on U1. I can't find anywhere information if IRQs are blocked when putc is executed. So lets say I got a string 19 chars incoming and I process it and then print out information based on it and in mean time I get another string incoming then I am missing 30% of it. I believe that during printing my IRQ RDA is not working. Any idea how to sort this out? When I was playing with software uart I did not have this problem because U2 was not based on IRD2 operation.
How do I get this bit working so I can push/pull data between both ports with very fast speed without any losses.

Thank you very much for your help.
_________________
Help "d" others and then you shell receive some help from "d" others.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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