Programación en ensamblador: El TMR0 como contador

Hola a todos! Estoy empezando a programar en el ensamblador del Pic 16F876A y no se hacer el siguiente problema:

-Implemente un programa que configure el timer0 del pic 16F876A
para que cuente los pulsos que genera un pulsador conectado al
puerto A (RA0), y los presente en el puerto B.


Lo del Timer0 no lo pillo muy bien, lo he configurado como contador, y ami entender que he visto en el manual sección 5.0 el valor de TMR0 se actualiza cada vez que hay un cambio de estado en RA4, pero tampoco estoy muy seguro. He hecho el siguiente programa en MPLAB pero no hace nada:

LIST P=16F876A
INCLUDE "P16F876A.INC"
__config _CP_OFF&_CPD_OFF&_LVP_OFF&_WDT_OFF&_XT_OSC

count EQU 0x20

ORG 0

goto INICIO

ORG 5


INICIO
bsf STATUS, RP0 ;Vamos a Banco 1
movlw 0x06
movwf ADCON1
clrf TRISA ;Puerto A como entrada
movlw b'11111111'
movwf TRISB ;Puerto B como salida

movlw b'11111000' ;Configuramos el timer como contador de Eventos
movwf OPTION_REG

bcf STATUS, RP0 ;Volvemos a Banco 0

Programa

movfw TMR0
movwf PORTB
goto Programa

END

Gracias por la atención! Saludos!
 
Saludos y bienvenido al foro... veamos

movlw b'11111111'
movwf TRISB ;Puerto B como salida

Con esa instrucción el puero B se hace entrada

Implemente un programa que configure el timer0 del pic 16F876A
para que cuente los pulsos que genera un pulsador conectado al
puerto A (RA0), y los presente en el puerto B.

La entrada de reloj del TMR0 es el pin RA4, comienza cambiando de posición tu pulsador
 
Si me he dado cuenta despues a sido un despiste jaja! Aqui dejo mi codigo ya retocado para pasarle a RA0 lo de RA4 pero cuando le hago el estimulo TMR0 solo se me activa cuando hago el estimulo en la primera linea de 'Programa'( la del swap) y una de cada dos, es decir, si me actualiza en ciclo en el siguiente no, pero al siguiente si, nose si me explico... Y nose porque hace eso yo el código creo que esta bien pero tengo ese problema. Muchas gracias por tu ayuda!
----- Codigo:


LIST P=16F876A
INCLUDE "P16F876A.INC"
__config _CP_OFF&_CPD_OFF&_LVP_OFF&_WDT_OFF&_XT_OSC

count EQU 0x20

ORG 0

goto INICIO

ORG 5


INICIO
bsf STATUS, RP0 ;Vamos a Banco 1
movlw 0x06
movwf ADCON1
movlw b'00001111'
movwf TRISA ;Puerto A como entrada solo 4 unos para que se pueda luego intercambiar el valor de RA4 y RA0
clrf TRISB ;Puerto B como salida

movlw b'11111001' ;Configuramos el timer como contador de Eventos
movwf OPTION_REG

bcf STATUS, RP0 ;Volvemos a Banco 0

Programa
swapf PORTA, 1 ;Así envío el valor de RA0 A RA4 (que es el que usa el tmr0)

movfw TMR0
movwf PORTB
goto Programa

END
 
swapf PORTA, 1 ;Así envío el valor de RA0 A RA4

Esta parte no es así, el TMR0 tiene conectada su entrada de reloj directamente al pin RA4, no es posible "mandarle" un pulso por software, no se si me explico... intenta conectando directamente el botón al pin RA4 (previamente configurado como entrada). Otra cosa, implementa un eliminador de rebotes en tu interruptor, con un 555 en modo monoestable es suficiente. El interruptor dispararía el 555 y la salida de este se conectaría al pin RA4 del PIC
 
Hola:

Ejemplos del 16F886, te puede orientar.

ASM
Código:
;El Timer 0 TMR0.
;
;Se trata de comprobar el funcionamiento básico del Timer 0. Cuando se detecta un flanco
;decendente en RA0 (conectada con un pulsador), se activa la salida RB0 durante un tiempo
;y luego se desconecta. El TMR0 realiza una temporización de 50mS que se repite tantas veces
;como se indique en la variable "Temp". Así pues la temporización total será de 50mS*Temp.
;
;Suponiendo una frecuencia de trabajo de 4MHz, 4Tosc=1uS. Trabajando con un prescaler de 256,
;al TMR0 hay que cargarlo con 195 para temporizar 50mS (Temporización=1uS*195*256)

    
        List    p=16F886        ;Tipo de procesador
        include    "P16F886.INC"    ;Definiciones de registros internos

;Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados
;adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades

        __config    _CONFIG1, _LVP_OFF&_PWRTE_ON&_WDT_OFF&_EC_OSC&_FCMEN_OFF&_BOR_OFF    ;Palabra 1 de configuración
        __config    _CONFIG2, _WRT_OFF&_BOR40V                                    ;Palabra 2 de configuración

Valor            equ    .20                ;Constante para temporizar 1 seg (50mS*20)

Temp            equ    0x020            ;Variable para la temporización
              
                org    0x00            ;Vector de RESET
                goto    Inicio
                org    0x05

;*********************************************************************************************
;Delay: El Timer 0 realiza un retardo de 50mS que se repite tantas veces como se indica en la 
;constante valor

Delay            movlw    Valor
                movwf    Temp        ;Nº de veces a temporizar 50 mS 
Delay_1            movlw    ~.195  
                movwf    TMR0        ;Inicia el Timer 0 con 195 (195*256=49.9mS)
                bcf        INTCON,T0IF    ;Repone flag del TMR0
Delay_2            btfss    INTCON,T0IF    ;Fin de los 50mS ??
                goto    Delay_2        ;No, el TMR0 no ha terminado
                decfsz     Temp,F        ;Decrementa el contador. Fin de temporización ??
                   goto     Delay_1        ;No, el TMR0 temporiza otros 50 mS
                return                ;Si, final de la temporización

;Programa principal
Inicio            clrf     PORTB        ;Borra los latch de salida
                bsf        STATUS,RP0
                bsf        STATUS,RP1    ;Selecciona banco 3
                clrf    ANSEL        ;Puerta A digital
                clrf    ANSELH        ;Puerta B digital
                bcf        STATUS,RP1    ;Selecciona banco 1
                movlw    b'11111110'
                movwf    TRISB        ;RB0 se configura como salida
                movlw    b'00111111'        
                movwf    TRISA        ;RA5:RA0 se configuran como entrada
                movlw    b'00000111'    
                movwf    OPTION_REG    ;TMR0 con reloj interno y preescaler de 256        
                bcf        STATUS,RP0    ;Selecciona banco 0                                                                                     

;Este es el cuerpo principal del programa. Espera a que en RA0 se detecte un flanco descendente

Loop            btfsc     PORTA,0     ;RA0=0 ??
                   goto     Loop        ;No, esperar
                bsf        PORTB,0        ;Si activar RB0
                call    Delay        ;Temporizar
                bcf        PORTB,0        ;Desactivar RB0
                goto    Loop        ;Repetir el proceso

                end                    ;Fin del programa fuente

C
Código:
/*El Timer 0 TMR0.

Se trata de comprobar el funcionamiento básico del Timer 0. Cuando se detecta un flanco
decendente en RA0 (conectada con un pulsador), se activa la salida RB0 durante un tiempo
y luego se desconecta. El TMR0 realiza una temporización de 50mS que se repite tantas veces
como se indique en la variable "Temp". Así pues la temporización total será de 50mS*Temp.

Suponiendo una frecuencia de trabajo de 4MHz, 4Tosc=1uS. Trabajando con un prescaler de 256,
al TMR0 hay que cargarlo con 195 para temporizar 50mS (Temporización=1uS*195*256) */

#include <16f886.h>

/* Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados
adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades */

#fuses     NOLVP,PUT,NOWDT,EC_IO,NOFCMEN,NOBROWNOUT    //Palabra 1 de configuración
#fuses    NOWRT,BORV40                                //Palabra 2 de configuración

/* Con estas directivas las funciones "input" y "output_bit" no reprograman
 el pin de la puerta cada vez que son utilizadas. Si no se indica el
modo fast_io se asume por defecto standard_io el cual reprograma el pin
siempre antes de ser utilizadas estas funciones. */

#use fast_io (A)
#use fast_io (B)

int Valor=20;                    //Constante para temporizar 1 seg (50mS*20)

/**********************************************************************************************
Delay: El Timer 0 realiza un retardo de 50mS que se repite tantas veces como se indica en la 
constante valor */

void delay()
{    
    int Temp;
    for(Temp=Valor;Temp>0;Temp--)
    {
    set_timer0(~195);                    // Cargar TMR0 con 195 (195*256=49.9mS)
    while(get_timer0()!=0);
    }
}

main()
{  
    setup_adc_ports(NO_ANALOGS);        //Puertas A y B digitales
    output_b(0x00);                        //Borra las salidas
      set_tris_a(0x3F);                    //Puertas A entrada
      set_tris_b(0xFE);                    //RB0 se configura como salida
             
    setup_counters(RTCC_INTERNAL,RTCC_DIV_256);    //TMR0 con reloj interno y preescaler de 256
 
//Este es el cuerpo principal del programa. Espera a que en RA0 se detecte un flanco descendente
      while(1)
         {
        while(input_state(PIN_A0)==1);    //Esperar que RA0=0
        output_high(PIN_B0);            //Activar RB0
        delay();                        //Temporizar
        output_low(PIN_B0);                //Desactivar RB0
        }
}
 
Ya lo de los rebotes lo tengo en cuenta luego a la hora de probarlo en la placa, pero, en realidad con el swapf si que le pasa el pulso de RA0 a RA4 para que actualice el TMR0, lo que pasa es que al simularlo en el MPLAB me pasa lo que te he comentado anteriormente. ¿Eso es problema de mi programa o del MPLAB? Muchas gracias por la ayuda! Saludos!
 
Atrás
Arriba