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 CCS Technical Support

PIC16F877A: Need to use timer0 int with serial data input

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



Joined: 02 Aug 2010
Posts: 2

View user's profile Send private message

PIC16F877A: Need to use timer0 int with serial data input
PostPosted: Mon Aug 02, 2010 5:20 pm     Reply with quote

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: 19539

View user's profile Send private message

PostPosted: Tue Aug 03, 2010 2:01 am     Reply with quote

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

View user's profile Send private message Send e-mail

Re: PIC16F877A: Need to use timer0 int with serial data inpu
PostPosted: Tue Aug 03, 2010 7:11 am     Reply with quote

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: 19539

View user's profile Send private message

PostPosted: Tue Aug 03, 2010 7:23 am     Reply with quote

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

View user's profile Send private message

Thank you
PostPosted: Thu Aug 05, 2010 9:03 am     Reply with quote

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.
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