|
|
View previous topic :: View next topic |
Author |
Message |
zonemikel
Joined: 13 Oct 2007 Posts: 53 Location: Texas
|
RTC Interrupts help, do they stop everything ? |
Posted: Fri Jan 11, 2008 10:09 pm |
|
|
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
|
|
|
zonemikel
Joined: 13 Oct 2007 Posts: 53 Location: Texas
|
Thanks |
Posted: Sat Jan 12, 2008 11:22 pm |
|
|
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
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
|
Re: Thanks |
Posted: Sun Jan 13, 2008 1:02 am |
|
|
zonemikel wrote: |
There is just one thing i dont understand right before the timer1_isr function begins what is the line
|
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
|
|
Posted: Sun Jan 13, 2008 8:38 am |
|
|
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
|
Re: Thanks |
Posted: Sun Jan 13, 2008 10:25 am |
|
|
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
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: 1909
|
|
Posted: Sun Jan 13, 2008 12:50 pm |
|
|
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
|
|
Posted: Sun Jan 13, 2008 2:33 pm |
|
|
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
|
|
Posted: Sun Jan 13, 2008 3:14 pm |
|
|
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
|
|
Posted: Sun Jan 13, 2008 5:10 pm |
|
|
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
_________________ Smart people know how stupid they are. |
|
|
|
|
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
|