|
|
View previous topic :: View next topic |
Author |
Message |
Pichuqy_1
Joined: 03 Aug 2010 Posts: 38
|
INT_RB problem - pic18f2550 |
Posted: Thu Feb 21, 2019 4:40 pm |
|
|
Hi all. I have a problem to use the interrupt for status change in port B, with pic18f2550.
The problem is, I can not detect the falling edge of the signal. I'm using four buttons on the pins 4,5,6,7. The interruption runs correctly, but I never detect the falling edge.
Try simulating it several times and I get the same result.
To put it in other terms, the program never enters to #elif HIGHTOLOW.
I took the code to deal with this interruption from the forum.
Can someone help me find out what's going on?
Code: |
#include <18f2550.h>
#device ICD = TRUE
//#device HIGH_INTS=TRUE
#fuses HS,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOUSBDIV,PLL5,CPUDIV1,NOVREGEN,NOPBADEN,NOPUT,DEBUG
#use delay(clock=20000000)
#byte UCFG = 0xF6F
#bit UTRDIS = UCFG.3
//#use fast_io(B)
#define _FLEX_LCD
#define LCD_DB4 PIN_C1
#define LCD_DB5 PIN_C0
#define LCD_DB6 PIN_B2
#define LCD_DB7 PIN_B3
#define LCD_RS PIN_A1
#define LCD_RW PIN_A2
#define LCD_E PIN_A0
#include "flex_lcd.c"
#include "internal_eeprom.c"
#include "ds1307.c"
#include "ds1307_configuracion.c"
#include "TMR.c"
//#include "convercion_int_char.c"
#define LOWTOHIGH TRUE
#define HIGHTOLOW FALSE
int16 overflow_timer0;
int falla_general=0;
int bandera_backlight=0;
int bandera_TMR1,bandera_TMR2,bandera_TMR3,bandera_TMR4,bandera_TMR5,bandera_TMR6;
int int_rb_1=0;
int current;
static int last=0;
//int dbutton4, dbutton5, dbutton6, dbutton7;
#INT_RB
void detect_rb_change(void)
{
// set_tris_b(0xF0);
current=input_b();
#if LOWTOHIGH
if ((!bit_test(last,4))&&(bit_test(current,4))&&(bandera_backlight==0)&&(int_rb_1==1))
dbutton4=4;
if ((!bit_test(last,5))&&(bit_test(current,5))&&(bandera_backlight==0)&&(int_rb_1==1))
dbutton5=5;
if ((!bit_test(last,6))&&(bit_test(current,6))&&(bandera_backlight==0)&&(int_rb_1==1))
dbutton6=6;
if ((!bit_test(last,7))&&(bit_test(current,7))&&(bandera_backlight==0)&&(int_rb_1==1))
dbutton7=7;
#elif HIGHTOLOW
if ((!bit_test(current,4))&&(bit_test(last,4))&&(bandera_backlight==0)&&(int_rb_1==1))
dbutton4=4;
if ((!bit_test(current,5))&&(bit_test(last,5))&&(bandera_backlight==0)&&(int_rb_1==1))
dbutton5=5;
if ((!bit_test(current,6))&&(bit_test(last,6))&&(bandera_backlight==0)&&(int_rb_1==1))
dbutton6=6;
if ((!bit_test(current,7))&&(bit_test(last,7))&&(bandera_backlight==0)&&(int_rb_1==1))
dbutton7=7;
#endif
last=current;
}
//#separate
{
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8); //104 ms overflow
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256); //3,4 s overflow
clear_interrupt(int_rb);
enable_interrupts(INT_EXT);
enable_interrupts(INT_RB);
enable_interrupts(INT_RTCC);
disable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
ext_int_edge( H_TO_L );
set_timer1(0x00);
set_timer0(0x00);
port_b_pullups(TRUE);
set_tris_b(0xF0);
delay_us(10);
UTRDIS = 1;
//int16 cuenta_pulsador=0;
overflow_timer1=0;
//int con_hours, con_inicio1,con_inicio2;
int resultado_TMR1=0;
int resultado_hora_actual;
output_high(PIN_C2);
lcd_init();
ds1307_init(DS1307_OUT_ON_DISABLED_HIHG | DS1307_OUT_ENABLED | DS1307_OUT_1_HZ);
//enable_interrupts(int_ext);
//ext_int_edge(L_TO_H);
//enable_interrupts(GLOBAL);
while(1)
{
delay_ms(250);
enable_interrupts(INT_RTCC); //Habilitamos timmer 0
disable_interrupts(INT_TIMER1); //Habilitamos timmer 1
int_rb_1=1;
overflow_timer1=0; //se pone a cer la variable del tamier 1
//overflow_timer0=0;
if(dbutton7==7) {
dbutton7=0;
CONFIGURACION_ENCENDIDO_APAGADO();
}
if(dbutton4==4) {
dbutton4=0;
CONFIGURACION_DS1307();
}
ds1307_get_time();
ds1307_get_date();
lcd_gotoxy(4,1);
printf(lcd_putc,"\f%1s-%1s-20%1s\n",date_char,month_char,year_char);
lcd_gotoxy(5,2);
printf(lcd_putc,"%1s:%1s:%1s",hours_char,minutes_char,seconds_char); //23:59:59
resultado_TMR1 = hora_TMR1_inicio + minutos_TMR1_INICIO;
resultado_hora_actual = hours + minutes;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if((hora_TMR1_inicio == hours) && (minutos_TMR1_INICIO == minutes) && (bandera_TMR1 == 0)&& (hora_TMR1_inicio != 255)){
output_high(PIN_C7);
bandera_TMR1 = 1;
}
if((hora_TMR1_stop == hours) && (minutos_TMR1_stop == minutes) && (bandera_TMR1 == 1)){
output_low(PIN_C7);
bandera_TMR1 = 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
if((hora_TMR2_inicio == hours) && (minutos_TMR2_INICIO == minutes) && (bandera_TMR2 == 0)&& (hora_TMR2_inicio != 255)){
output_high(PIN_C7);
bandera_TMR2 = 1;
}
if((hora_TMR2_stop == hours) && (minutos_TMR2_stop == minutes) && (bandera_TMR2 == 1)){
output_low(PIN_C7);
bandera_TMR2 = 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
if((hora_TMR3_inicio == hours) && (minutos_TMR3_INICIO == minutes) && (bandera_TMR3 == 0) && (hora_TMR3_inicio != 255)){
output_high(PIN_C7);
bandera_TMR3 = 1;
}
if((hora_TMR3_stop == hours) && (minutos_TMR3_stop == minutes) && (bandera_TMR3 == 1)){
output_low(PIN_C7);
bandera_TMR3 = 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
if((hora_TMR4_inicio == hours) && (minutos_TMR4_INICIO == minutes) && (bandera_TMR4 == 0)&& (hora_TMR4_inicio != 255)){
output_high(PIN_C7);
bandera_TMR4 = 1;
}
if((hora_TMR4_stop == hours) && (minutos_TMR4_stop == minutes) && (bandera_TMR4 == 1)){
output_low(PIN_C7);
bandera_TMR4 = 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Thu Feb 21, 2019 6:07 pm |
|
|
you have ...
#define HIGHTOLOW FALSE
so your elif won't execute....
at least that's how I read it.
As an aside, I don't think that PIC actually has h2l, l2h options for the 'Interrupt-on-change' so you can't decode which did fire the interrupt.
Jay |
|
|
Pichuqy_1
Joined: 03 Aug 2010 Posts: 38
|
|
Posted: Thu Feb 21, 2019 8:08 pm |
|
|
Thank you very much for your answer Jay. I had already put #define HIGHTOLOW TRUE in the program and even then it did not work either.
If I keep pressing any button, the interruption is executed when I press and when I stop pressing. That is why I can deduce that it is possible to read the falling edge.
Thank you. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Thu Feb 21, 2019 8:46 pm |
|
|
just some comments..
OK, I read the datasheet(2550 is skinny 4550).. and IOC is different that 'edge detect'.
Seems this PIC can only do 'IOC' BUT there's a note about you having to wait 1 cycle other wise the flag keeps getting set.
I'd change this...
current=input_b();
#if LOWTOHIGH
to this...
current=input_b();
delay_us(5); //added delay as per datasheet...
#if LOWTOHIGH
See if it does anything...
There could be the nasty hardware 'debounce' problem. If you have just a mechancal pushbutton to ground and a 10K pullup, you'll get several 101010 transitions, not just a 1-0-1. Adding a small cap ( .68uf) should quench the bounce. Easy to see if you have a scope.
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Feb 21, 2019 8:53 pm |
|
|
My advice is to strip down the program. Get rid of the #if, #elif, and
#endif statements. Remove the code for the edge you don't want to test.
Get rid of all enable_interrupts() for everything except #int_rb.
Get rid of all excess code that has nothing to do with #int_rb. Example:
Quote: | &&(bandera_backlight==0)&&(int_rb_1==1)) |
Get rid of all ds1307 stuff, etc. Strip the program down. Test it, and
if it still fails, post the new program.
Also, describe your circuit for your switches. What value is the pull-up
resistor ? Are your switches connected the same as this ?
Code: |
+5v
|
<
> 4.7K
< ___ Switch
To | _|_|_
PIC -----------------o o------
pin B4 |
--- GND
-
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Fri Feb 22, 2019 12:22 am |
|
|
Also, in what you post you have INT_EXT also enabled, but no handler
for this. This will cause major problems.
Then at the start you try to clear INT_RB. You need to read port B
before doing this, or it can't be cleared.
As PCM_programmer says, test with simpler code first. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
|
Pichuqy_1
Joined: 03 Aug 2010 Posts: 38
|
|
Posted: Fri Feb 22, 2019 10:33 am |
|
|
Thank you very much for your advice. I will try the modifications you mentioned and I will publish the results.
The project is about a programmable clock, in which 10 different hours can be configured independently. You can enter the start time, end time, and you can deactivate any time.
I almost have it ready, but this problem appeared with the interruption of the RB port.
The code that I put before, is simplified, since I also use: #INT_EXT, # INT_TIMER1, #INT_RTCC.
https://ibb.co/z7VWS6c |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Feb 22, 2019 11:21 am |
|
|
Your schematic is missing the series resistor for your LED D3. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Fri Feb 22, 2019 7:15 pm |
|
|
Also you need a battery on the DS1307 as well as a 32KHz xtal.
_mclr should be pulled high, not low.... according to your fuse you are using that pin for _mclr.
If you set the SQW out of the DS1307 at 1Hz, you get a nice timed interrupt for your project that allows main() to update the LCD every second. |
|
|
Pichuqy_1
Joined: 03 Aug 2010 Posts: 38
|
|
Posted: Mon Feb 25, 2019 6:03 pm |
|
|
Hello everyone again.
I simplified the code and followed his advice. Even so, the interruption RB is executed twice (I understand that the first time is on the rising edge and the second on the falling edge) but always enters #if LOWTOHIGH. Therefore the same action is executed twice.
When I simulate it using PROTEUS, the #elif code HIGHTOLOW seems not to be enabled. Look at the attached photo. I do not know why...
Code: | #include <18f2550.h>
#device ICD = TRUE
#fuses HS,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOUSBDIV,PLL5,CPUDIV1,NOVREGEN,NOPBADEN,NOPUT,DEBUG
#use delay(clock=20000000)
#byte UCFG = 0xF6F
#bit UTRDIS = UCFG.3
//#use fast_io(B)
#define _FLEX_LCD
#define LCD_DB4 PIN_C1
#define LCD_DB5 PIN_C0
#define LCD_DB6 PIN_B2
#define LCD_DB7 PIN_B3
#define LCD_RS PIN_A1
#define LCD_RW PIN_A2
#define LCD_E PIN_A0
#include "flex_lcd.c"
#include "internal_eeprom.c"
#include "ds1307.c"
#include "ds1307_configuracion.c"
#include "TMR.c"
#define LOWTOHIGH TRUE
#define HIGHTOLOW TRUE
int int_rb_1=0;
int current;
static int last=0;
#INT_RB
void detect_rb_change(void)
{
current=input_b();
delay_us(5);
#if LOWTOHIGH
if ((!bit_test(last,4))&&(bit_test(current,4))
dbutton4=4;
if ((!bit_test(last,5))&&(bit_test(current,5))
dbutton5=5;
if ((!bit_test(last,6))&&(bit_test(current,6))
dbutton6=6;
if ((!bit_test(last,7))&&(bit_test(current,7))
dbutton7=7;
#elif HIGHTOLOW
if ((!bit_test(current,4))&&(bit_test(last,4))
dbutton4=14;
if ((!bit_test(current,5))&&(bit_test(last,5))
dbutton5=15;
if ((!bit_test(current,6))&&(bit_test(last,6))
dbutton6=16;
if ((!bit_test(current,7))&&(bit_test(last,7))
dbutton7=17;
#endif
last=current;
}
//#separate
void main(void)
{
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
port_b_pullups(TRUE);
set_tris_b(0xF0);
delay_us(10);
UTRDIS = 1;
lcd_init();
ds1307_init(DS1307_OUT_ON_DISABLED_HIHG | DS1307_OUT_ENABLED | DS1307_OUT_1_HZ);
while(1)
{
delay_ms(250);
if(dbutton7==7) {
dbutton7=0;
CONFIGURACION_ENCENDIDO_APAGADO();
}
if(dbutton4==4) {
dbutton4=0;
CONFIGURACION_DS1307();
}
ds1307_get_time();
ds1307_get_date();
lcd_gotoxy(4,1);
printf(lcd_putc,"\f%1s-%1s-20%1s\n",date_char,month_char,year_char);
lcd_gotoxy(5,2);
printf(lcd_putc,"%1s:%1s:%1s",hours_char,minutes_char,seconds_char); //23:59:59
}
|
[img]https://subefotos.com/ver/?f412abc288c1cb4afe564c439e727b86o.jpg[/img]
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Mon Feb 25, 2019 6:23 pm |
|
|
Quote: | When I simulate it using PROTEUS, the #elif code HIGHTOLOW seems not to be enabled. Look at the attached photo. I do not know why...
|
this...
using PROTEUS
It's very, very well known that PROTEUS is a broken piece of software NOT to be trusted.!
As for the
Quote: | if
do this....
elseif
do that... |
Since the first condition is true, it will execute the following code 'do this' then bypasses the 2nd 'if' condition (the 'elseif') and 'do that... is never executed.
Another comment...
I don't see any difference in the 2 groups of tests in 'this' vs 'that'.
Also that PIC can't tell you which edge, only that an 'edge event' has occurred, at least that's how I read the datasheet. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 25, 2019 9:06 pm |
|
|
Pichuqy_1 wrote: |
Therefore the same action is executed twice.
|
I'm not sure what you mean by "the same action".
The program will definitely execute the LOWTOHIGH code twice. That's
expected. There are two edges, falling and rising, and each one causes
an interrupt-on-change. Because of your #if-#elseif structure, only the
LOWTOHIGH code will be compiled into the program.
Also, #if LOWTOHIGH only affects what section of code is compiled into
the program. That statement doesn't affect anything when the PIC is
actually running the program. Maybe you were confused by this.
Your code is looking for a low, followed by a high. This low-high sequence
is the rising edge of your pulse. That's what you want it to do.
Code: |
"High" bit_test(current,4) == True for the current sample
________ __|_____________
| |
| |<-- Rising Edge
|__________|
|
"Low" !bit_test(last,4) == True for the previous sample
When both tests are true, you have detected the rising edge.
|
The first edge (the falling edge) will not be be detected by this code.
That's what you want (I assume). You want to detect the rising edge. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Tue Feb 26, 2019 6:57 am |
|
|
I'm thinking you've got 2 problems. 1 hardware, 2nd code.
1)
note:
from CCS, in the FAQ section of the manual...
https://www.ccsinfo.com/faq.php?page=int_ext_button
...they do a delay inside the ISR to handle the pb 'bounce'. All mechanical switches have bounce ( sending several 1-0 transitions) when you use them
2)
you can modify(add to) this example to 'decode' whether the interrupt was from a rising or falling edge.
I'd start with just one pb(say B4) and get the code to work 100% then just copy 3x, edit as needed for b5,6,and 7. |
|
|
Pichuqy_1
Joined: 03 Aug 2010 Posts: 38
|
|
Posted: Tue Feb 26, 2019 8:43 pm |
|
|
I apologize for my English, it is not my native language. Thank you for your answers.
What I interpreted with this code is that, for the falling edge, the #if LOWTOHIGH is executed. And for rising edge the #elif HIGHTOLOW is executed. Am I wrong?
But in this case the segment #if LOWTOHIGH is executed twice, and I can not understand why. |
|
|
|
|
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
|