Compiler
Compiler
Compiler
Interrupciones
Con las interrupciones en un microcontrolador vamos a poder hacer que el dispositivo pare de
repente la tarea que está realizando para que haga o realice una función con urgencia y después
continúe haciendo su rutina habitual. Por ejemplo. cuando hacemos el llamado de funciones
desde el main, lo que se hace es que el programa ejecute un subprograma y luego regrese al
programa principal, sin embargo el programador esta definiendo en que momento debe saltar a
ejecutar la función mediante las instrucciones, por esta razón se considera sincronas.
Las interrupciones son desviaciones de flujo de control del programa
originadas asincrónicamente por diversos sucesos que no dependen del programador, es decir,
ocurren en cualquier momento.
Las interrupciones ocurren por sucesos externos como la generación de un flanco o nivel en un
PIN del microcontrolador o eventos internos tales como el desbordamiento de un contador,
terminación del conversor análogo a digital, entre otras.
Los pasos que se deben seguir para atender una interrupción, son los siguientes
Digitar la función correspondiente a la interrupción. La función debe comenzar con # y la interrupción
correspondiente, por ejemplo para la función de interrupción por RB0 se digita #int_EXT
En el programa principal, habilitar las interrupciones en forma global, con la
instrucción: enable_interrupts(GLOBAL);
En el programa principal, habilitar la interrupción correspondiente, como ejemplo se muestra como
habilitar la interrupción externa por RB0: enable_interrupts(INT_EXT);
Ejemplo 1
Hacer un programa que me incremente un contador de 0 a 9, cuando ocurra una
interrupción externa por RB0. Cuando el contador llegue a 9, comienza de nuevo en
cero. (El código de implementación se encuentra al final del post)
1 ext_int_edge(H_TO_L);
1 ext_int_edge(L_TO_H);
Codigo de Implementación:
A continuación se presenta el Código de Implementación de los dos ejemplos de vistos en
esta entrada con relación a las interrupciones externas por RB0. Recuerda que para ver el
código, solo basta con compartir la información de este post con alguno de los siguientes tres
botones.
Código Ejemplo 1
1 #INCLUDE <16F887.H>
2 #FUSES XT,NOLVP,NOWDT,PUT
3 #USE DELAY(CLOCK=4000000)
4 Byte CONST display[10]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67};
5 #BYTE PORTC = 7
6 #BYTE PORTB = 6
7 INT CONT=0;
8
9
10 #INT_EXT //Funcion de la Interrupcion
11 VOID INTERRUPCION()
12 {
13 DELAY_MS(200); //Retardo
14 CONT++; //Incremente la variable CONT
15 IF(CONT==10) //Si la variable CONT es igual a 10
16 CONT=0; //Ponga en cero la variable CONT
17 }
18
19 VOID MAIN()
20 {
21 SET_TRIS_B(0B11111111); //Configurar el puerto B
22 SET_TRIS_C(0); //Configurar el puerto C
23 ENABLE_INTERRUPTS(GLOBAL); //Habilita todas las interrupciones
24 ENABLE_INTERRUPTS(INT_EXT); //Habilita la interrupción externa
25 WHILE(TRUE)
26 {
27 PORTC= (display[CONT]); //Muestra lo que hay en la variable CONT en el display
28 }
29 }
Pueden descargar el código y el diseño en proteus aqui:
>>>>>8. Interrupciones<<<<<<<<
Código Ejemplo 2
1 #INCLUDE <16F887.h>
2 #DEVICE ADC=10
3 #USE DELAY(CLOCK=4000000)
4 #FUSES XT,NOPROTECT,NOWDT,NOBROWNOUT,PUT,NOLVP
5 #INCLUDE <LCD.C>
6
7 #BYTE PORTA= 5
8 #byte PORTB= 6
9 #byte PORTC= 7
10 #BYTE PORTD= 8
11
12 long contador=0;
13 int16 duty=0;
14 int Timer2,Poscaler;
15 double RPM;
16
17 //Interrubción por cambio en RB0
18 #INT_EXT
19 ext_isr()
20 {
21 contador++;
22 }
23 void main()
24 {
25 //Configura los Puertos del PIC
26 set_tris_a(0x01);
27 set_tris_b(0x01); //RB0 como entrada
28 set_tris_d(0);
29
30 //Configura la Entrada Analoga
31 setup_adc_ports(sAN0); //Configurar ADC (Lectura de temperatura)
32 setup_adc(adc_clock_internal); //Reloj interno para la conversion analoga digital)
33
34 //Configura el PWM
35 // Generemos una Señal cuadrada de 1 Khz
36 Timer2=249; //Se carga timer 2 con 249 como lo vimos en la pagina
37 //Preescaler=4; //Preescaler solo puede tomar valores de: 1 - 4 - 16
38 //Para el preescaler colocamos "t2_div_by_4"
39 Poscaler=1; //Preescaler solo puede tomar valores de: 1
40
41 setup_timer_2(t2_div_by_4,Timer2,Poscaler); //Configuracion de Timer 2 para establecer frec. PWM a 1kHz
42 setup_ccp1(ccp_pwm); //Configurar modulo CCP1 en modo PWM
43
44 //Habilita las Interrupcciones
45 enable_interrupts(int_ext); //Activa interrupcion por RB0
46 ext_int_edge(L_TO_H); //Activa interrupción por flanco de bajada
47 enable_interrupts(global); //Habilita interrupciones de forma global
48
49 lcd_init();
50 lcd_gotoxy(1,1);
51 LCD_PUTC("VELOCIDAD MOTOR");
52
53 //Hace por siempre
54 while(1)
55 {
56
57 //Lectura del Potenciometro
58 set_adc_channel(0); //Escoge el canal 0 de los puertos analogos
59 delay_us(100);
60 duty=read_adc(); //Almacena en duty el valor del voltaje del pot
61 set_pwm1_duty(duty);//10 bits= 1023 y 8bit= 255
62
63 //Espera por 1 segundo
64 delay_ms(999);
65
66 //Despues de 1 segundo multiplica el valor de los pulsos contados en
67 //contador y los multiplica por 60 (para pasarlo a minutos) y lo divide
68 //por el numero de pulsos que tiene el encoder, en este caso el encoder
69 //da 10 pulsos en 1 giro completo
70 RPM=contador*60/10;
71
72 //Reinicia el contador de Pulsos
73 contador=0;
74
75 //Visualiza la Velocidad
76 lcd_gotoxy(1,2);
77 printf(lcd_putc,"RPM: %f ",RPM);
78
79 }
80
81 }
Click aqui para descargar los archivos del medidor de velocidad del motor DC