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

RTC Interrupts help, do they stop everything ?

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



Joined: 13 Oct 2007
Posts: 53
Location: Texas

View user's profile Send private message Visit poster's website Yahoo Messenger

RTC Interrupts help, do they stop everything ?
PostPosted: Fri Jan 11, 2008 10:09 pm     Reply with quote

Hello everyone,
This is what i want to do, im going to have a device that does several things but it needs to respond instantly when a button is pressed or time is updated. But it also needs to respond to outside stimulus via the serial in.

I'm using a pic 877, this is what it needs to do
- Act when buttons are pressed (int ?)
- Keep track of time (can loose a few seconds a day, but not minutes)
- Multi-Tasking/Threading ?

So basically my pic will be hooked into motors and relays that are doing stuff that needs to be executed at certain time intervals and/or certain times of day. But it also needs to listen to me if i log onto it through the serial port.

Ive been reading up on interrupts and i was thinking about keeping the time via a internal clock or external clock interrupt. I understand how i could use this to call functions after time has elapsed but lets say after one hour i want it to do something, but that something takes ~5 seconds to perform would that cause my pic to loose 5 seconds or would the function start to run the be "interrupted" by the interrupt and never finish.

So i kind of need it to keep track of time in the background so it does not mess with the operation.

So how does it work ? After the interrupt completes whatever it was doing (keep time, button press) will it return to the function that it was in or will it go back to main ?

And can (should) i have more than one external interrupt ? For example if i had two buttons that would cause something to happen could i have them connected to separate interrupts or is there only one interrupt ? I used to put stuff in all my functions that checked to see if a button was pressed but this would sometimes cause the user to hold down the button before it would react (about 500ms) instead of instant reaction, and its redundant.

Thanks in advance, im just getting a feel for ints and possible rtc before i start to use them. And thanks for your previous help everyone ![/code]
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jan 11, 2008 10:57 pm     Reply with quote

See this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=17189
Also use the forum search page to search for multitasking.
zonemikel



Joined: 13 Oct 2007
Posts: 53
Location: Texas

View user's profile Send private message Visit poster's website Yahoo Messenger

Thanks
PostPosted: Sat Jan 12, 2008 11:22 pm     Reply with quote

Thanks for the link, I used some of the code int that link to make a clock. Now i can just check to see if its a certain time if so do something. I had a horrible time with strtol every time i tried to use it, i would get a error "not enough ram" so i used atio.

Code:

#include <16F877.h>
#device adc=8
#use delay(clock=4000000)
#fuses NOWDT,HS,NOPUT,NOLVP
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#include <string.h>                         // string stuff
#include <stdlib.h>                         // for strtol etc
#include <INPUT.C>                         // for get_string()


// Defines
#define XTal_FQ 4000000
#define T1_FQ (XTal_FQ/4)                   // 1 clock tick = 1 instr.
                                            // cycle = xtal freq / 4
#define MAX_STRING_LEN    5

// Global Variables                         
int32 Ticker;
// current Date/time will be here
int8 Years=0, Months=0, Days=0, Hours=0, Minutes=0, Seconds=0;

/////////////////////////////////////////
// Initilize RTC
/////////////////////////////////////////
void Init_RTC(void)                         // start up the real time clock
{
Ticker = T1_FQ;                             // clock counter = #clocks per second
setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 ); // int 16 bit timer to interupt
                                            // Every 65536 clock cycles
enable_interrupts( INT_TIMER1 );            // Start RTC
}

////////////////////////////////////////
// Process RTC Info
////////////////////////////////////////
#int_TIMER1
void TIMER1_isr()
{
Ticker -= 65536;                            // Decrament by clocks per interrupt
   if ( Ticker < 65536 )                    // If second has expired
   {
   Ticker += T1_FQ;                         // Incrament ticker by clocks/sec
   Seconds++;                               // Incrament Seconds
   }
   
   // turn seconds into everything else
   if(Seconds == 60) {
   Minutes++; Seconds=0;
      if(Minutes == 60) {
      Hours++; Minutes=0;
         if(Hours == 24){
         Days++; Hours=0;
            if(Days == 30){                 // this is wrong you need
                                                    // a long ugly if || situation here
                                                    // for months with different days
            Months++; Days=0;
               if(Months == 13){
               Years++; Months=0;
               } // years
            } // months
         } // days
      } // hours
   } // minutes
}

////////////////////////////////////////
// Beep makes a beep then waits 300 ms
////////////////////////////////////////
void Beep() // sends a beep to the piezo on C0
{
      int k = 0;
      for(k=0; k<255; k++)                   // 255 times not very long but a beep
      {
      output_high(PIN_C0);
      delay_us(100);                         // produces a tone
      output_low(PIN_C0);
      }
      delay_ms(300);                         // need to wait a little b4 doing again



////////////////////////////////////////
// Set the time, i hate dialogs
////////////////////////////////////////
int SetupTime()
{
   char String[MAX_STRING_LEN];                         // for user input
   
   
   printf("Please Give Me the time\N");
   
   printf("\N Years:");
   get_string(String,MAX_STRING_LEN);
   Years = atoi(String);                      // save year
   
   printf("\N Months:");
   get_string(String,MAX_STRING_LEN);
   Months = atoi(String);
                     
   printf("\N Days:");
   get_string(String,MAX_STRING_LEN);
   Days = atoi(String);
                     
   printf("\N Hours:");
   get_string(String,MAX_STRING_LEN);
   Hours = atoi(String);
                       
   printf("\N Minutes:");
   get_string(String,MAX_STRING_LEN);
   Minutes = atoi(String);
   

   printf("\N New Date: %d/%d/%d %d:%d",Months,Days,Years,Hours,Minutes);
                   


}

////////////////////////////////////////
// The Glorious Main
////////////////////////////////////////
void main()
{
   //variables
   char String[45];                         // for user input
   char Input[45];                          //
   int8 Prev_Seconds;

   // startup the pic has been restarted all old data is lost
   printf("Startup, old settings are lost\N");
   SetupTime();                             // get time from user

   // do the rtc stuff
   Init_RTC();                              // startup the rtc
   enable_interrupts( GLOBAL );             // use the ints

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_2(T2_DISABLED,0,1);
   Beep();                                  // startup beep
   printf("Start");                         // print start
   
   // from here on its for ev er
   while(1)
   {
   // print out seconds
   if( Seconds != Prev_Seconds )
   {
      Prev_Seconds = Seconds;
         printf("\r Time: %d/%d/%d %d:%d.%d",Months,Days,Years,Hours,Minutes,Seconds);
   }

   }

}


There is just one thing i dont understand right before the timer1_isr function begins what is the line
Code:
#int_TIMER1


If anyone has any suggestions/improvements feel free. If not i think this thread is resolved, i just wanted to post the code in case someone else comes across this thread searching for the same thing.
_________________
Smart people know how stupid they are.


Last edited by zonemikel on Sun Jan 13, 2008 10:34 am; edited 2 times in total
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

Re: Thanks
PostPosted: Sun Jan 13, 2008 1:02 am     Reply with quote

zonemikel wrote:

There is just one thing i dont understand right before the timer1_isr function begins what is the line
Code:
#int_TIMER1

That declares the following function to be the code that will run when the timer1 interrupt is triggered by overflowing.

Only one instruction can be executed at a time. Instructions are executed sequentially but jumps to different spots in the program can be made. The timer module counts when instructions are executed. When the interrupt occurs, main program (or sub functions) execution stops and interrupt function execution begins. When the interrupt function completes, main program (or sub functions) execution resumes where it left off when the interrupt occured.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Jan 13, 2008 8:38 am     Reply with quote

A minor bug:
Code:
int SetupTime()
{
   char String[5];                         // for user input
   
   ...
   get_string(String,10);
The second parameter for get_string() gives the maximum string length, including terminating zero. The declaration of String and the length specified in every call doesn't match.

Tip: instead of using 'magic values' these kind of errors can be avoided by using a named constant, then you have to change the value in only one location to have effect in all your code.
Code:
#define MAX_STRING_LEN    5

int SetupTime()
{
   char String[MAX_STRING_LEN];                // for user input
   
   ...
   get_string(String, MAX_STRING_LEN);
zonemikel



Joined: 13 Oct 2007
Posts: 53
Location: Texas

View user's profile Send private message Visit poster's website Yahoo Messenger

Re: Thanks
PostPosted: Sun Jan 13, 2008 10:25 am     Reply with quote

Neutone wrote:

Only one instruction can be executed at a time. Instructions are executed sequentially but jumps to different spots in the program can be made. The timer module counts when instructions are executed. When the interrupt occurs, main program (or sub functions) execution stops and interrupt function execution begins. When the interrupt function completes, main program (or sub functions) execution resumes where it left off when the interrupt occured.


So it jumps to that location when "INT_TIMER1" is triggered. I didnt see the link because it was lowercase "int". Also in the original code (in the link after my first post) the seconds variable is "Seconds" but then used as "seconds" i think.

Thats great that execution resumes where it left off, very nifty.

thanks ckielstra i remembered that last night, its dumb to have it receive 10 chars into a char array that can only hold five, ill fix it up in my post.

I was actually thinking i could use strtok to have the user insert a time like this 7:08 and then it would just take the numbers out, ill work on it some more. Since im going to have alarms and stuff that all need to be set via the serial port i dont want to make that long prompt system for every time.

Its nice to know get_string actually gets the terminating zero also, funny i didnt see get_string in the help file, just on these forums Smile

one more thing, i hate to go off topic but when i use the "\n" newline in my terminal program it does not actually do a "new line" its more like a tab and a new line ? I tested it on hyperterm, ive yet to test it on minicom, but it shows up like this
Code:
first line
             second line
                             third line

Any ideas why ?
_________________
Smart people know how stupid they are.
newguy



Joined: 24 Jun 2004
Posts: 1903

View user's profile Send private message

PostPosted: Sun Jan 13, 2008 12:50 pm     Reply with quote

The newline code (0x0a) gives you a new line - nothing else. A carriage return (0x0d) puts the cursor back to the beginning of the current line. You need to send a carriage return line feed (\n\r). The order doesn't matter.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Jan 13, 2008 2:33 pm     Reply with quote

Code:
void Beep() // sends a beep to the piezo on C0
{
      int k = 0;
      for(k=0; k<255; k++)                   // 255 times not very long but a beep
      {
      output_high(PIN_C0);
      delay_us(100);                         // produces a tone
      output_low(PIN_C0);
      }
There is no delay between output_low / output_high, so you get a signal pattern that is high for 100us and low for about 4us. Just wondering... do you really hear a sound with this setup?
Ttelmah
Guest







PostPosted: Sun Jan 13, 2008 3:14 pm     Reply with quote

Slight 'caveat', the order can matter for CR/LF or LF/CR.
Depends on the terminal emulation being used, but some settings in hyperterminal in particular affect this.
If you have the option in ASCII settings set to 'append line feeds to line ends', then you only need to send the CR, and the terminal will automatically perform an LF. With this enabled, hyperterminal in some versions at least, gives an 'extra' line feed with the commands one way round.
It caused me a problem with a menu display in the past. The 'real' VT terminal that hyperterminal was 'meant' to be emulating, behaved correctly...

Best Wishes
zonemikel



Joined: 13 Oct 2007
Posts: 53
Location: Texas

View user's profile Send private message Visit poster's website Yahoo Messenger

PostPosted: Sun Jan 13, 2008 5:10 pm     Reply with quote

newguy wrote:
The newline code (0x0a) gives you a new line - nothing else. A carriage return (0x0d) puts the cursor back to the beginning of the current line. You need to send a carriage return line feed (\n\r). The order doesn't matter.


Wow i didnt think of that thanks a lot, my terminal sessions will be much more readable now.



Quote:
here is no delay between output_low / output_high, so you get a signal pattern that is high for 100us and low for about 4us. Just wondering... do you really hear a sound with this setup?

Ya, it does beep. ive never used a piezo before i made that with just pure experimenting, i was unable to find the right info on the net. If you know a better way to make a "cleaner" beep please share, should i have a delay after the low output ? ah fooey its to easy ill just go put a delay afterwords and see what happens
Smile
_________________
Smart people know how stupid they are.
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