Ejecución de varias rutinas a la vez en un PIC

Pseudocódigo:

Lanzar el timer con interrupción y activar las primeras luces

Bucle de mirar pulsador y encender el led. Te quedas aquí por los siglos de los siglos.

Funcion de atención a la interrupción, se reprograma el timer si no es autorecargable y se pone la siguiente secuencia de luces.




Más o menos tres funciones. No morirás en el empeño. Busca información de como se hace en c con un pic.
En c programo más bien poco y pics más bien nada. Si quieres el código en ensamblador de 8052 o en wiring del arduino te lo preparo.


Pon resistencias en los leds y quita las de los pulsadores.
 
Última edición:
Con hoja de datos del uC en mano, tenés que hacer lo siguiente:

1- Elegir un timer, creo que tenés 3 (0, 1 y 2).
2- Ver como se conecta ese timer con el circuito oscilador principal, esto implica posibles preescaler en clock principal.
3- Configurar la cuenta según los tiempos a fijar (buscar registro de cuenta).
4- Configurar los registros del timer para habilitar una interrupción por desborde.
5- Posiblemente se necesite habilitar las interrupciones en forma general (buscar registros).

Desde el código:

1- Implementar la inicialización en base a los puntos anteriores.
2- Implementar una rutina de interrupción que permita modificar el estado de una variable según el tiempo transcurrido (flags).
3- En el loop principal (while), preguntar c/tanto el estado de esos flags y modificar el estado de los leds según corresponda.

De todo eso, una mejora sería implementarlo usando una función de sleep que solo se despierte cuando exista una interrupción, en este caso del timer o por el pulsador.
 
Bueno, echar a dormir el micro ya sería para nota. Pero estaría bien, para un caso tan simple es perfectamente posible; tienes interrupciones sin usar para aburrir...
 
Bueno, echar a dormir el micro ya sería para nota. Pero estaría bien, para un caso tan simple es perfectamente posible; tienes interrupciones sin usar para aburrir...

Digamos que si, ya que está, que aproveche y aprenda lo más posible.

Igual no siempre se puede, en los AVR los muy.... no me salen las palabras en neutro... "¿mal bichos?".... no se despiertan cuando hay una interrupción por timer, así que habría que ver bien en esta familia que pasa.
 
yo cuando tenia dudas a quien recurria era ami mismo pues tenia profesores muy ineptos anclados al 8051 en modo ASM o al 16f84 en ASM

el foro no lo conocia, y un libro de base de datos en C para PC de 1994 me enseñaron mucho.

lo aprendido lo meti al pic16f628 y funciono!

lo que trato de decir es que no te debes apoyar al 100% en los demas si no en ti mismo y si salen dudas debes razonar apoyarte en ti
 
¿Podrían ayudarnos en este programa?
Lo que se quiere es que sea una rutina de pasos múltiples, la cual encienda un servo y un motor y después de 5 veces que el servo actúe, el motor debe parar.
Aparte el motor cuando llegue a un tope y lo capte un sensor, se debe regresar.

Hasta ahora tenemos esto. El problema es que compila pero ya en la simulación no funciona.
El servo no se mueve y no parece funcionar el motor.

Estamos usando el PIC16F648A.

PHP:
@3F10H
I VAR BYTE
PAUS VAR BYTE
SENSOR2 VAR BYTE
SENSOR1 VAR BYTE
CORTA VAR BYTE 
TRISB=%00001111
SENSOR1=PORTB.0
SENSOR2=PORTB.1

INICIACION:
IF SENSOR2= 0 THEN
    CALL SERV90
    PORTB.4=%01
    GOTO INICIACION
    ELSE 
    PORTB.4=0
    ENDIF 
GOTO PROCESO

PROCESO: 
CORTA = 0

AQUI: PORTB.6=%10

    IF SENSOR1 = 1 THEN 
    CALL CORTAR
        GOTO AQUI
    ELSE
    GOTO PROCESO
     ENDIF   
SERV90: FOR I = 0 TO 20 
        PULSOUT PORTB.5,98
        next i
        return
    
  CORTAR: CORTA = CORTA +1
        FOR I = 0 TO 20 
        PULSOUT PORTB.5,180
        pause 10 
        next i
        IF CORTA = 5 THEN
        GOTO PAUSA
        ENDIF
        return
        
  PAUSA:
    FOR PAUS=0 TO 60
    PAUSE 1000
    NEXT PAUS
    
  END
 
Cuando te hacen faltan Timers .... Usa soft-timers
Cuando no hay interrupciones .... Usa monitoreo continuo
Aqui les dejo una pequeña aportación para el viejisimo pero muy funcional PIC16F54 ... me gusta por
su precio ...solo una soda ($0.54 us) y si quiero hacer aplicaciones más complejas uso su upgrade el
PIC16F18855 a un costo de una soda y su hotdog ($1.40 us).

Basado en MicroChip nota de aplicación an-585 " A RTOS"

Código:
; Ultima edicion: Abril 27, 2017
; - decrements active timers
; - 4 MHz oscillator
; - period: 1 millisec. (prescaler divide by 8)
; - subClock: 0 .. 125  (125 * 8 = 1000 nsec )
;Usa las variables:
;     sample     EQU   0x07   = copia actual del TMR0
;     incr       EQU   0x08   = Incremento de TMR0 desde ultima revicion
;     prevTMR0   EQU   0x09   = 
;     subClock   EQU   0x0A   =
;     timer1     EQU   0x0B   = Timer de 8-Bits
;     timer2L    EQU   0x0C   = Timer de 16 bits
;     timer2H    EQU   0x0D
;     Time_bit   EQU   0x0E   = Bits para indicar cuando ya
;                                    transcurrio el Tiempo


timerTick
      MOVF  TMR0,W       ; Obten copia del tiempo actual en TMR0
      MOVWF sample
                         ; Calcula cuanto tiempo ha trascurrido
      MOVF  prevTMR0,W   ; desde la ultima vez que revisamos
      SUBWF sample,W     ; incr = sample - prevTMR0
      MOVWF incr

      MOVF  sample,W     ; y actualiza prevTMR0
      MOVWF prevTMR0
 
      MOVF  incr,W       ; Lleva B a W
      SUBWF subClock,1   ; Has A - B  (subClock -incr)
                         ; 
      BTFSC STATUS,CarryF ; A > B -> C = 0
      GOTO  m002         ; Si: Salte todavia no trascurre un Tick
                         ; No: Ya transcurrio más de un Tick
      MOVLW 125          ;     /* new 1 millisec. tick */
      ADDWF subClock,1   ; Añade la cuenta para otro milisec
	  
;   Incrementa Soft-Timers y ve si han llegado a su cuenta limite
;     cuando esto ocurre las banderas de timeout en Time_bit
;     son ajustadas a zero 
;   Revisa si los Soft-Timers son > a su limite

Test_ST01
      BTFSC Time_bit,timeout1 ; Timer1 > Limite -> timeout=0  
      GOTO  Test_ST02     ; No: Revisa siguiente Soft-timer
                          ; Si: timeout = 0
      DECF  timer1,1      ;     Decrementa soft-Timer 
      INCF  timer1,W      ;     y Revisa si llego al limite
      BTFSC STATUS,ZeroF  ;       == 255?
      BSF   Time_bit,timeout1 ; Si: Ajusta Bandera a 1
	                      ; y revisa el siguiente Soft-Timer
;
Test_ST02
      BTFSC Time_bit,timeout2 ; Timer1 > Limite -> timeout=0 
      GOTO  Test_ST03     ; No: Revisa siguiente Soft-timer
                          ; Si: timeout = 0
      DECF  timer2L,1     ;     Decrementa soft-Timer 
      INCFSZ timer2L,W    ;     y Revisa si llego al limite
                          ;     el byte bajo == 255?
      GOTO  Test_ST03     ;  No: Todavia no se llega al limite
                          ;      asi que revisa el siguiente Soft-Timer
      DECF  timer2H,1     ;  Si: Incrementa la cuenta del bit alto
      INCF  timer2H,W     ;      Revisa si se llego al limite
      BTFSC STATUS,ZeroF  ;      el byte alto == 255?
      BSF   Time_bit,timeout2 ; Si: Ajusta Bandera a 1
                          ;     No: Checamos el siguiente Soft-Timer
Test_ST03                 ;
m002                      ; Como ya no hay mas Soft-Timers
	  RETLW 0             ; Nos regresamos

Observen que tiene dos soft-timers ...uno de 16-Bits y otro de 8-Bits



Y como la primera vez que lei la nota AN-585 " A RTOS" se me hizo muy engorrosa, les dejo
el desgloce que edite para ayudarme a entenderla
Código:
El RTOS ejemplo "Alarma serie"

; The code segment lines 1-87 are explained in this paragraph.
; Line 4 tells the MPASM assembler which PICmicro you
; are using.
        list    p=16C54,t=ON,c=132

        include "P16C5X.INC"

; The include file PICREG.H follows with the
; equates and assignments to make the code more
; readable and changeable. You should use equates that
; relate symbols to each other.
;
; The Constants  lines 10-12 are the values to change
;   for different Baud rates.
; Constants
INDIR          equ     0           ;Indirect Register
OUT_BIT_TIME   equ     33h         ;9600 Baud, 104uS Bit Rate
IN_BIT_TIME    equ     64h         ;4800 Baud, 208uS Bit Rate
FUDGE_TIME     equ     23h         ;Current Time within a Fudge Factor

; They represent the Bit Times for the Baud rates divided
;  by 2 minus some latency factor. You might have to
;  adjust the “Fudge Factor” and other values to fine tune
;  the performance. The value used for the “Fudge
;  Factor” is related to the longest path of code.
;
; Lines 21-24 are an experiment that allows a simple
;  name to be associated to a single bit.
;  This allows for easily changeable assignments.
; PORTB Register Definitions
#define Level_Reset    PORTB,0     ;Low will cause Past Level to reset
                                   ;RB.7 - RB.1 == Input from Sensors
RB_TRIS        equ     B'11111111' ;RB TRIS at INIT State == all input
RB_MASK        equ     B'00000000' ;What is High/Low for RB at INIT State

; A Register Definitions - Programmable Inputs
#define Serial_IN_1    PORTA,0     ;Serial Input #1 - 8 bits
#define LED            PORTA,1     ;LED Output - Level/State Indicator
#define Serial_Out     PORTA,2     ;Serial Output - 8 bits + passwords
#define Serial_IN_2    PORTA,3     ;Serial Input #2 - 8 bits

RA_TRIS        equ     B'11111001' ;RA TRIS at INIT State  RA1,2 Output
RA_MASK        equ     B'00000000' ;What is High/Low for RA at INIT State
;
; Lines 30-54 are the variable assignments.
;   Variables (lines 35-39) are used as time counters.
;   They count the number of units of time, and are compared
;   to literals to see if an Event has just happened.
;
; Register Files RAM
temp           equ     07h          ;Tempary holding register - PIC16C54/56
Timer_Bits     equ     08h          ;Indicates which Timer(s) are Active = 1
Flags          equ     09h          ;Error Flags
LED_Mode       equ     0Ah          ;(0-2)=Mode, 3=LED_B, (4-6)=Seq #, 7=NEW
OState         equ     0Bh          ;Serial Out State
T_5_M_LO       equ     0Ch          ;5 Min Timer Counter - Low
T_5_M_HI       equ     0Dh          ;5 Min Timer Counter - High
T_5_S_CO       equ     0Eh          ;5 Second Timer - lack of Serial Input
T_20_mS_CO     equ     0Fh          ;20 mS Timer - used for debouncing
LED_C          equ     10h          ;LED Counter
Last_TMR0      equ     11h          ;Last value of the TMR0
First_TMR0_O   equ     12h          ;Starting time for next Output event
xmt_byte       equ     13h          ;Serial xmit byte - destroyed in use
Curnt_Cnt      equ     14h          ;256 * TMR0 time μs
RCV_Storage    equ     15h          ;Long term storage of rcv_byte #1 & 2
Old_RB         equ     16h          ;Oldest/Master copy of RB
Last_RB        equ     17h          ;Last copy of RB
IState1        equ     18h          ;Serial In #1 State
First_TMR0_I1  equ     19h          ;Starting time for next #1 Input event
nbti1          equ     1Ah          ;Next Bit #1 In Time - variable time 
rcv_byte_1     equ     1Bh          ;Receive Serial #1 In byte
IState2        equ     1Ch          ;Serial In #2 State
First_TMR0_I2  equ     1Dh          ;Starting time for next #2 Input event
nbti2          equ     1Eh          ;Next Bit #2 In Time - variable time
rcv_byte_2     equ     1Fh          ;Receive Serial #2 In byte

; The bits defined in lines 57-64 are used as Binary Semaphores.
;   They keep Critical Sections of data protected.
;   We will see them in action later in the code.

; Indicates which Timer(s) are Active = 1 & Flags
#define OState_B      Timer_Bits,0  ;Serial Out Active Bit
#define IState1_B     Timer_Bits,1  ;Serial IN #1 Active Bit
#define IState2_B     Timer_Bits,2  ;Serial IN #2 Active Bit
#define T_5_S_B       Timer_Bits,3  ;5 Second Timer Active Bit
#define T_5_M_B       Timer_Bits,4  ;5 Min Timer Active Bit
#define RCV_Got_One_B Timer_Bits,5  ;Got a NEW Received byte to send out
#define RB_NEW_B      Timer_Bits,6  ;Indicates a change in RB input
#define S_5_S_B       Timer_Bits,7  ;Serial In 5 secs of inactivity

; The bits defined in lines 67-73 are error flags.
;   They define the current or last error states of the Serial
;   routines, and whether data was lost coming in or out.

; Error Flags
#define FS_Flag_1      Flags,0       ;Serial #1 IN had a False Start Error
#define FE_Flag_1      Flags,1       ;Last Serial #1 IN had a Frame Error
#define FS_Flag_2      Flags,2       ;Serial #2 IN had a False Start Error
#define FE_Flag_2      Flags,3       ;Last Serial #2 IN had a Frame Error
#define RCV_Overflow   Flags,4       ;Lost Serial Input Byte - too Slow
#define RB_Overflow    Flags,5       ;Lost RB Input Byte - too Slow
#define S_5_S_Overflow Flags,6       ;Lost '5S Inactivity' msg - too Slow

;
; The section of equates in lines 76-85 are used to define
; the different LED activity. They are used by Task #7 to
; keep the LED blinking.
;
;Equates for LED Task #7
#define LED_B          LED_Mode,3    ;LED is active
#define LED_NEW_B      LED_Mode,7    ;LED has just changed Modes = 1
LED_OFF_MODE    equ    B'00001000'   ;LED OFF
LED_SEQ1_MODE   equ    B'10001001'   ;LED Sequence 1: .2s On, 1s Off
LED_SEQ2_MODE   equ    B'10001010'   ;LED Sequence 2: 3x(.2s), 1s Off
LED_SEQ3_MODE   equ    B'10001011'   ;LED Sequence 3: 5x(.2s), 1s Off
LED_SLOW_MODE   equ    B'10011100'   ;LED Slow Pulsing - .3 Hz
LED_MEDIUM_MODE equ    B'10011101'   ;LED Medium Pulsing - 1 Hz
LED_FAST_MODE   equ    B'10011110'   ;LED Fast Pulsing - 3 Hz
LED_ON_MODE     equ    B'10001111'   ;LED ON Continuously

; In lines 89-94, we try to save the all important first 256
;  bytes of any page.

; Clear Registers 7-1Fh 

Clear_Regs   

        GOTO    Do_Clear_Regs        ;Save space in first 256 bytes

; Determine the Highest Error Level & Start Task #7 outputing the new Level

D_H_E_L   

        GOTO    Do_D_H_E_L           ;Save space in first 256 bytes
;
; Task #1 outputs a byte Asynchronously over the Serial
; Output pin. Task #1 is started at line 98.
;  The time units used for Tasks #1-4 are 2μS.
;  Task #1 - Asynchronous 9600 Baud Serial Output (LOW=0)
;
; When Tasks #1-4 are then allowed to run, they check the
; difference between the first sample and the current time.
;  If the delta is greater than or equal to the delay,
;    then that Event has just happened.
;  We first check if the state of the Serial Output is zero.
;  We then jump to OStateS to start the outputting of the
;   “Start Bit”. Because any Serial Output timings must be
;   rock solid, we use a trick in lines 101-116 that helps greatly.
; We check if we are within a certain amount of time BEFORE
;   the deadline and then wait for the time to output another bit.
; This trick allows us to be within a certain ± amount of time
; within the expected time to output that bit. With this code,
; we are about <±8% accurate for the Serial Output.
; You can only use this trick on the most critical tasks,
;  and only on one. In this section of code, we are constantly checking
;  the delta of time from the “FIRST_TMR0_O” reading
;  and the current reading of TMR0.
; When we are very close to the output time, we jump to line 117 (_0005).
;
Do_OState
        MOVF    OState, F           ;if OState == 0   
        BTFSC   STATUS, Z           ;        
        GOTO    OStateS             ;   then goto Output-Start-Bit

		;  We first sample the TMR0 and store the count.

        MOVF    TMR0, W             ;Get current time  
        MOVWF   temp                ;    & store in temporary variable
        MOVF    First_TMR0_O, W     ;Get elapsed time; Time Unit = 2 uS 
        SUBWF   temp, F             ;Delta of Current Time & Orginal Time
        MOVLW   FUDGE_TIME          ;Take in account processing time to do it
        SUBWF   temp,W              ;Time within fudge factor ? 
        BTFSS   STATUS, C
        GOTO    _0005               ;Not time yet to change States so return
;   Check if we are within a certain amount of time BEFORE
;   the deadline and then wait for the time to output another bit.
_0003   MOVLW   OUT_BIT_TIME        ;Past time for next out-bit ? 
        SUBWF   temp,W          
        BTFSC   STATUS, C           ;Do some delaying until it is time
        GOTO    _0004               ;It is now time to out put a bit
        MOVLW   H'04'               ;Account for loop delay 
        ADDWF   temp, F
        NOP                         ;   make loop delay even
        GOTO    _0003               ;Wait for exact time to output bit


;****** 
; If we are not even close to the proper time, we exit back to the
; main loop, so we can check the other timers and tasks.
;
; Now look at Figure 4 for a description of the Output Pulses,
; the “Bit units of Time”, and the associated state numbers.
; Note that the activities are spread out over time.
; The timer Events help to define the different states and
;  their associated output activities. Each Event is
;  handled in a very short, well-defined set of code as Task #1.
; Lines 117-131, are a quick state jump table.
		; State machine  --- OState = state table Entry
_0004   MOVF    OState, W          ;Get (0-A) mode #
        ANDLW   H'0F'              ;Get only mode #  
        ADDWF   PCL, F             ;jump to subroutine
        GOTO    OStateS            ;Serial Start Bit
        GOTO    OState0_7          ;Bit 0 
        GOTO    OState0_7          ;Bit 1 
        GOTO    OState0_7          ;Bit 2 
        GOTO    OState0_7          ;Bit 3 
        GOTO    OState0_7          ;Bit 4 
        GOTO    OState0_7          ;Bit 5 
        GOTO    OState0_7          ;Bit 6 
        GOTO    OState0_7          ;Bit 7 
        GOTO    OStateE            ;Serial Stop Bit
        GOTO    OStateL            ;Last State 
_0005   RETLW   H'00'

; You need to break all Real-Time code into very short
;  segments  in and then out.
;  Each segment is just a few lines long.
; You do your activity, save status, and increment to
;  the next state.
; Notice that OState0_7 code is used several times to
;   output all 8 bits.
; The state variable (OState) is used also to count the number
;   of bits already outputted.
; The time to the next outputting of a bit is calculated
;   and is adjusted to take out the accumulation of
;   errors in lines 151-152.
OS_End  MOVLW   OUT_BIT_TIME       ;Adjust out the cumulation of error   
        ADDWF   First_TMR0_O, F
        INCF    OState, F          ;increment to next state 
        RETLW   H'00'

; We make sure of a full “Stop Bit” length in the OStateE code.
; In the OStateL code,
OStateL   
        CLRF    OState             ;Ready to send next byte out  
        BCF     OState_B           ;Serial Out not active  
        RETLW   H'00'

;   we reset the OState variable to zero, and tell the world
;   that we are not outputting now in line 157.
; This is important because we use that bit (OState_B)
;   to Signal that we need to protect the variable xmt_byte
;   that changes over several states.
; We also use it to Signal that we are ready for another byte
;   to output.
; Look at Task #4. See how it uses this Semaphore to full advantage.
; We have just explained a Critical Segment variable as
;   outlined in the theory sections of this article.
;
; Task #2 starts at line 302.
; Task #2’s subroutines continue at line 363 and continue until line 423.
; This task reads the Serial Input #1 for Asynchronous data.
; Task #2 can be described as a State Machine for outputting
;  a byte Serially.
; Task #2 reads the Serial Input line 1, running at 4800 Baud.
;******         ;Task #2 - Asynchronous 4800 Baud Serial Input (LOW=0)
Do_I1State   
        MOVF    IState1, F          ;if IState1 == 0  
        BTFSC   STATUS, Z           ;      then Do Start Bit 
        GOTO    I1StateS
        MOVF    TMR0, W             ;Get current time
        MOVWF   temp
        MOVF    First_TMR0_I1, W    ;Get elapsed time; Time Unit = 2 uS 
        SUBWF   temp, F
        MOVF    nbti1, W            ;Past time for next input bit ? 
        SUBWF   temp, W
        BTFSS   STATUS, C
        GOTO    _0033
	; State machine - IState1 = State table entry
        MOVF    IState1, W          ;Get (0-B) mode #
        ANDLW   H'0F'               ;Get only mode #  
        ADDWF   PCL, F              ;jump to subroutine
        GOTO    I1StateS            ;State - Serial Start Bit 
        GOTO    I1State2            ;State - 1/2 of Start Bit - see if False Start
        GOTO    I1State0_7          ;State - Bit 0  
        GOTO    I1State0_7          ;State - Bit 1  
        GOTO    I1State0_7          ;State - Bit 2  
        GOTO    I1State0_7          ;State - Bit 3  
        GOTO    I1State0_7          ;State - Bit 4  
        GOTO    I1State0_7          ;State - Bit 5  
        GOTO    I1State0_7          ;State - Bit 6  
        GOTO    I1State0_7          ;State - Bit 7  
        GOTO    I1StateE            ;State - Serial Stop Bit 
        GOTO    I1StateL            ;Last State - End of Stop Bit
_0033   
        RETLW   H'00'


;***            ;Subroutines for Task #2
I1StateS                           ;Start Bit - Setup timing variables
        BSF     IState1_B          ;Serial Input Active 
        MOVF    TMR0,W             ;Store starting time
        MOVWF   First_TMR0_I1
        MOVLW   H'0D'              ;Fudge again 
        SUBWF   First_TMR0_I1, F
        MOVLW   H'32'              ;Time delay = 1/2 bit time 
        MOVWF   nbti1
        INCF    IState1, F         ;Increment to next state  
        RETLW   H'00'

I1State2                           ;Check if still a Start Bit
        BTFSS   Serial_IN_1        ;False Start Error ? 
        GOTO    FS_Error_1
        BCF     FS_Flag_1          ;Start Bit OK  
        MOVF    nbti1, W           ;Adjust out the error
        ADDWF   First_TMR0_I1, F
        MOVLW   IN_BIT_TIME        ;Time Delay = full bit time
        MOVWF   nbti1
        INCF    IState1, F         ;increment to next state
        RETLW   H'00'

I1State0_7                         ;Bit 0 - 7 
        BTFSS   Serial_IN_1        ;Move Input bit into C    
        BCF     STATUS,C
        BTFSC   Serial_IN_1
        BSF     STATUS,C
        RRF     rcv_byte_1, F      ;Move C into left most bit 
        MOVF    nbti1,W
        ADDWF   First_TMR0_I1, F   ;Adjust out the error
        INCF    IState1, F         ;increment to next state 
        RETLW   H'00'

I1StateE                           ;Check if we have a proper Stop Bit
        BTFSC   Serial_IN_1        ;Frame Error
        GOTO    F_Error_1
        BCF     FE_Flag_1          ;Stop Bit OK
        CLRF    T_5_S_CO           ;Reset 5 Sec Timer - got a good byte 
        ;Process the msg Here !
        MOVF    rcv_byte_1, W      ;Make a copy of just received byte  
        MOVWF   RCV_Storage
        BTFSS   RCV_Got_One_B      ;Report Lost data 
        BCF     RCV_Overflow
        BTFSC   RCV_Got_One_B
        BSF     RCV_Overflow
        BSF     RCV_Got_One_B      ;We Now have a RB Value to go out 
I1StateL   
        CLRF    IState1            ;Ready to receive next byte
        BCF     IState1_B          ;Serial In not currently active
        RETLW   H'00'

FS_Error_1                         ;False Start - Shut Down Checking
        BCF     IState1_B          ;Serial Input NOT Active
        BSF     FS_Flag_1          ;False Start Error 
        GOTO    I1StateL           ;Start All Over 
F_Error_1                          ;Frame Error - Wait for End of Stop Bit 
        MOVF    nbti1,W            ;Adjust out the error
        ADDWF   First_TMR0_I1, F
        MOVLW   H'32'              ;Time Delay = 1/2 bit time
        MOVWF   nbti1
        BSF     FE_Flag_1          ;Frame Error for this Byte ?
        INCF    IState1, F         ;Increment to next state
        RETLW   H'00'

; The code structure is very similar to that of Task #1 (Figure 3).
; Notice that there are more states than the Serial Output Task #1.
;  Once the “Start Bit” is detected, we half step into the
;  “Start Bit” to see if it was a “False Start” or not.
; We then sample and store theincoming bits to form an 8-bit byte
;  just like Task #1.
;  We sample the “Stop Bit” to see if it is a “Frame Error”.
;  We delay another 1/2 bit to get to the end of the “Stop Bit”
;   if there was an “Frame Error” before resetting Task #1’s
;   state to 0. Otherwise, we reset Task #1’s state to 0, and
;   Signal that we are ready for another “Start Bit”.
; The just received byte is stored in variable “RCV_Storage”.
; A check is made to see if we already sent out the last
;  received byte before clobbering the old byte with the new byte.
;

; Task #3 reads the Serial Input line 2, running at 4800 Baud.
; The code structure is the same as Task #2
; Task #3 interrupts the code of Task #2 at line 333 and continues
;   until line 362.
; Task #3’s subroutines continue at line 424 and continue until line 484
;   is reached.
; The received byte is also put into the same
; storage variable as Task #2 - “RCV_Storage”.
; When either Task #2 or Task #3 receives a valid byte,
;   Task #8’s counter is reset.
;   You can up the Baud rate of Task #2 and 3 if you lower the output
;   Baud rate of Task #1.
; Note that for reading the Serial Input Lines, you can be
; off by ±15% for each sampling, but not accumulatively

;******    ;Task #3 - Asynchronous 4800 Baud Serial Input (LOW=0)

Do_I2State   
        MOVF    IState2, F          ;if IState1 == 0
        BTFSC   STATUS, Z           ;   then Do Start Bit 
        GOTO    I2StateS
        MOVF    TMR0, W             ;Get current time
        MOVWF   temp
        MOVF    First_TMR0_I2, W    ;Get elapsed time; Time Unit = 2 uS
        SUBWF   temp, F
        MOVF    nbti2, W            ;Past time for next input bit ? 
        SUBWF   temp, W
        BTFSS   STATUS, C
        GOTO    _0035
	; State machine - IState2 = State table entry
        MOVF    IState2,W           ;Get (0-B) mode #
        ANDLW   H'0F'               ;Get only mode #  
        ADDWF   PCL, F              ;jump to subroutine 
        GOTO    I2StateS            ;State - Serial Start Bit 
        GOTO    I2StateS2           ;State - 1/2 of Start Bit - see if False 
Start  
        GOTO    I2State0_7          ;State - Bit 0
        GOTO    I2State0_7          ;State - Bit 1
        GOTO    I2State0_7          ;State - Bit 2
        GOTO    I2State0_7          ;State - Bit 3
        GOTO    I2State0_7          ;State - Bit 4
        GOTO    I2State0_7          ;State - Bit 5
        GOTO    I2State0_7          ;State - Bit 6
        GOTO    I2State0_7          ;State - Bit 7
        GOTO    I2StateE            ;State - Serial Stop Bit 
        GOTO    I2StateL            ;Last State - End of Stop Bit 
_0035   RETLW   H'00'
;
;***    ;Subroutines for Task #3
I2StateS                           ;Start Bit - Setup timing variables
        BSF     IState2_B          ;Serial Input Active  
        MOVF    TMR0, W            ;Store starting time 
        MOVWF   First_TMR0_I2
        MOVLW   H'0D'              ;Fudge again   
        SUBWF   First_TMR0_I2, F
        MOVLW   H'32'              ;Time delay = 1/2 bit time
        MOVWF   nbti2
        INCF    IState2, F         ;Increment to next state
        RETLW   H'00'

I2StateS2                          ;Check if still a Start Bit
        BTFSS   Serial_IN_2        ;False Start Error ?  
        GOTO    FS_Error_2
        BCF     FS_Flag_2          ;Start Bit OK 
        MOVF    nbti2,W            ;Adjust out the error 
        ADDWF   First_TMR0_I2, F
        MOVLW   IN_BIT_TIME        ;Time Delay = full bit time 
        MOVWF   nbti2
        INCF    IState2, F         ;increment to next state
        RETLW   H'00'

I2State0_7                         ;Bit 0 - 7 
        BTFSS   Serial_IN_2        ;Move Input bit into C
        BCF     STATUS, C
        BTFSC   Serial_IN_2
        BSF     STATUS, C
        RRF     rcv_byte_2, F      ;Move C into left most bit 
        MOVF    nbti2, W
        ADDWF   First_TMR0_I2, F   ;Adjust out the error    
        INCF    IState2, F         ;increment to next state 
        RETLW   H'00'

I2StateE                           ;Check if we have a proper Stop Bit
        BTFSC   Serial_IN_2        ;Frame Error
        GOTO    F_Error_2
        BCF     FE_Flag_2          ;Stop Bit OK 
        CLRF    T_5_S_CO           ;Reset 5 Sec Timer - got a good byte
        ;Process the msg Here !
        MOVF    rcv_byte_2, W      ;Make a copy of just received byte 
        MOVWF   RCV_Storage
        BTFSS   RCV_Got_One_B      ;Report Lost data 
        BCF     RCV_Overflow
        BTFSC   RCV_Got_One_B
        BSF     RCV_Overflow
        BSF     RCV_Got_One_B      ;We Now have a RB Value to go out   
I2StateL   
        CLRF    IState2            ;Ready to receive next byte 
        BCF     IState2_B          ;Serial In not currently active 
        RETLW   H'00'

FS_Error_2   
        BCF     IState2_B          ;False Start - Shut Down Checking
        BSF     FS_Flag_2          ;False Start Error 
        GOTO    I2StateL           ;Start All Over

F_Error_2                          ;Frame Error - Wait for End of Stop Bit
        MOVF    nbti2,W            ;Adjust out the error 
        ADDWF   First_TMR0_I2, F
        MOVLW   H'32'              ;Time Delay = 1/2 bit time 
        MOVWF   nbti2
        BSF     FE_Flag_2          ;Frame Error for this Byte ? 
        INCF    IState2, F         ;Increment to next state 
        RETLW   H'00'

;
; Task #4 starts at line 538 and finishes at line 561.
; Task #4 controls the feeding of Task #1 from several other tasks
; that want data to be outputted. It uses several Semaphores
; to make sure that Task #1 is not bothered until
; it is ready for another byte.
;
Task_4 ;Task #4 - Finds next Buffered Byte to Send Out through Task 1
        BTFSC   OState_B           ;if outputing now then skip call
        GOTO    _0059
        BTFSS   RCV_Got_One_B      ;Got a NEW Received byte to send
        GOTO    _0057
        MOVF    RCV_Storage, W     ;Send just received byte 
        MOVWF   xmt_byte
        BCF     RCV_Got_One_B      ;Clear need to send old byte 
        BSF     OState_B           ;Start Task #1 & Lock Out Others 
        GOTO    _0059

_0057   BTFSS   RB_NEW_B           ;Indicates a change in RB input 
        GOTO    _0058
        MOVF    Old_RB, W          ;Send New RB value  
        MOVWF   xmt_byte
        BCF     RB_NEW_B           ;Clear need to send out newest value 
        BSF     OState_B           ;Start Task #1 & Lock Out Others
        GOTO    _0059

_0058   BTFSS   S_5_S_B            ;Serial In 5 secs of inactivity
        GOTO    _0059
        MOVLW   H'FF'              ;Tell of inactivity of Serial In 
        MOVWF   xmt_byte
        BCF     S_5_S_B            ;Clear need to send msg  
        BSF     OState_B           ;Start Task #1 & Lock Out Others
                
       ;Heart Beat - Time unit = 512 uS for Tasks #5 & #6
_0059   MOVF    TMR0,W             ;Step-up time units * 512  
        MOVWF   temp
        MOVF    Last_TMR0, W       ;Test to see if it overflowed 
        SUBWF   temp, W
        BTFSS   STATUS, C
        GOTO    Inc_Time
        MOVF    temp, W            ;unit error = < |+-512 uS| 
        MOVWF   Last_TMR0
        GOTO    Task_1             ;Serial Output

Inc_Time
        MOVF    temp, W            ;Save current TMR0 into Last_TMR0
        MOVWF   Last_TMR0

; Task #4 finds the next buffered byte to send out through Task #1.
; Task #4 also controls the order of which byte
; goes first over another less important byte of data.
; It can be said that Task #1 Blocks Task #4 from running.
; You can think of the Serial Output Line as a Shared Resource.
; The use of Semaphores here allow the Synchronization of data
;  and actions.
;
; Task#5 runs through lines 576-581, and is very short.

Task_5  ; - Monitor Level Reset Input Line - Always Running ! 
        BTFSC   Level_Reset
        GOTO    Task_6             ; Debounces sensors input lines
        MOVLW   LED_OFF_MODE       ;Lowest Level Indicator output
        MOVWF   LED_Mode

; Task #5 monitors the Level Reset Input Line and will
; reset the LED state variable if the line ever goes low.
; This task is always in the Ready State. This task is said
; to simply “pole the input line” when ever it can.
;
; Task #6 debounces the seven sensor input lines,
; running every 20 ms. Lines 582-611 represent Task #6.
; The variable “T_20_mS_CO” is incremented every 512 μs (Clock Tick)
; and is compared to the count needed to equal 20 ms. If it is time,
; the subroutine QCheck_T123 is called to see if Tasks
; #1-3 are in the Ready State.

Task_6  ;Task #6 - Debounce 8 bit Input Sensors - Runs every 20 mS 
        INCF    T_20_mS_CO, F      ;Inc Counter - Time Unit = 512 uS
        MOVLW   H'27'              ;Used to debounce the input 
        SUBWF   T_20_mS_CO, W
        BTFSS   STATUS, Z
        GOTO    _0065
        CLRF    T_20_mS_CO         ;Reset T_20_mS_CO to start over again
        CALL    QCheck_T123        ;Quick Check of Tasks #1, #2 and #3 
        MOVF    PORTB,W            ;Last copy of RB same as Current ? 
        SUBWF   Last_RB,W
        BTFSC   STATUS, Z        
        GOTO    _0062
        MOVF    PORTB, W           ;  Store Current RB - diff from Last
        MOVWF   Last_RB
        GOTO    _0063

_0062   MOVF    Last_RB, W         ;New Old RB <- same value over 20 mS 
        MOVWF   Old_RB
_0063   MOVF    Old_RB, F          ;See if RB is now 0 
        BTFSC   STATUS,Z           ;RB == 0 ? then keep timer running 
        GOTO    _0064
        CLRF    T_5_M_LO           ;Reset 5 Min Timer 
        CLRF    T_5_M_HI           ;  still not zero yet 
_0064   CALL    D_H_E_L            ;Determine the Highest Error Level
        BTFSS   RB_NEW_B           ;Check for Lost Data Error 
        BCF     RB_Overflow
        BTFSC   RB_NEW_B
        BSF     RB_Overflow
        BSF     RB_NEW_B           ;Every 20 mS send Old_RB out
                
        ;Heart Beat - Time unit = 131072 uS for Tasks #7, #8 & #9
_0065   MOVLW   H'F9'              ;RA TRIS - refresh RA=1001
        TRIS    5
        MOVLW   H 'FF'             ;RB TRIS - refresh 
        TRIS    6
        DECFSZ  Curnt_Cnt, F	   ;Step-up time units * 256 
        GOTO    Task_1             ;Serial Output
;
; If any of the Tasks #1-3 are ready, they are ran and we then
;  continue with Task #6.
; We compare the current value of the input Port_B to
; see if it stayed the same from the last reading 20 ms back.
; If the two readings are the same, then Port_B is
;  considered to be stable and the possibly new value is
;  placed in the variable “Old_RB” to be outputted by Task#1.
;

; The subroutine D_H_E_L is called to determine the new LED state.
; We then check if Task #1 was too busy to output the last sensor
; status byte, if so then that error is recorded.
;
; Do_D_H_E_L determines the LED’s next state based
;   on the 7 sensor input status.
; This subroutine checks each bit to see if it is active and then
;   checks if a change in the LED’s current state needs changing.

;****

Do_D_H_E_L      
; Determine the Highest Error Level & Start Task #7
; - Output Highest Level Indication on LED

        MOVLW   H'07'              ;Check top 7 bits 
        MOVWF   temp
        MOVF    Old_RB, W          ;Get copy of 7 debounced Sensor Input
        MOVWF   Last_RB
_0070   RLF     Last_RB, F         ;Put top bit into C bit
        BTFSC   STATUS, C          ;Check if C bit is set 
        GOTO    _0072
        DECFSZ  temp, F            ;Continue to check lesser bits
        GOTO    _0070
_0071   MOVF    PORTB, W           ;Restore current value of RB 
        MOVWF   Last_RB
        RETLW   H'00'

_0072  ; Implimentation off  missing instruccion SUBLF  L, RAM-Reg
        MOVF    LED_Mode, W        ;Get current Level Indicator 
        ANDLW   H'07'              ;Get only      "       "  
        MOVWF   Last_RB            ;Store into a tempary register 
        MOVF    temp, W            ;Check if already at this Level
        SUBWF   Last_RB, W
		                   ; end implementation
        BTFSC   STATUS, C
        GOTO    _0071
        MOVLW   H'88'              ;Start to build LED_Mode 
        IORWF   temp, W            ;Put new Level Indicator into reg 
        MOVWF   LED_Mode           ;Store new LED Mode 
        GOTO    _0071

; Task #7 outputs the Highest Severity Level Indicationon the LED.
; Task #7’s main code is lines 621-628.
;
; Do_LED starts at line 161, and continues to 276.
; This task is also broken into small time units of code.
; It is constantly checking to see if it is time to switch the
;  on/off condition of the LED.
;  The time units for Task #7 are regulated by the code in lines 613-619.
;  131072 μS = time unit for Tasks #7-9.
; Task #7 has many state jump tables so it is included in the
;  first 256 bytes of the first page.
;  Lines 168-175 explain the on and off sequences and offs that
;  represent levels of severity of the input status lines.
;  The variable “LED_Mode” has both Task #7’s current state number
;   and the sub-state-number for that state’s output sequence.
;
;  Task #8 is a 5 second lack of input from either of the two
;  Serial input timers. Tasks #2 and #3 will reset the time
;   counter for Task #8, when either receives a full byte.
;  If the time counter “T_5_S_CO” equals 5 secs, then the
;   LED’s state is bumped to the highest, and a special
;   byte is sent down the line to the next “Remote Alarm” unit.
;   The counter variable is reset, and count starts all over.
; We then check if Task #1 was too busy to output
;   the last special status byte, if so then that error is recorded.
;
; Task #9 measures 5 minutes of calm on the 7 sensor
;   lines and then resets the LED’s state.
; Lines 646-663 compose Task #9.

Task_9  ; - 5 Min. Lack of Severe Error from Sensors Reset Timer 
        BTFSS   T_5_M_B            ;5 Min Timer Active ? 
        GOTO    Task_A
        ; 16-bit increment
        INCF    T_5_M_LO, F        ;Inc LO Counter; Time Unit = 131072 uS
        BTFSC   STATUS,Z           ;  See if carry needs to be passed on ?
        INCF    T_5_M_HI, F        ;Inc HI Counter; Time Unit = 131072 uS
		                   ; end of 16-bit increment
        MOVLW   H'08'              ;#2288<  Check T_5_M_HI if time  
        SUBWF   T_5_M_HI, W
        BTFSS   STATUS, Z
        GOTO    Task_A
        MOVLW   H'F0'              ;#2288>  Check T_5_M_LO if time 
        SUBWF   T_5_M_LO, W
        BTFSS   STATUS, Z
        GOTO    Task_A
        CLRF    T_5_M_LO           ;Reset T_5_M_LO 
        CLRF    T_5_M_HI           ;Reset T_5_M_HI 
        MOVLW   LED_OFF_MODE       ;Lowest Level Indicator output 
        MOVWF   LED_Mode
Task_A   
        GOTO    Task_1             ; Loop Forever

; Task #9 needs 16 bits of counter power to record 5 minutes of time.
; The counter variables are reset after being triggered.


; Subrutie Do_Clear_Regs clears registers 7-1Fh.
; It leaves the FSR register zeroed out.
; This is very important for the PIC16C57 chip.

Do_Clear_Regs   ; Limpia Registros RAM  07h-1Fh
        MOVLW   H'1F'             ;Write the base (First regs to clear)
        MOVWF   FSR               ; into FSR 
Loop_C  CLRF    INDIR             ; Limpia el registro apuntado 
        DECF    FSR, F            ;   y apunta al siguiente registro
; Con el PIC16F54, en el reg FSR, solo podemos cambiar los bits 4 -> 0
; cuando estan en 1 1111 e incrementamos FSR este pasa a 0 0000 sin afectar
;      los bits 5,6 & 7.
        MOVLW   H'E7'             ;Vemos si ya alcanzamos el limite bajo
        SUBWF   FSR, W            ;  de RAM el cual es 07h pero como los
                                  ;  bits 5, 6, y 7 de
                                  ; FSR estan ajustados a 1 ... debemos
                                  ; subtraer  E7h
        BTFSC   STATUS, C         ;
        GOTO    Loop_C            ;  No: Regresa hasta que se alcanze
        CLRF    FSR               ;  Si:  Limpia el reg FSR
        RETLW   H'00'             ;       y regresa

; The main or starting code is started at line 485.
; From that line to line 515, all variables are initialized, and all tasks
;  are initialized at this time also.
;******         ;Code Starting point

Main
	; Configura Puertos y TMR0
        MOVLW   H'00'             ;What is High/Low for RA at INIT State 
        MOVWF   PORTA
        MOVLW   H'00'             ;What is High/Low for RB at INIT State 
        MOVWF   PORTB
        MOVLW   H'F9'             ;RA TRIS at INIT State  
        TRIS    5
        MOVLW   H'FF'             ;RB TRIS at INIT State 
        TRIS    6
        MOVLW   H'00'             ; Set TMR0/2 
	; bit5-Clock source = Internal  bit4-Edge =low-to-high transition
	; bit3-Prescaler on TMR0        bit210- Prescaler = 1:2
        OPTION
        CALL    Clear_Regs        ;Clear Registers 7-1F - Same Memory Page
        CLRF    TMR0              ;Start timers

;Initialize Tasks
                                  ;Task #1 waits for byte to output
                                  ;Asynchronous 9600 Baud Serial Output
;
                                  ;Task #2 waits for Serial IN Start Bit
                                  ;1st Asynchronous 4800 Baud Serial Input
;
                                  ;Task #3 waits for Serial IN Start Bit
                                  ;2nd Asynchronous 4800 Baud Serial Output
;
                                  ;Task #4 runs when Task 1 is Not
                                  ;  Finds next Buffered Byte to Send Out
                                  ;  through Task 1
;
                                  ;Task #5 is always running
                                  ;   Monitor Level Reset Input Line
;
                                  ;Task #6  - Runs every 20 mS
                                  ;   Debounce 8 bit Input Sensors
        MOVF    PORTB, W        ;Task #6 is Initialized here 
        MOVWF   Old_RB
        MOVF    Old_RB, W         ;Make all the same initial value 
        MOVWF   Last_RB
        BSF     RB_NEW_B          ;Tell Task #4: RB byte ready to output
;								
                                  ;Task #7  - Runs every 20 mS
                                  ;   Output Highest Level Indication on LED
        MOVLW   LED_OFF_MODE
        MOVWF   LED_Mode          ;Task #7 is Started 
;
                                  ;Task #8 - Runs every 20 mS
                                  ;   5 Second Serial Input Lack of
                                  ;   Activity Timer
        BSF     T_5_S_B           ;Task #8 is Started here  
;
                                  ;Task #9 - 5 Min. Lack of Severe Error
                                  ;   from Sensors Reset Timer
        BSF     T_5_M_B           ;Task #9 is Started here  

; The Main Loop is started at line 516 and ends at line 665.
; This is where the real action is done.
; Each task checks the time to see if the conditions are correct for it to run.
; The tasks that are not Blocked, and have a job to do now are in a Ready State.
; In the Main Loop, we check the current state of
; each task in order of Priority (1-9). If ready, we do a
; very simple Task Switch and place that task in the
; Executing State/Running State. Several time unit
; changes take place in the Main Loop.
; Handle Task & Timer activities - Main Loop

Task_1  ;Task #1 - Asynchronous 9600 Baud Serial Output (LOW=0)
        BTFSS   OState_B          ;if not outputing now then skip call 
        GOTO    Task_2
        CALL    Do_OState         ;Go Do Task #1

Task_2  ;Task #2 - Asynchronous 4800 Baud Serial Input (LOW=0)
        BTFSC   IState1_B         ;if already started then call
        GOTO    _0053
        BTFSC   Serial_IN_1       ;if Start bit ? then call
        GOTO    _0053
        GOTO    Task_3

_0053   CALL    Do_I1State        ;Go Do Task #2


Task_3  ;Task #3 - Asynchronous 4800 Baud Serial Input (LOW=0)
        BTFSC   IState2_B         ;if already started then call 
        GOTO    _0055
        BTFSC   Serial_IN_2       ;if Start bit ? then call 
        GOTO    _0055
        GOTO    Task_4
_0055   CALL    Do_I2State        ;Go Do Task #3

Task_4  ;Task #4 - Finds next Buffered Byte to Send Out through Task 1
        BTFSC   OState_B          ;if outputing now then skip call
        GOTO    _0059
        BTFSS   RCV_Got_One_B     ;Got a NEW Received byte to send
        GOTO    _0057
        MOVF    RCV_Storage, W    ;Send just received byte 
        MOVWF   xmt_byte
        BCF     RCV_Got_One_B     ;Clear need to send old byte 
        BSF     OState_B          ;Start Task #1 & Lock Out Others 
        GOTO    _0059

_0057   BTFSS   RB_NEW_B          ;Indicates a change in RB input 
        GOTO    _0058
        MOVF    Old_RB, W         ;Send New RB value  
        MOVWF   xmt_byte
        BCF     RB_NEW_B          ;Clear need to send out newest value 
        BSF     OState_B          ;Start Task #1 & Lock Out Others
        GOTO    _0059

_0058   BTFSS   S_5_S_B           ;Serial In 5 secs of inactivity
        GOTO    _0059
        MOVLW   H'FF'             ;Tell of inactivity of Serial In 
        MOVWF   xmt_byte
        BCF     S_5_S_B           ;Clear need to send msg  
        BSF     OState_B          ;Start Task #1 & Lock Out Others
                
        ;Heart Beat - Time unit = 512 uS for Tasks #5 & #6
_0059   MOVF    TMR0,W            ;Step-up time units * 512  
        MOVWF   temp
        MOVF    Last_TMR0, W      ;Test to see if it overflowed 
        SUBWF   temp, W
        BTFSS   STATUS, C
        GOTO    Inc_Time
        MOVF    temp, W           ;unit error = < |+-512 uS| 
        MOVWF   Last_TMR0
        GOTO    Task_1
            ;Serial Output
Inc_Time   
        MOVF    temp, W           ;Save current TMR0 into Last_TMR0
        MOVWF   Last_TMR0

Task_5  ;Task #5 - Monitor Level Reset Input Line - Always Running ! 
        BTFSC   Level_Reset
        GOTO    Task_6
        MOVLW   LED_OFF_MODE      ;Lowest Level Indicator output
        MOVWF   LED_Mode

Task_6  ;Task #6 - Debounce 8 bit Input Sensors - Runs every 20 mS 
        INCF    T_20_mS_CO, F     ;Inc Counter - Time Unit = 512 uS
        MOVLW   H'27'             ;Used to debounce the input 
        SUBWF   T_20_mS_CO, W
        BTFSS   STATUS, Z
        GOTO    _0065
        CLRF    T_20_mS_CO        ;Reset T_20_mS_CO to start over again
        CALL    QCheck_T123       ;Quick Check of Tasks #1, #2 and #3 
        MOVF    PORTB,W           ;Last copy of RB same as Current ? 
        SUBWF   Last_RB,W
        BTFSC   STATUS, Z        
        GOTO    _0062
        MOVF    PORTB, W          ;  Store Current RB - diff from Last
        MOVWF   Last_RB
        GOTO    _0063

_0062   MOVF    Last_RB, W        ;New Old RB <- same value over 20 mS 
        MOVWF   Old_RB
_0063   MOVF    Old_RB, F         ;See if RB is now 0 
        BTFSC   STATUS,Z          ;RB == 0 ? then keep timer running 
        GOTO    _0064
        CLRF    T_5_M_LO          ;Reset 5 Min Timer 
        CLRF    T_5_M_HI          ;  still not zero yet 
_0064   CALL    D_H_E_L           ;Determine the Highest Error Level
        BTFSS   RB_NEW_B          ;Check for Lost Data Error 
        BCF     RB_Overflow
        BTFSC   RB_NEW_B
        BSF     RB_Overflow
        BSF     RB_NEW_B          ;Every 20 mS send Old_RB out
                
        ;Heart Beat - Time unit = 131072 uS for Tasks #7, #8 & #9
_0065   MOVLW   H'F9'             ;RA TRIS - refresh RA=1001
        TRIS    5
        MOVLW   H'FF'             ;RB TRIS - refresh 
        TRIS    6
        DECFSZ  Curnt_Cnt, F	  ;Step-up time units * 256 
        GOTO    Task_1            ;Serial Output

Task_7          ;Task 7 - Output Highest Level Indication on LED
        BTFSS   LED_B             ;Is LED active ? 
        GOTO    Task_8
        CALL    QCheck_T123       ;Quick Check of Tasks #1, #2 and #3 
        CALL    Do_LED            ;Handle LED timing
                                  
Task_8  ;Task #8 - 5 Second Serial Input Lack of Activity Timer
        BTFSS   T_5_S_B           ;5 Sec Timer Active ?  
        GOTO    Task_9
        INCF    T_5_S_CO, F       ;Inc Counter - Time Unit = 131072 uS 
        MOVLW   H'26'             ;Check T_5_S_CO if time  
        SUBWF   T_5_S_CO, W
        BTFSS   STATUS, Z
        GOTO    Task_9
        CLRF    T_5_S_CO          ;Reset T_5_S_CO 
        MOVLW   LED_ON_MODE       ;Highest Level Indicator output 
        MOVWF   LED_Mode
        BTFSS   S_5_S_B           ;Check if Lost Data Error 
        BCF     S_5_S_Overflow
        BTFSC   S_5_S_B
        BSF     S_5_S_Overflow
        BSF     S_5_S_B           ;Send notice of 5 seconds of inaction  

Task_9  ;Task #9 - 5 Min. Lack of Severe Error from Sensors Reset Timer 
        BTFSS   T_5_M_B           ;5 Min Timer Active ? 
        GOTO    Task_A

        ; 16-bit increment
        INCF    T_5_M_LO, F       ;Inc LO Counter; Time Unit = 131072 uS 
        BTFSC   STATUS,Z          ;  See if carry needs to be passed on ?
        INCF    T_5_M_HI, F       ;Inc HI Counter; Time Unit = 131072 uS
	; end of 16-bit increment
        
        MOVLW   H'08'             ;#2288 < Check T_5_M_HI if time  
        SUBWF   T_5_M_HI, W
        BTFSS   STATUS, Z
        GOTO    Task_A
        MOVLW   H'F0'             ;#2288 > Check T_5_M_LO if time 
        SUBWF   T_5_M_LO, W
        BTFSS   STATUS, Z
        GOTO    Task_A
        CLRF    T_5_M_LO          ;Reset T_5_M_LO 
        CLRF    T_5_M_HI          ;Reset T_5_M_HI 
        MOVLW   LED_OFF_MODE      ;Lowest Level Indicator output 
        MOVWF   LED_Mode

Task_A   
        GOTO    Task_1          ; Loop Forever
Espero que les sea útil.
 
Última edición:
Hola amigos soy nuevo pero necesito ayuda, lo que tengo que hacer es un encoder con un PIC18F4550, mi señal esta siendo analisada en mi puerto A0, con el sensor H21a1 y estoy utilizando un KEYPAD, si coloco 123 el motor gira a la derecha y mi a=a+1; si coloco 456 mi motor se detiene; si coloco 789 el motor giro a la izquierda y mi a=a-1.
en mi programación se queda anclado en el ciclo While y no logro sacarlo de ahi porque solo hace mi adquisición de datos de mi KEYPAD 1 sola vez y se queda en el contador.

esta es mi programación, porfavor que devo agregar
 

Adjuntos

  • encoder.txt
    3.1 KB · Visitas: 4
  • ENCODER1.pdf
    195.9 KB · Visitas: 4
Para hacer varias cosas a la vez, lo primero de todo es borrar de tu mente y para siempre los delays. (la plaga de la programación)

Lo segundo es trabar ambos programas o hacer primero uno y luego otro consecutivamente.
Yo personalmente voto por la primera opción si se puede.
 
Para eso debes emplear interrupciones y banderas, el timer es recomendable para escanear el teclado, el procesamiento lo haces por condicional o durante la interrupción del teclado, el encoder también debes controlarlo por interrupción o el timer en modo capture.
 
hola ERICK ATEM, te comento que tu programa esta muy mal estructurado.
Usando solo la rutina principal no podras tener un buen rendimiento en tu programa, las interrupciones son lo que le dan poder a un uC.
Este un ejemplo de como usarlas en tu programa.
Código:
/*****************************************************************************/
#include <18F4550.h>
#device PASS_STRINGS=IN_RAM
#FUSES NOWDT,NOPUT,NOPROTECT,NOBROWNOUT,NOLVP,NOCPD,NOWRT,NODEBUG
#use delay(xtal=4000000)
/*****************************************************************************/
#define LCD_ENABLE_PIN  PIN_B3
#define LCD_RS_PIN      PIN_B1
#define LCD_RW_PIN      PIN_B2
#define LCD_DATA4       PIN_B4
#define LCD_DATA5       PIN_B5
#define LCD_DATA6       PIN_B6
#define LCD_DATA7       PIN_B7
#include <lcd.c>
/*****************************************************************************/
#include "kbd_4x4.c"
/*****************************************************************************/
#INCLUDE <ctype.h>
#include <stdlib.h>
#include <string.h>
/*****************************************************************************/
signed int16 a=0;
char bandera_teclado=0;
char bandera_lcd=0;
/*****************************************************************************/
#INT_TIMER1
void interrupcion_timer1()
{
   static unsigned int8 contador;
   set_timer1(64536);
   bandera_teclado=1;
   if(++contador==50)
   {
      contador=0;
      bandera_lcd=1;
   }
}
/*****************************************************************************/
#INT_EXT
void interrupcion_externa0()
{
   if(input_state(pin_a0))
   {
      a++;
   }
   else if(input_state(pin_a1))
   {
      a--;
   }
}
/*****************************************************************************/
void leer_teclado()
{
   char c;
   static char codigo[4];
   static unsigned int8 n;
   c=kbd_getc();
   if(isdigit(c))
   {
      if(n==3)
      {
         n=0;
         lcd_gotoxy(1,2);
         lcd_putc("   ");
      }
      codigo[n++]=c;
      lcd_gotoxy(n,2);
      lcd_putc(c);
   }
   else if(c=='#')
   {
      codigo[n]='\0';
      n=0;
      lcd_gotoxy(1,2);
      lcd_putc("   ");
      lcd_gotoxy(12,1);
      if(!strcmp(codigo,"123"))
      {
         lcd_putc("ON  H");
         output_high(pin_a0);
         output_low(pin_a1);
      }
      else if(!strcmp(codigo,"456"))
      {
         lcd_putc("OFF");
         output_low(pin_a0);
         output_low(pin_a1);
      }
      else if(!strcmp(codigo,"789"))
      {
         lcd_putc("ON  A");
         output_low(pin_a0);
         output_high(pin_a1);
      }
   }
}
/*****************************************************************************/
void main()
{
   output_low(pin_a0);
   output_low(pin_a1);
   kbd_init();
   lcd_init();
   lcd_putc("INTRODUCIR|OFF H\n");
   lcd_putc("   |N=          ");
   lcd_gotoxy(1,2);
   set_timer1(64536);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(INT_EXT_H2L);
   enable_interrupts(GLOBAL);
   while(true)
   {
      if(bandera_teclado)
      {
         leer_teclado();
         bandera_teclado=0;
      }
      if(bandera_lcd)
      {
         lcd_gotoxy(7,2);
         printf(lcd_putc,"%06Ld",a);
         bandera_lcd=0;
      }
   }
}
Sin título.jpg
 

Adjuntos

  • teclado.rar
    216.1 KB · Visitas: 8
Atrás
Arriba