|
|
View previous topic :: View next topic |
Author |
Message |
kensplace
Joined: 02 Jul 2005 Posts: 1
|
serial polling, software rs232 and timer0 |
Posted: Sat Jul 02, 2005 7:01 pm |
|
|
I am still learning, and having a conceptual problem with serial and timer0...
I have managed so far to control a stepper motor, and lcd, and serial tx/rx using a pic linked to a max3701 port expander. The pic16f630 in use didnt have a spi port, so I wrote my own routine, which seems to be working well. The rs232 uses a max232 chip for level shifting.
I would like to have the serial port read and buffered, its using the ccs software rs232 routines, as the pic does not have a built in uart
I could either re-wire the board to use port a and use the interupt on change to use that for the rs232 reading via interrupts, or I could
set up timer0 to interupt every x microseconds thereby polling the serial port on a regular basis. Polling seemed the easier option.... Plus I would learn about timers, so I decided to see what happens if I went that route for now.
If I was to poll the serial via timed interrupts would I be correct in thinking the following..
I need to poll at 10 times the bit rate, so for 9600 baud that would mean
interupting at
1 / (9600x10) = 1.0416666666666666666666666666667e-5
ie approx once every .0000104 seconds
and running with a 20Mhz crystal would give a clock speed of
1 / (20000000 / 4) = 0.0000004
0.0000104 seconds required interupt interval
0.0000004 seconds per timer clock
0.0000104 / 0.0000004 = 26 timer clocks
so no prescaler, and timer set to count to 26 would be correct?
Or have I got the calculation totally wrong somewhere?
Wish I had a scope, could measure the output to see if it is right....
I am trying with the following simple little test routine
Code: |
#include <16f630.h>
#fuses HS,NOWDT,NOPROTECT,NOMCLR,BROWNOUT,PUT
// High speed osc, No WatchDog Timer, No Code protext, NoMclr, Brownout reset enabled, Power up timer enabled.
#use delay(clock=20000000) // HS - High speed crystal osc 20hm, 30picofarad caps
int serin;
#USE RS232(BAUD=9600 ,XMIT=PIN_C4, RCV=PIN_C5, bits=8, parity=n )
setup_counters(RTCC_INTERNAL, RTCC_DIV_1);
set_timer0(230);
#INT_TIMER0
void serial_timer()
{
set_timer0(230);
if(kbhit())
{
serin = getc();
}
}
void main()
{
delay_ms(500);
puts ("STARTED OK.");
set_timer0(0);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
while (1==1)
{
if (serin != 0)
{
disable_interrupts(INT_RTCC);
disable_interrupts(global);
puts ("*********** FROM INTERUPT *********");
putc(serin);
serin = 0;
enable_interrupts(global);
enable_interrupts(INT_RTCC);
}
}
}
|
Serial on its own, without any interupts works fine, but the example above hardly ever picks up a character, so I figure I either have the setting of the timer way out, or Im doing something else silly..... Can someone point out where Im going wrong please? |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Sat Jul 02, 2005 9:17 pm |
|
|
There is a mistake in your numbers. Quote: | 1 / (20000000 / 4) = 0.0000004 |
The result should be 1 / (20000000 / 4) = 0.0000002 This will give you a count of 52 timer ticks.
A problem with this type of solution if that you introduce errors as a result of interrupt handler overhead. The time it takes to interrupt the current task, right up to the point where you reset the timer in the interrupt handler. There are a couple of ways of dealing with this. You know that the error will be relatively constant (assuming you do not enable and disable interrrupts in the main line around large blocks of code. So you could subtract a correction factor form your number. (Use a count of 50 for example).
Another option is to choose a different tye of timer. I do not know the PIC you are using but some, such as the 18F PICs, have timer 2 which can be configured with a specific target point value. When the count hits this value it is automatically set to zero at the next timer interval. If I wanted a constant interrupt source at 52 timer ticks, I would set the PR register to 51. This provides me with an accurate time base.
Another method for PICs that do not have this type of timer if to do as you have done but use the PIC's timer to correct itself.
Crudely put Timerx = 230-Timerx _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Sun Jul 03, 2005 7:55 am |
|
|
Quote: |
I could either re-wire the board to use port a and use the interupt on change to use that for the rs232 reading via interrupts, or I could
set up timer0 to interupt every x microseconds thereby polling the serial port on a regular basis. Polling seemed the easier option.... Plus I would learn about timers, so I decided to see what happens if I went that route for now.
|
IMO, choosing that route all you get is to null other functionalities of a PIC and it's not
the best way to learn how timers works. Use #INT_EXT to ovoid Rx polling overhead
and then you can use some timers if you want to write your own getc() function.
Important key to know is that your code ignore the edge of the START bit and by
extension the BIT-samples would be done out of the right frame.
The code you posted canīt receive 2 consecutive characters. Am I wrong?.
Keep well,
Humberto |
|
|
kensplace
Joined: 02 Jul 2005 Posts: 1
|
thanks |
Posted: Sun Jul 03, 2005 7:58 pm |
|
|
Thanks, I will go down the route of getting the serial to interrupt, instead of using a timer. Just changed board so ra2 is the rx, and got a basic interupt working on it for a single char. Just need to write the buffer now, some nice examples on the forum I will look into. |
|
|
|
|
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
|