|
|
View previous topic :: View next topic |
Author |
Message |
robsons
Joined: 02 Aug 2010 Posts: 2
|
PIC16F877A: Need to use timer0 int with serial data input |
Posted: Mon Aug 02, 2010 5:20 pm |
|
|
I am making a display with 32 leds and 12 7 segments that are driven from Port B and controlled by Port A with 4-16 decoders so the display is very time sensitive but I also have to receive data from the serial port. I would like for the rtcc interrupt to always occur in time and to get the data properly when timer0 is not interrupting. I've used kbhit and also int_rda and both seem to stall the program when data is received. How can this be resolved?
Code: |
#include <16F877A.h>
#include <stdlib.h>
#include <stdio.h>
#PRIORITY rtcc, rda
#fuses HS, NOLVP, NOWDT
#use delay(clock=20000000, oscillator) // Crystal 20MHz
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
byte CONST LED_MAP[16] =
{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
byte CONST LED_MAP_HIGH[16] =
{0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0};
int i,j,k;
int value[20]={48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48};
byte enLine;
#int_rtcc
void clock_isr()
{
// this is just to control one row of 16 leds I left the other row and the 7 segments out
enline=0b000;
if (j>((value[6]-48)*10+(value[7]-48)))
enline|=0b010;
output_b(LED_MAP[value[j]-48] | LED_MAP_encode[j]);
output_a(enline);
j++;
if (j==16)
j=0;
clear_interrupt(int_rtcc);
}
void get_string(char* s, int max) {
int len;
char c;
--max;
len=0;
do {
c=getch();
if ((c>='0')&&(c<='9'))
if(len<=max)
{
s[len++]=c;
}
} while(c!=13);
s[len]=0;
}
// another interrupt I had working by itself
/*
#int_rda
void serial_isr()
{
get_string(value,15);
}
*/
#int_rda
void serial_isr()
{
ch = getch();
if (ch!=13)
value[k++] = getch();
else
{
value[k] = 0;
k=0;
}
clear_interrupt(int_rda);
}
void main()
{
set_tris_a (0b00000000); // configure pins of PORTA as output
set_tris_b (0b00000000); // configure pins of PORTB as output
//set_tris_d (0b00000000); // configure pins of PORTD as output
//set_tris_e (0b00000000);
output_a(0b000);
output_b(0b00000000);
j=0;
k=0;
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
set_timer0(0);
clear_interrupt(int_rtcc);
clear_interrupt(int_rda);
enable_interrupts(int_rda);
enable_interrupts(int_rtcc);
enable_interrupts(GLOBAL);
while(1)
{
// if (kbhit())
// get_string(value,15);
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Tue Aug 03, 2010 2:01 am |
|
|
Look at ex_sisr.c
The RDA interrupt means that _one_ character is ready to be received. Just one. Get just one character in the interrupt. If you try to get any more, the code has to wait for them to arrive, and in computer terms, this takes an age.
Add 'errors' to your #use rs232 declaration. This should _always_ be present when using the hardware UART, unless _you_ are handling the possible error conditions yourself. If this is not done, the UART can get hung.
As a comment, there might be problems with your maths in int_rtcc. 'value[6]', is going to be 48. *10, will overflow an integer. This is also going to take an unacceptably long time in an interrupt. extract the value into a temporary variable, multiply it by two (rotation...). Then by eight, and add the two results. There is a library routine to do this in one of the standard include files (mult_with10 stdlib.h). Copy this, using an int16, instead of an int32 (which you don't need), and it'll save many dozens of machine cycles...
Best Wishes |
|
|
mkuang
Joined: 14 Dec 2007 Posts: 257
|
Re: PIC16F877A: Need to use timer0 int with serial data inpu |
Posted: Tue Aug 03, 2010 7:11 am |
|
|
robsons wrote: | I am making a display with 32 leds and 12 7 segments that are driven from Port B and controlled by Port A with 4-16 decoders so the display is very time sensitive but I also have to receive data from the serial port. I would like for the rtcc interrupt to always occur in time and to get the data properly when timer0 is not interrupting. I've used kbhit and also int_rda and both seem to stall the program when data is received. How can this be resolved?
Code: |
#PRIORITY rtcc, rda
|
|
The 16 series of PICS do not have interrupt priorities (no IPEN bit as in the 18 series). How does the #PRIORITY work in this case? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Tue Aug 03, 2010 7:23 am |
|
|
It has the same effect as the order in which you define the interrupts. It sets the order in which the interrupt flags are 'polled' when you enter the global interrupt handler. Hence if two interrupts occur at the same or similar times, the first will be serviced first, but one cannot interrupt the other as on the 18 and latter chips.
Best Wishes |
|
|
robsons
Joined: 02 Aug 2010 Posts: 2
|
Thank you |
Posted: Thu Aug 05, 2010 9:03 am |
|
|
Your suggestions helped me out a lot and also reading through my code again I noticed some serious mistakes with the serial function using getch twice by accident most likely skipping my carriage return. It is working very well now thanks again. |
|
|
|
|
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
|