|
|
View previous topic :: View next topic |
Author |
Message |
ZeroF877A
Joined: 17 Mar 2008 Posts: 6
|
Problem using the external interrupt (Rb0) with a PIC16F877 |
Posted: Thu Mar 27, 2008 11:09 am |
|
|
Hello everyone.
I'm working with a 16F877 using the Tmr1 and Rb0 interrupts. The Tmr1 interrupt works well all the time. However, the external interrupt only works once.
Here's the code for the interrupt
Code: | #include "C:\Micro C\Complex test\complex.h"
#include <lcdlib.c>
#include <kbdlib.c>
int starter, i, weight, j;
char keypress, keylcd1, keylcd2, keylcd3, hour1, hour2, min1, min2;
#int_EXT
void EXT_isr()
{
starter = true;
}
#int_timer1
void TIMER1_isr()
{
i=++i;
if(i==2){
min2=++min2;
if(min2==':')
{
min1=++min1;
min2='0';
}
if(min1=='6')
{
min1='0';
hour2=++hour2;
}
if(hour2=='3'&&hour1=='1')
{
hour1='0';
hour2='1';
}
i=0;
}
}
void main()
{
lcd_init();
kbd_init();
port_b_pullups(true);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
enable_interrupts(int_ext);
enable_interrupts(int_timer1);
enable_interrupts(global);
//USER CODE
min2='0';
min1='0';
hour2='0';
hour1='1';
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_8 );
i=0;
do{
while(starter != true){
lcd_putc('\f');
lcd_putc(hour1);
lcd_putc(hour2);
lcd_putc(':');
lcd_putc(min1);
lcd_putc(min2);
if((hour1=='1'&&hour2=='2')||hour1=='0')
{
lcd_putc(" am\n");
}
else
{
lcd_putc(" pm\n");
}
lcd_putc("Sistema Activo");
delay_ms(250);
if(hour1=='0'&&hour2=='4')
{
disable_interrupts(GLOBAL);
lcd_putc("\fJornada\n");
lcd_putc("Finalizada");
do{
delay_ms(500);
}while(true);
}
}
clear_interrupt(int_ext);
starter = 0;
lcd_putc("\fBienvenido...\n");
delay_ms(3000);
lcd_putc("Espere");
delay_ms(250);
lcd_putc('.');
delay_ms(250);
lcd_putc('.');
delay_ms(250);
lcd_putc('.');
setup_adc_ports(RA0_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
weight = read_adc();
if(weight<75)
{
lcd_putc("\fTipo\n");
lcd_putc("Liviano");
delay_ms(2000);
lcd_putc("\fCodigo de\n");
lcd_putc("Confirmacion:");
lcd_putc("\f350\n");
}
if(weight>=75&&weight<=150)
{
lcd_putc("\fTipo\n");
lcd_putc("Pesado");
delay_ms(2000);
lcd_putc("\fCodigo de\n");
lcd_putc("Confirmacion:");
lcd_putc("\f658\n");
}
if(weight>=150)
{
lcd_putc("\fTipo\n");
lcd_putc("Extra Pesado");
delay_ms(2000);
lcd_putc("\fCodigo de\n");
lcd_putc("Confirmacion:");
lcd_putc("\f999\n");
}
do{
lcd_gotoxy(1,2);
for(j=0;j<=2;++j)
{
do{
keypress=kbd_getc();
}while(keypress==0);
lcd_putc(keypress);
}
delay_ms(500);
keylcd1=lcd_getc(1,2);
keylcd2=lcd_getc(2,2);
keylcd3=lcd_getc(3,2);
if(keylcd1!=lcd_getc(1,1)||keylcd2!=lcd_getc(2,1)||keylcd3!=lcd_getc(3,1))
{
lcd_gotoxy(1,2);
lcd_putc("Erroneo");
delay_ms(1500);
lcd_gotoxy(1,2);
lcd_putc(" ");
lcd_gotoxy(1,2);
}
else
{
lcd_gotoxy(1,2);
lcd_putc("Confirmado");
}
delay_ms(1500);
}while(keylcd1!=lcd_getc(1,1)||keylcd2!=lcd_getc(2,1)||keylcd3!=lcd_getc(3,1));
lcd_putc("\fBuen viaje");
delay_ms(2000);
lcd_putc('\f');
}while(hour1!='0'&&hour2<='4');
disable_interrupts(GLOBAL);
lcd_putc("\fJornada\n");
lcd_putc("Finalizada");
}
|
And here's the .h:
Code: | #include <16F877.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#use delay(clock=4000000) |
As you can see, the large piece of code will repeat as long as "starter" is false. The only way to make "starter" true is by pressing a switch on Rb0, thus triggering the interrupt. Once that is done, the program moves forward until a point where it goes back to wait until Rb0 is pressed again.
Now here's the deal. It works wonderfully but only once. Once the program returns to "while(starter != true)", even if you hit the button with a hammer, it won't trigger the interrupt again...
So, what am I missing in the code? Thanks in advice.
Last edited by ZeroF877A on Fri Mar 28, 2008 7:02 am; edited 3 times in total |
|
|
Ttelmah Guest
|
|
Posted: Thu Mar 27, 2008 11:19 am |
|
|
How can it _ever_ return to the 'while(starter != true)'?.
It'll never go past the:
Code: |
do{
delay_ms(500);
}while(true);
}
|
This is a 'forever' loop. it'll never exit, so the code will never go back and wait for 'starter'again....
Best Wishes |
|
|
ZeroF877A
Joined: 17 Mar 2008 Posts: 6
|
|
Posted: Thu Mar 27, 2008 11:24 am |
|
|
Quote: | if(hour1=='0'&&hour2=='4')
{
disable_interrupts(GLOBAL);
lcd_putc("\fJornada\n");
lcd_putc("Finalizada");
do{
delay_ms(500);
}while(true);
} |
That forever loop is intended. It'll only happen IF(hour1=='0'&&hour2=='4'). Which doesn't happen yet. And I've tested that part, it works perfectly fine, it's supposed to be an endless loop when the "timer" reaches 04. Thanks for the help anyway =D
EDIT: It DOES return to the 'while(starter != true)', since it's a LCD refresh loop (I'm emulating a 'real time' clock [1 minute per second] using tmr1). And after the rest of the code is executed it returns to showing the 'current time'. It refreshes properly and all. Goes ahead and displays "Jornada Finalizada" via LCD AND THEN it goes into the infinite loop, which is intended to be sort of the end of the program. |
|
|
Matro Guest
|
|
Posted: Thu Mar 27, 2008 12:06 pm |
|
|
Ttelmah is right!
This loop
Code: |
do{
delay_ms(500);
}while(true);
|
is endless.
So the application will stay here ... and that's all.
Matro |
|
|
Matro Guest
|
|
Posted: Thu Mar 27, 2008 12:09 pm |
|
|
Moreover, when the ext interrupt is triggered, the code will goes out the
Code: |
while(starter != true)
|
loop and then execute
And after...
What's happening?
Matro |
|
|
ZeroF877A
Joined: 17 Mar 2008 Posts: 6
|
|
Posted: Thu Mar 27, 2008 12:21 pm |
|
|
After the loop ends when starter = true, the "starter = false" is written so the moment I return to that specific area, it won't just go ahead again and execute the rest of the program.
Also, Matro. That endless loop only happens IF something else happens first.
Check the {}'s in the code and see for yourself.
Anyways, the problem seems to have miraculously solved by itself... |
|
|
Matro Guest
|
|
Posted: Thu Mar 27, 2008 12:27 pm |
|
|
The question about the endless loop is : Why write it like you did it when you can just write :
while(1);
since nothing happens in the loop.
Check that NOLVP is present among your #FUSES directives.
If you want more help, please post a complete "compilable" code with fuses.
Matro. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Mar 27, 2008 9:37 pm |
|
|
Quote: | If you want more help, please post a complete "compilable" code with fuses. | And may I add to that to please use a correct indentation. Now at least three seasoned programmers (Me, Ttelmah and Matro) overlooked your problem because of bad formatting. |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Fri Mar 28, 2008 1:24 am |
|
|
I'm reluctant to jump in on this since the person with the issue seems to believe in their code more than the reality that their code didn't work.
Coding an RTC for most coders is a basic task that is accomplished without
the issues presented by ZeroF877A's code.
The enable_interrupts (GLOBAL) is missing in the snippet of code given as well as the initialization of the variable starter.
Now ZeroF877A's faith in his/her code has according to ZeroF877A resulted in a miracle.... it was self repairing. Wish we all could be as blessed. |
|
|
ZeroF877A
Joined: 17 Mar 2008 Posts: 6
|
|
Posted: Fri Mar 28, 2008 7:00 am |
|
|
Douglas Kennedy wrote: | I'm reluctant to jump in on this since the person with the issue seems to believe in their code more than the reality that their code didn't work. |
If you see your code working as you designed it to work on a physical MCU (except for the interrupt part), you're bound to think it's functional, no? I've been working with these MCU for nearly 10 months now (used to work in assembly), so it's not like I don't know what I'm doing.
Anyway, I might add that I had to replace the PIC with a new one, and change the wiring in my board for it to work. The code works perfectly fine, and if anyone is still reluctant about it, I can upload a video to prove it. |
|
|
Guest
|
|
Posted: Fri Mar 28, 2008 8:54 am |
|
|
ZeroF877A wrote: | Douglas Kennedy wrote: | I'm reluctant to jump in on this since the person with the issue seems to believe in their code more than the reality that their code didn't work. |
If you see your code working as you designed it to work on a physical MCU (except for the interrupt part), you're bound to think it's functional, no? I've been working with these MCU for nearly 10 months now (used to work in assembly), so it's not like I don't know what I'm doing.
Anyway, I might add that I had to replace the PIC with a new one, and change the wiring in my board for it to work. The code works perfectly fine, and if anyone is still reluctant about it, I can upload a video to prove it. |
Unfortunately, it seems that Douglas was right. We can have looked for a solution during hours since your hardware was bad... That is the first thing to check if you never successfully run a software on it. :-/
Personnaly I work with µC and program in embedded C and ASM for years. And I always produce code with a proper indentation and a lot of comments. It makes my job easier and the one of my colleagues too. ;-)
See you!
Matro |
|
|
|
|
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
|