|
|
View previous topic :: View next topic |
Author |
Message |
shocks
Joined: 10 Aug 2006 Posts: 5
|
Need help with my bits |
Posted: Mon Aug 21, 2006 4:28 pm |
|
|
High Guys
Im not sure whats goin on.
In the code that follows Ive set the register 0x20 the name Phasereg.
I have an ISR for Timer 1. The ISR is meant to check the status of bits 1,2,3 in Phasereg.
I set the value of these bits to 1 in the main code and when I check, they are as i have set them, in the main code. However when the code throws the ISR, the value of the bits appears to have returned to Zero????
The idea behind the code is to tell the ISR which input C2,C3,C4 has lost its input, causing the ISR.
#include <16f877a.h>
#device ICD=TRUE
#fuses HS,NOLVP,NOWDT,PUT
#use delay(clock=20000000)
#use rs232 (DEBUGGER)
#define GREEN_LED PIN_A5
#define YELLOW_LED PIN_B4
#define RED_LED PIN_B5
#define PUSH_BUTTON PIN_A4
#define R_PHASE PIN_C2
#define S_PHASE PIN_C3
#define T_PHASE PIN_C4
#define OUT PIN_C5
#define Phasereg 0x20
#bit rphase=0x20.1
#bit sphase=0x20.2
#bit tphase=0x20.3
#int_timer1
timer1_isr()
{//char phase;
printf("int, Rphase=%u",rphase);
IF(rphase)
{output_LOW(RED_LED);
delay_ms(100);
output_high(RED_LED);
delay_ms(100);}
IF(sphase==1)
{output_LOW(GREEN_LED);
delay_ms(100);
output_high(GREEN_LED);
delay_ms(100);}
IF(tphase==1)
{output_LOW(YELLOW_LED);
delay_ms(100);
output_high(YELLOW_LED);
delay_ms(100);}
}
void main(){
WHILE(1){
output_high(GREEN_LED);
output_high(RED_LED);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
set_timer1(58661);
//rphase=1;
#asm
movlw 11111111
movwf 0x20
#endasm
//printf("int, Rphase=%u",rphase);
while(!input(R_PHASE));
set_timer1(58661);
sphase=1;
while(!input(S_PHASE));
set_timer1(58661);
tphase=1;
while(!input(T_PHASE));
disable_interrupts(GLOBAL);
(output_low(GREEN_LED));
//delay_ms(100);
}}
I would really appreciate help and/or advice
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Aug 21, 2006 9:16 pm |
|
|
Quote: | #define Phasereg 0x20
#bit rphase=0x20.1
#bit sphase=0x20.2
#bit tphase=0x20.3 |
It's not done that way. You need to use the #locate statement.
Example:
Code: |
#locate Phasereg = 0x20
#bit rphase=Phasereg.1
#bit sphase=Phasereg.2
#bit tphase=Phasereg.3 |
Quote: | #asm
movlw 11111111
movwf 0x20
#endasm |
You don't need to use ASM code. Use C code instead:
Also, did you know that in CCS, it's not required to assign the address
of a variable ? (unless you want to). In some compilers like Hi-Tech,
you have to assign everything. CCS is like normal C (on a PC).
It automatically assigns the variable to a suitable RAM location.
You don't even have to worry about it. |
|
|
MikeW
Joined: 15 Sep 2003 Posts: 184 Location: Warrington UK
|
|
Posted: Tue Aug 22, 2006 2:42 am |
|
|
and of course, the last thing you want in an isr are delay_ms routines.
it is always best to just use the isr to set and clear semaphore flags, and let a routine in main turn leds on, and have delays.
Mike |
|
|
sjbaxter
Joined: 26 Jan 2006 Posts: 141 Location: Cheshire, UK
|
|
Posted: Tue Aug 22, 2006 3:57 am |
|
|
You also want to move the
statement down the Main function (passed the initialization code) other wise your program will effectively reset itself very quickly and many times !!!
I would start with a simple application before moving onto interrupts as you don't seem to have grasped the basics yet.
and as Mike says, DON'T use delays or printfs in interrupt handlers. The interrupt handler is there to 'capture an event' ... not process it. Code in an interrupt handler should consum as little time as possible. Otherwise you WILL miss other events. _________________ Regards,
Simon. |
|
|
shocks
Joined: 10 Aug 2006 Posts: 5
|
Need help with my bits |
Posted: Tue Aug 22, 2006 5:47 pm |
|
|
Guys thanks much for the help.
PCM programmers reply is particularily helpful.
Your collective comments on the use of while loops and printf are quite correct. Rest assured Ionly use them for debugging. I find looped code is easier to debug when implemented with hardware.
The printf's give an indication of whats actually happening when used in conjunction with the monitor in debugger.
I dont have a big problem with time constraints in terms of signal input frequency (VLF), hence the ISR contains actual executable code with delays to flash LEDs.
In terms of your collective responses I would be grateful for any insightful code snippets, particularily from Simon.
Thanks once again |
|
|
sjbaxter
Joined: 26 Jan 2006 Posts: 141 Location: Cheshire, UK
|
|
Posted: Wed Aug 23, 2006 2:48 am |
|
|
First here is your code with a few corrections and improvements:
Note: there is nothing in you code that resets any of the *phase values to zero !!! so this is supposed to be a one-shot application ??
Code: | #include <16f877a.h>
#device ICD=TRUE
#fuses HS,NOLVP,NOWDT,PUT
#use delay(clock=20000000)
#use rs232 (DEBUGGER)
#define GREEN_LED PIN_A5
#define YELLOW_LED PIN_B4
#define RED_LED PIN_B5
#define PUSH_BUTTON PIN_A4
#define R_PHASE PIN_C2
#define S_PHASE PIN_C3
#define T_PHASE PIN_C4
#define OUT PIN_C5
int1 rphase;
int1 sphase;
int1 tphase;
#int_timer1
timer1_isr()
{
//char phase;
printf("int, Rphase=%u",rphase);
if (rphase)
{
output_LOW(RED_LED);
delay_ms(100);
output_high(RED_LED);
delay_ms(100);
}
if (sphase)
{
output_LOW(GREEN_LED);
delay_ms(100);
output_high(GREEN_LED);
delay_ms(100);
}
if (tphase)
{
output_LOW(YELLOW_LED);
delay_ms(100);
output_high(YELLOW_LED);
delay_ms(100);
}
}
void main()
{
// initialise hardware
output_high(GREEN_LED);
output_high(RED_LED);
// initialise globals
rphase=1;
sphase=1;
tphase=1;
// setup timers and interrupts
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
set_timer1(58661);
//printf("int, Rphase=%u",rphase);
// main program loop
while(1)
{
while(!input(R_PHASE));
set_timer1(58661);
sphase=1;
while(!input(S_PHASE));
set_timer1(58661);
tphase=1;
while(!input(T_PHASE));
disable_interrupts(GLOBAL);
(output_low(GREEN_LED));
//delay_ms(100);
}
}
|
.. however, going by your original post, I think you need to switch around the code between the main loop and the isr. I would use the isr to poll the status of the inputs (at an interval defined by Timer1) and set the relavent *phase flag. The main program loop would then test this flag and flash the corresponding LED.
To change anymore code, I would need to know some more information...
When you say 'checks to see if 'C2,C3,C4 has lost its input', are these simple steady state inputs or is there 'data' on these lines. By that I mean is the PIC checking for the pins being ON, OFF or a loss of a data stream ?
BTW: Doesn't code look far better and more readable if you format it, add comments and use the CODE button when submitting posts HINT !! _________________ Regards,
Simon. |
|
|
shocks
Joined: 10 Aug 2006 Posts: 5
|
Need help with my bits |
Posted: Thu Aug 24, 2006 4:09 pm |
|
|
Simon
You're quite correct. Commenting would be better, bad habit on my behalf.
Im new to the forum so I need a small bit of grace.
The project is composed of a number of features, hence the code is written to become part of a bigger code.
The code posted, looks at pins C2 C3 C4 and tests for loss of voltage( ie zero) on a pin by waiting for the pin to go high for 11ms.
The inputs are 3 square waves with a 120 degree phase displacement. The frequency is 50 HZ same as your AC supply in UK.
The 11ms delay which is the count to ISR on T1, is 1 ms longer than half the cycle time.
I start the timer, wait for a high on the pin , if it goes high TI resets and looks at the next pin.
If not, the ISR is called the missing input identified and the relevant LED energised.
Thats all, in theory at least.
I appreciate your help.
Paul |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Fri Aug 25, 2006 1:34 pm |
|
|
How about something simple
Code: | while(1)
{
//some other code
if(ms_Tick) // SET IN AN INTERUPT
{ if (++Phase_A_Time>15) Phase_A_Lost=1; // Detect excessive phase time
if (++Phase_B_Time>15) Phase_B_Lost=1; // Detect excessive phase time
if (++Phase_C_Time>15) Phase_C_Lost=1; // Detect excessive phase time
if (Phase_A_Old != Phase_A)
{ Phase_A_Time=0; // Clear Phase time
Phase_A_Lost=0; // Clear Phase lost flag
}
if (Phase_B_Old != Phase_B)
{ Phase_b_Time=0; // Clear Phase time
Phase_b_Lost=0; // Clear Phase lost flag
}
if (Phase_C_Old != Phase_C)
{ Phase_c_Time=0; // Clear Phase time
Phase_c_Lost=0; // Clear Phase lost flag
}
Phase_A_Old = Phase_A;
Phase_B_Old = Phase_B;
Phase_C_Old = Phase_C;
if ((!Phase_A_Time) && (((!Phase_B_Time)||(!Phase_C_Time)) || (Phase_B_Time == Phase_C_Time)))
Phase_A_Lost=1; // Set Phase lost flag if phases are in time
//some other code
ms_Tick=0;
}
//some other code
} |
|
|
|
|
|
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
|