fbpx

Expresate

Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:

Interrupcione en CC...
 
Avisos
Vaciar todo

Interrupcione en CCS

19 Respuestas
5 Usuarios
0 Reactions
8,907 Visitas
vcs
Respuestas: 114
 vcs
Topic starter
(@vcs)
Estimable Member
Registrado: hace 18 años

Buenas a todos

Voy a tratar de usar las interrupciones en un 16f877 y necesito un poco de ayuda, alguien conoce de algun link o manual en el que pueda informarme de en primer lugar en que consisten las interrupciones en un PIC y en segundo lugar como aplicarlas con CCS.

Es decir segun el manual de CCs he visto algunas intrucciones relativas a esto, pero no están nada claras, lo que yo conozco a nivel mas interno respecto a otros sistemas (que me imagino que serán portables) es que cuando realizas una interrupcion internamente en el micro el programa salta a una direccion fisica y real determinada y apartir de ahí empiezas a picar el codigo, si te lo haces todo en lenguaje maquina tienes que guardar el estado de los flag anterior al salto, bla bla bla... ahora leo que existen varios tipos de instrucciones sobre interrupciones en el ccs, entiendo que al igual que en otros sistemas las interrupciones podrian ser por flanco ascendente, descendente, temporizadas (y en determinados sistemas por cambio de flanco), en fin esto me imagino es igual pero es a muy groso modo, me ha parecido entender que en CCS existen ¿instrucciones para programar interrupciones de contador?, bueno hasta ahora lo que habia usado siempre para realizar un conteo es programar una interrupcion por flanco, y una vez hecho el salto a partir de esa direccion de memoria picar un incremento a una variable (la de conteo o contador) y volver a la direccion anterior al salto (asegunrandome de dejar todos los flag como estaban antes del salto) ahora con los PIC no se muy claro como iria ¿existe una instruccion especifica que realiza todo esto en el CCS? o existe alguna entrada hardware que se le pueda asignar esta funcion mientras el programa sigue corriendo, imagino que nó, que sea cual sea el metodo, el programa se parará hará el conteo y continua... en fin lo que estoy probando es hacer un conteo dentro de un recorrido determinado y ademas quiero implementar una señal NOT (Negative OverTravel) y POT (Positive OverTravel) es decir finales de carrera mediante interrupcion, es decir simplificando más necesito un contador por flanco y dos interrupciones de libre programacion por Flanco. o en su defecto tres de estas.

Como es evidente que no estoy muy puesto en el tema, no quiero aburrir a nadie y por eso solicito algun link o manual donde esto se explique con mas o menos detalle y a ser posible acompañado de ejemplos.

SALUDOS Y GRACIAS

Responder
18 respuestas
heli
Respuestas: 748
 Heli
(@heli)
Ardero
Registrado: hace 19 años

Si, makabra, con un PIC se puede hacer multitarea, igual que con cualquier otro micro. La multitarea se inventó mucho antes de que los micros la soportaran con recursos de hardware.
La pega es que tienes que escribir las tareas de forma "cooperativa", es decir, que no se queden nunca enganchadas en un bucle, ya que detendrían el proceso de las demás tareas.
Hoy en día lo normal es que el soporte de multitarea lo haga el Sistema Operativo (linux, uCos, windows?, etc), pero cuando no existe SO se puede hacer, con más esfuerzo y más cuidado. El pseudocódigo que ha puesto Ranganok es un ejemplo típico de programa multitarera. No es muy dificil de implementar. Lo importante es que ninguna terea detenga la ejecución del resto.

Responder
gonzao
Respuestas: 218
(@gonzao)
Estimable Member
Registrado: hace 19 años

Hola a todos:
Tengo problemas en el envío por el puero serie con CCS.
El objetivo es manejar tanto el envio como la recepción por interrupción. He simplificado el programa para poder encontrar el fallo. Por sondeo/polling todo guay pero eso, quiero que al enviar me genere la interrupción.
Veo que el problema está ahí, porque si tengo TXIE a '1' y transmite , él pone a '1' TXIF y debería lanzar la interrupción.
El código es el siguiente:
#DEVICE PIC16F876A
#include <PIC16F876A>
/*------- g0n -------*/
#fuses HS,NOWDT

int transmitido=1;
int recibido=0;

char dato=0;

#int_RDA // interrupción caracter_recibido
RDA_isr(){
//RCIF=0; // se borra automáticamente al leer
dato=RCREG;
recibido=1; // activa flag
}
#int_TBE
TBE_isr()
{
TXIE=0;
//TXIF=0; // se borra automaticamente al cargar un nuevo dato para enviar
transmitido=1;
}

void main()
{
// configuro comunicaciones serie
SPBRG = 0x81; //-- 9600 baudios (con cristal de 20MHz)
TXSTA = 0x24; //-- Configurar transmisor
RCSTA = 0x90; //-- Configurar receptor
// habilito int recepcion/transmision uart
//PIE1 |= 0x30; // habilito Int rx y tx
RCIE = 1;
TXIE = 0;
GIE = 1;
PEIE = 1;

while(1)
{
if(recibido)
{
recibido=0;
if(transmitido)
{
TXREG=dato;
TXIE=1;
transmitido=0;
}
}

}//while(1)

}Ahora básicamente es un ECO. Me da que falla en #int_TBE porque la primera vez repite la letra pero luego ya no. eso es que no me marca transmitido a 1. Puede que esté equivocado, lo de #int_TBE es lo más parecido a lo que necesito no?, una interrupción cuando se ha enviado el dato, al igual que #int_RDA que es cuando se recibe.

A ver qué me podéis contar.
En resumen es: ¿cómo se maneja la interrupción de recepción del puerto serie de la usart con CCS?

Gracias, gONzAO

Responder
vcs
Respuestas: 114
 vcs
Topic starter
(@vcs)
Estimable Member
Registrado: hace 18 años

Buenas a todos, vuelvo a la carga.

He tenido un rato y por fin he podido tocar un poquito esto de interrupciones y para ir probando pues he empezado haciendo un programa que tan solo enciende y apaga las luces del puerto A de forma intermitente., apartir de aqui he comenzado a probar intentando hace una interrupcion que encienda solo el pin 1 del puerto A y haga una parada de 5 seg, luego en principio deberia de seguir encendiendo y apagando el puesto A como de principio.

Para esto la primera prueba que hice fue con Int_Rb, es decir al encender alguno de los pines b4, b5, b6, b7 del puerto B , pero no me funciono pues una vez ejecutado el codigo de la interrupcion no salta de nuevo al programa principal. el codigo es este:


#include <16F877A> // incluimos el archivo de definicion del PIC
#fuses XT,NOWDT // definimos que es un Crital y el NO Wdog activo (para el ICPROG)
#use delay (clock=1000000) // definimos la frecuencia del cristal

#use fast_io(a) // Elegimos el modo de los puertos
#use fast_io(b) // son de entrada o salida
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
#byte PORTA=0x05 // 6 patas// Definimos la Variable PORTA y PORTB como los puertos ya que por defecto no viene definido
#byte PORTB=0x06 // 8 patas
#byte PORTC=0x07 // 8 patas
#byte PORTD=0x08 // 8 patas
#byte PORTE=0x09 // 3

/* LA INTERRUPCION */

#int_rb
VOID interrupcion()
{PORTA=0X01;
Delay_ms(5000);
}

/* Fin del codigo de la interrupcion */

void main(void) // Comienzo de programa, void quiere decir que no se obtendrá ningun valor de esta funcion

{

disable_interrupts(GLOBAL);// deshabilitamos las interrupciones por seguridad puesto que no las usaremos
enable_interrupts(int_rb);
enable_interrupts(GLOBAL);
set_tris_a(0x00); // Puerto a definido como salida
set_tris_b(0xff); // el Puerto e lo definimos como entrada
PORTB=0;

do

{
PORTA=0xff; // Enciendo el puerto
Delay_ms(1000); // Espero un Segundo
PORTA=0; // Apago el puerto
Delay_ms(1000); // Espero un Segundo

}WHILE(TRUE);
} // Fin

Es decir el problema está en que en principio funciona bien, pero cuando activo la interrupcion, se corre el codigo del programa de la interrupcion, es decir que la interrupcioen es ejecutada y realiza lo que se ha programado en ella, pero tras correr el codigo de la interrupcion no vuelve por donde iba el programa, he probado a poner un Return y a poner un Break (aunque no se muy bien lo que hacen porque ni siquiera viene explicado en el manual del CCS en castellano)

Por otro lado he probado con la interrupcion externa, es decir por cambio de estado de Rb0, y esto ha funcionado perfectamente, la unica diferencia en el codigo es cambiar INT_RB por INT_EXT. ¿que es lo que me está fallado en la interrupcion por RB?, es decir que diferencias aparte de la forma de lanzar la interrupcion existe. este es el codigo para INT_EXT


#include <16F877A> // incluimos el archivo de definicion del PIC
#fuses XT,NOWDT // definimos que es un Crital y el NO Wdog activo (para el ICPROG)
#use delay (clock=1000000) // definimos la frecuencia del cristal

#use fast_io(a) // Elegimos el modo de los puertos
#use fast_io(b) // son de entrada o salida
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
#byte PORTA=0x05 // 6 patas// Definimos la Variable PORTA y PORTB como los puertos ya que por defecto no viene definido
#byte PORTB=0x06 // 8 patas
#byte PORTC=0x07 // 8 patas
#byte PORTD=0x08 // 8 patas
#byte PORTE=0x09 // 3

/* LA INTERRUPCION */

#int_ext
VOID interrupcion()
{PORTA=0X01;
Delay_ms(5000);
}

/* Fin del codigo de la interrupcion */

void main(void) // Comienzo de programa, void quiere decir que no se obtendrá ningun valor de esta funcion

{

disable_interrupts(GLOBAL);// deshabilitamos las interrupciones por seguridad puesto que no las usaremos
enable_interrupts(int_ext);
enable_interrupts(GLOBAL);
set_tris_a(0x00); // Puerto a definido como salida
set_tris_b(0xff); // el Puerto e lo definimos como entrada
PORTB=0;

do

{
PORTA=0xff; // Enciendo el puerto
Delay_ms(1000); // Espero un Segundo
PORTA=0; // Apago el puerto
Delay_ms(1000); // Espero un Segundo

}WHILE(TRUE);
} // Fin


Gracias por adelantado.

Responder
gonzao
Respuestas: 218
(@gonzao)
Estimable Member
Registrado: hace 19 años

En CCS no se bien como va, pero despues de atender una interrupción hay que borrar el flag de la misma (si no se borra sólo, que no suele ser el caso). Si no se hace lo que ocurre es que según vuelve al programa principal, ve que hay una interrupción pendiente y vuelve a entrar.., así hasta el infinito.
Para ver si es ese el problema, pon que en la interrupción te invierta el led y el delay para poder verlo. Si te parpadea el led tras provocar sólo 1 interrupción, ese era el problema.

Prueba con: clear_interrupt(int_rb); /* o algo parecido*/
al final de la atención a la interrupcion.

Ya nos contarás.

Un saludo
gONzAO

Responder
vcs
Respuestas: 114
 vcs
Topic starter
(@vcs)
Estimable Member
Registrado: hace 18 años

Nas

Pues segun lo que entiendo de lo que leo en el manual es el compilador quien se encarga de borrarlo.

También es el compilador quien borrará la interrupción (el flag). Sin embargo, nuestro programa es el encargado de llamar a la función ENABLE_INTERRUPT() para activar previamente la interrupción junto con el señalizador (flag) global de interrupciones.

Es decir que yo he de habilitar las interrupciones y poco mas.

Responder
Página 3 / 4
Compartir: