TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Cortijero en 16 de Abril de 2010, 10:20:56
-
Wenas! estoy trasteandole a la interrupcion de cambio de estado del portB, pero tengo un problemilla... lo simulo, y todo va bien, pero en el momento en que entra en la interrupcion, se queda en ella repitiendola una y otra vez. Donde esta el problema?
#include <18F4550.h> //Libreria del PIC
#fuses XT,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,NOVREGEN,NOPBADEN // fuse con cristal 4Mhz
#use delay (clock=4000000) //Configuramos oscilador a 4Mhz
#include <lcd.c> //Libreria para la lcd
#include <kbd.c> //Libreria para teclado matricial
#byte PortB=0x81
#bit led=PortB.0
//----------FUNCION INTERRUPCION----------
#INT_RB
void R4_7(){
delay_ms(20);
output_low(Pin_B0);
delay_ms(200);
}
//----------PROGRAMA PRINCIPAL-----------
void main(){
setup_adc_ports(NO_ANALOGS);
setup_comparator(NC_NC_NC_NC);
set_tris_b(0b11110000);
portb=0;
clear_interrupt(int_rb);
enable_interrupts(int_RB);
enable_interrupts(global);
do{
output_high(Pin_B0);
}while(true);
}
Por otro lado, si cambio los output_high/low(Pin_B0) por las funciones led=1 y led=~led, no va nada de nada... y en los primeros programas que hacia de encender y apagar un led hasta el infinito, estas funciones si que hiban bien :(
Saludos y muchas gracias!
-
http://www.todopic.com.ar/foros/index.php?topic=24920.0
-
Me he leido varios hilos del tema intentando comprender los codigos colgados y demas, y he hecho alguna modificacion, pero la cosa no ha cambiado... sigue repitiendose la interrupcion :(
include <18F4550.h> //Libreria del PIC
#fuses XT,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,NOVREGEN,NOPBADEN // fuse con cristal 4Mhz
#use delay (clock=4000000) //Configuramos oscilador a 4Mhz
#include <lcd.c> //Libreria para la lcd
#include <kbd.c> //Libreria para teclado matricial
#byte PortB=0x81
#bit led=PortB.0
//----------FUNCION INTERRUPCION----------
#INT_RB
void R4_7(){
flanco=PortB&0b11110000;
if(flanco!=11110000){
disable_interrupts(int_RB);
delay_ms(20);
output_high(pin_B0);
delay_ms(500);
output_low(Pin_B0);
enable_interrupts(int_RB);
}
#asm movf PORTB,0 #endasm
clear_interrupt(int_rb);
}
//----------PROGRAMA PRINCIPAL-----------
void main(){
setup_adc_ports(NO_ANALOGS);
setup_comparator(NC_NC_NC_NC);
set_tris_b(0b11110000);
portb=0;
clear_interrupt(int_rb);
enable_interrupts(int_RB);
enable_interrupts(global);
do{
}while(true);
}
-
Debes nada mas entrar en la interrupción desabilitarla y seguidamente refrescar el registro. Si activas la interrupción antes de refrescar el registro, se volverá a llamar y entra en un circulo vicioso. Por cierto con que pongas solamente la instrucción que te indico es suficiente:
#asm movf PORTB,0 #endasm
Un saludo
-
Debes nada mas entrar en la interrupción desabilitarla y seguidamente refrescar el registro. Si activas la interrupción antes de refrescar el registro, se volverá a llamar y entra en un circulo vicioso. Por cierto con que pongas solamente la instrucción que te indico es suficiente:
#asm movf PORTB,0 #endasm
Un saludo
He probado a poner esa linea antes de habilitar interrupciones, despues, al final, al principio... y nada :(
-
Espero que a estas alturas ya hayas solucionado el problema. Dejo esto principalmente para futuros lectores del foro. Espero ayude.
Esa instruccuón recomendada por jfh900 no es mas que una instrucción de assambler para leer el valor del puerto B. Puedes substituirla por otra mas sencilla como "PORTB=PORTB;". El chiste es que tienes que leer el puerto antes de salir de la interrupción, de otra manera la interrupción se quedara repitiendose a si misma.
//PRUEBA_INTERRUPCION.c
#include "htc.h"
#include "Led.h"
//CONFIGURACION
void configuracion_inicial(void)
{;
TRISA = 0B00000000; //Configura puerto a como salida.
TRISB = 0B00010000; //Configura puerto b como salida excepto RB1.
ANSEL = 0b00000000; //Selecciona modo digital para entradas con opción a modo análogo.
CMCON = 0B00000111; //Apaga los comparadores.
PORTB = 0b00000000; //Limpia puerto b.
PORTA = 0b00000000; //Limpia puerto a.
INTCON = 0B10001000; //Configura y activa interrupciones en por cambio en RB4 a RB7 .
};
//INTERRUPCION
static void interrupt
isr(void)
{;
LED('v',3845); // Prende un led bicolor en verde como medio seg ( tengo la función en otro archivo "Led.h")
PORTB=PORTB; // Refresca el puerto b (***ESTA ES LA INSTRUCCIÓN RECOMENDADA***)
RBIF = 0; // Limpia bandera de cambio RB4 a RB7
RBIE = 1; // Habilita interrupción de cabio en RB4 a RB7
GIE = 1; // Habilita interrupciones globales
};
//PRINCIPAL
void main(void)
{;
configuracion_inicial(); //Configuración
while(1) //Ciclo infinito
{;
SLEEP(); //Pone al pic a dormir hasta que se genere la interrupción
NOP(); //No hace nada
NOP(); //El pic continuaría aquí despues de la interrupción
}; //regresa al ciclo infinito
// FIN
};
Suerte.
-
como dice el amigo pakuak, espero que esto este solucionado, pero por ahi le veo eso de incluir funciones dentro de la interrupcion, ojo no digo que no se pueda a¿hacer, solo es algo que no recomiendo, tampoco es tema de los delay.
Al ingresar a la interrupcion se debe hacer lo menos posible dentro de ella. Sensear quien disparó la interrupcion, setear alguna flag, limpiar los flag antes de salir, esas son las instrucciones basicas y a mi me han servido, quizas con mayores complicaciones del programa se necesite algo mas, pero debe ser lo menos posible.
Tambien uso como ayuda encender algun led para detectar que ha entrado en la interrupcion, a modo de debugger.
Saludos