¿Cómo crear banderas en los PIC?

Si se pueden crear banderas (Flags) propias para cualquier evento, es algo muy común.

Nota: Microchip es el nombre de la empresa que fabrica los PIC y actualmente también los ATmega.
 
Gracias por aclarármelo. ¿Tienes algún ejemplo? Ya que he buscado y no encontré ni uno.
Muchos programas contienen banderas definidas por el programador y también los registros las tienen.

Por ejemplo, en ensamblador:
PHP:
    cblock 0xXX
        bandera
        ; Más variables.
    endc

timer0    equ    0
timer1    equ    1
otra    equ    2

; Servicio de interrupciones:
interrupciones
    btfss    INTCON,T0IF        ; ¿Se desbordó el Timer 0?
    goto    salir_sdi        ; No desbordó, ir a "salir_sdi"
    bsf    bandera,timer0        ; Sí desbordó. (Pongo en 1 la bandera "timer0")
    bcf    INTCON,T0IF        ; Pongo en 0 la bandera T0IF del registro INTCON
salir_sdi
    retfie                ; Salir del servicio de interrupciones.
                    ; Se regresará al punto en donde se produjo la interrupción.
En PICBasic (Compilador PBP o PBPX)
PHP:
Bandera_Timer0    Var Bit            ; Declarar "Bandera_Timer0" como variable de 1 bit

Servicio_Interrupciones:
    Disable                ; Desactivar Interrupciones globales.
    If INTCON.2 = 1 Then        ; ¿Se desbordó el Timer 0?
        Bandera_Timer0 = 1    ; Sí desbordó. Pongo en 1 "Bandera_Timer0"
        INTCON.2 = 0        ; Pongo en 0 la bandera T0IF del registro INTCON
    End If
    Resume                ; El programa regresará al punto donde se produjo la interrupción.
    Enable                ; Rehabilitar las interrupciones.
En C, dependerá del entorno usado.

Por ejemplo, en PIC C Compiler (PCWHD):
PHP:
int1 bandera_timer0 = 0;

#INT_TIMER0
void sdi_desborde_timer0 (void)
{
    bandera_timer0 = 1;
}
En este entorno no hay necesidad de poner la bandera T0IF en 0, porque el compilador lo hace automáticamente.

Y bueno, ya sabrás qué hacer cuando una bandera se encuentre en 1, pero siempre se debe poner en 0 después de la comprobación.
Y por lógica, cuando se usan interrupciones, siempre debe activarse la correspondiente.
 
Hola, ¿en que lenguaje de programación?
En lo personal, para ASM uso esta sintaxis

Código:
;Banderas de propósito específico

	#DEFINE		CARL		REGBAND,.6	;Bandera de acarreo en conversión de código binario-BCD
	#DEFINE		CARR		REGBAND,.5	;Bandera de acarreo en operaciónes matemáticas
	#DEFINE		SENS		REGBAND,.4	;Interrupción por solicitud del usuario (sensor)
	#DEFINE		TEMPO		REGBAND,.3	;Interrupción por expiración de tiempo del TMR1	
	#DEFINE		ERRM		REGBAND,.2	;Bandera de error matemático
	#DEFINE		CARFULL		REGBAND,.1	;Bandera de carga >97%

Previamente tengo definido a REGBAND como una variable en RAM

Ahora, en C me sirvo de la directiva "struct"

Código:
/*Registro de banderas de propósito general*/
union
{
   struct
   {
	  uint8_t	BUTTNCHA		:1;			//Bandera indicadora de boton pendiente por procesar
	  uint8_t	SYSON			:1;			//Bandera indicadora de sistema encendido
	  uint8_t	ENCO_PRES		:1;			//Bandera indicadora de botón de encoder presionado
	  uint8_t	ENCO_RIGHT		:1;			//Bandera indicadora de giro de encoder a la derecha
	  uint8_t	ENCO_LEFT		:1;			//Bandera indicadora de giro de encoder a la izquierda
   };
   uint8_t ALL;
}BANDERAS;

Saludos

PD. D@rkbytes comento lo mismo 1 min antes :oops:
 
Hola, ¿en que lenguaje de programación?
En lo personal, para ASM uso esta sintaxis

Código:
;Banderas de propósito específico

	#DEFINE		CARL		REGBAND,.6	;Bandera de acarreo en conversión de código binario-BCD
	#DEFINE		CARR		REGBAND,.5	;Bandera de acarreo en operaciónes matemáticas
	#DEFINE		SENS		REGBAND,.4	;Interrupción por solicitud del usuario (sensor)
	#DEFINE		TEMPO		REGBAND,.3	;Interrupción por expiración de tiempo del TMR1	
	#DEFINE		ERRM		REGBAND,.2	;Bandera de error matemático
	#DEFINE		CARFULL		REGBAND,.1	;Bandera de carga >97%

Previamente tengo definido a REGBAND como una variable en RAM

Ahora, en C me sirvo de la directiva "struct"

Código:
/*Registro de banderas de propósito general*/
union
{
   struct
   {
	  uint8_t	BUTTNCHA		:1;			//Bandera indicadora de boton pendiente por procesar
	  uint8_t	SYSON			:1;			//Bandera indicadora de sistema encendido
	  uint8_t	ENCO_PRES		:1;			//Bandera indicadora de botón de encoder presionado
	  uint8_t	ENCO_RIGHT		:1;			//Bandera indicadora de giro de encoder a la derecha
	  uint8_t	ENCO_LEFT		:1;			//Bandera indicadora de giro de encoder a la izquierda
   };
   uint8_t ALL;
}BANDERAS;

Saludos

PD. D@rkbytes comento lo mismo 1 min antes :oops:



Bueeno,, en enssembler esta bien.



a ya entendi,:D. GRACIAS
 
Última edición:
Espero que también sepas entender lo irrelevante que es crear otra bandera, cuando se trata de interrupciones.

Yo no entendí ese punto, declarar banderas secundarias de interrupción es algo que, en lo personal, hago eventualmente.

Por poner un ejemplo cuando se lee una serie de botones por medio de las interrupciones. El micro se mantiene atendiendo la aplicación principal y cuando es interrumpido por alguna pulsación entra a la ISR y ahí no hago más que establecer una bandera secundaria que le indica al bucle principal o local que se ha pulsado una tecla y entonces que desde ahí (main) llamo a la rutina que se encarga de decodificar el botón pulsado con su respectivo "retardo antirrebote" para después borrar esa bandera secundaria para la siguiente interrupción.

De no hacerlo así tendría que meter todo el proceso de retardo antirrebote en la misma ISR y eso quitaría valioso tiempo al main. Por demás que utilizar las mismas banderas de hardware del PIC (caso específico) hace que se haga una re-entrada a la ISR en un lazo interminable.

Por ello no creo que sea tan irrelevante :unsure:
 
Por poner un ejemplo. Cuando se lee una serie de botones por medio de las interrupciones. El micro se mantiene atendiendo la aplicación principal y cuando es interrumpido por alguna pulsación entra a la ISR y ahí no hago más que establecer una bandera secundaria que le indica al bucle principal o local que se ha pulsado una tecla y entonces que desde ahí (main) llamo a la rutina que se encarga de decodificar el botón pulsado con su respectivo "retardo antirrebote" para después borrar esa bandera secundaria para la siguiente interrupción.
A eso es a lo que me refiero.
Una bandera de interrupción X siempre está disponible y se puede comprobar su estado en cualquier parte del programa, por lo que es irrelevante declarar otra que prácticamente se le dará el mismo estado que la del registro verificado.
De no hacerlo así, tendría que meter todo el proceso de retardo antirrebote en la misma ISR y eso quitaría valioso tiempo al main.
Por demás que utilizar las mismas banderas de hardware del PIC (caso específico) hace que se haga una re-entrada a la ISR en un lazo interminable.
No necesariamente, porque el estado de la bandera activa, como mencioné anteriormente, siempre estará disponible desde cualquier parte del programa.
Y después de su comprobación por polling, se puede regresar a 0 para seguir comprobando el evento.
Por ello no creo que sea tan irrelevante :unsure:
Me parece que ya lo expliqué, y siempre he pensado qué... Al buen entendedor, pocas palabras. :cool:
 
Si, ya comprendo mejor... me doy cuenta que lo he estado haciendo mal usando esa técnica de programación, no tiene caso utilizar el vector de interrupción si es que la ISR la procesaré después (de hecho va contra la el objetivo y finalidad de las int's :oops:) y por lo tanto puedo hacer el "polling" de la bandera cuando sea necesario atenderla.

En mi ejemplo anterior, no tiene caso el uso de la bandera secundaria para los botones. Es mejor mantener el permiso de interrupción desactivado y solo hacer "polling" a su respectiva bandera dentro del "main" cuando así lo requiera, ya que esta sigue funcionando independientemente si tiene permiso o no de interrumpir al micro.

Bueno, mejoraré eso de ahora en adelante.


Saludos :apreton:
 
Por favor, sin van a modificar los flags desde rutinas de interrupción no se olviden de usar VOLATILE!!!!!

Sino se las van a ver con el optimizador de C...
 
Atrás
Arriba