Autor Tema: Preguntas sobre assembler  (Leído 14839 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Fedextrem

  • PIC10
  • *
  • Mensajes: 25
Preguntas sobre assembler
« en: 02 de Febrero de 2015, 09:42:28 »
Buenas gente, tengo una duda existencial. Como hago en assembler para preguntar si un dato que ingresa por medio de llaves es entre un valor u otro? Por ejemplo entre 0 y 9 o A(10) y F(15)?

Porque si es entre los primeros tiene que hacer algo diferente a que si es entre los segundos parametros.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Preguntas sobre assembler
« Respuesta #1 en: 02 de Febrero de 2015, 11:52:17 »
De la misma forma que haces para saber si un dato tiene X valor

Restando. Algunos micros tienen set de instrucciones mas complejos que permiten una clara diferenciacion de Mas grande que, Menor que, etc.

Pero si es de lo mas basico, primero restas W - literal = W (SUBLW)y te fijas en las banderas. asi ya tenes si es un valor menor, igual o lo que sea, y luego comprobas por el otro extremo, restando 15 y preguntando si es cero o mayor.

Desconectado syndu

  • PIC10
  • *
  • Mensajes: 12
Re: Preguntas sobre assembler
« Respuesta #2 en: 04 de Febrero de 2015, 01:53:49 »
Una pregunta, el caso es que yo tengo declaro estas variables
cblock  20H
    pwm_r, pwm_v, pwm_a, W2, Status2, Var_I, Var_C
    endc
la cosa es que los registros Var_I, Var_C, no los reconoce :/ al incrementar Var_I o Var_C no lo hace... me di cuenta cuando corri paso por paso mi programa en proteus.... dejo el codigo por aqui, espero me ayuden!

list p=16f887
    #include   <p16f887.inc>
    __CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
   __CONFIG    _CONFIG2, _WRT_OFF & _BOR21V


;------------------------------------------------------------------
;configuro inicio del programa con el vector reset/interrupcion
;*****************************************************************
        org 00H

           goto inicio

     org 04h
        goto inte
;-----------------------------------------------------------------------
; Inicia Programa
; CONFIGURO I/O
;**********************************************************************

inicio
    ;-------------------------------------------------------------------------
; Configuro Variables
;*************************************************************************
    CBLOCK  20H
    pwm_r, pwm_v, pwm_a, W2, Status2, Var_I, Var_C
    endc

     BANKSEL ANSEL
    clrf    ANSELH
    BANKSEL TRISD
    clrf    TRISB
    BANKSEL PORTA
    clrf    PORTB
;---------------------------------------------------------------------
; configuro Interrupcion cada 40us
;*********************************************************************
   
    BANKSEL OPTION_REG
    Movlw   b'00000100'
    Movwf   OPTION_REG
    BANKSEL INTCON
    Movlw   b'10100000'
    Movwf   INTCON
;-------------------------------------------------------------------------
; Defino pin de puertos
;*************************************************************************
    #Define Led_r PORTB,0
    #Define Led_v PORTB,1
    #Define Led_a PORTB,2

;--------------------------------------------------------------------------
; Pregunto la variable "Var_C" para ver en que Var_C me encuentro
;**************************************************************************

Carga_duty
    movlw   0h
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso
    goto    rojo
Reviso
    movlw   .1
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso1
    goto    Azul
Reviso1
    movlw   .2
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso2
    goto    verde
Reviso2
    movlw   .3
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso3
    goto    amarillo
Reviso3
    movlw   .4
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso4
    goto    agua
Reviso4
    movlw   .5
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso5
    goto    magenta
Reviso5
    movlw   .6
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso6
    goto    orange
Reviso6
    movlw   .7
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso7
    goto    bonito
Reviso7
    movlw   .8
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso8
    goto    morado
Reviso8
    movlw   .9
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso9
    goto    marron
Reviso9
    movlw   .10
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso10
    goto    violeta
Reviso10
    movlw   .11
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso11
    goto    oscuro
Reviso11
    movlw   .12
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso12
    goto    verde1
Reviso12
    movlw   .13
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso13
    goto    rosado
Reviso13
    movlw   .14
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Reviso14
    goto    verde2
Reviso14
    movlw   .15
    subwf   Var_C,0
    btfss   STATUS,Z
    goto    Carga_duty
    goto    blanco
;-------------------------------------------------------------------------
; Cargo las variables con los distintos dutys para generar
;los colores correspondientes
;*************************************************************************
rojo
    movlw   .255
    movwf   pwm_r
    movlw   .0
    movwf   pwm_v
    movlw   .0
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm

verde
    movlw   .0
    movwf   pwm_r
    movlw   .255
    movwf   pwm_v
    movlw   .0
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm

Azul
    movlw   .0
    movwf   pwm_r
    movlw   .0
    movwf   pwm_v
    movlw   .255
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm

amarillo
    movlw   .255
    movwf   pwm_r
    movlw   .255
    movwf   pwm_v
    movlw   .0
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm
agua
    movlw   .0
    movwf   pwm_r
    movlw   .255
    movwf   pwm_v
    movlw   .255
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm

magenta
    movlw   .255
    movwf   pwm_r
    movlw   .0
    movwf   pwm_v
    movlw   .255
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm

orange
    movlw   .255
    movwf   pwm_r
    movlw   .140
    movwf   pwm_v
    movlw   .0
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm

bonito
    movlw   .0
    movwf   pwm_r
    movlw   .250
    movwf   pwm_v
    movlw   .154
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm

morado
    movlw   .147
    movwf   pwm_r
    movlw   .112
    movwf   pwm_v
    movlw   .219
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm

marron
    movlw   .139
    movwf   pwm_r
    movlw   .69
    movwf   pwm_v
    movlw   .19
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm

violeta
    movlw   .238
    movwf   pwm_r
    movlw   .130
    movwf   pwm_v
    movlw   .238
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm

oscuro
    movlw   .25
    movwf   pwm_r
    movlw   .25
    movwf   pwm_v
    movlw   .112
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm

verde1
    movlw   .46
    movwf   pwm_r
    movlw   .139
    movwf   pwm_v
    movlw   .87
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm

rosado
    movlw   .220
    movwf   pwm_r
    movlw   .20
    movwf   pwm_v
    movlw   .60
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm

verde2
    movlw   .144
    movwf   pwm_r
    movlw   .238
    movwf   pwm_v
    movlw   .144
    movwf   pwm_a
    incf    Var_C,0
    goto    Pregunto_Pwm

blanco
    movlw   .255
    movwf   pwm_r
    movlw   .255
    movwf   pwm_v
    movlw   .255
    movwf   pwm_a
    clrf    Var_C
    goto    Pregunto_Pwm

;-------------------------------------------------------------------------
;Pregunto si ya cumplieron los ciclos de trabajo
;**************************************************************************
Pregunto_duty
    movwf    W2
    movf     STATUS,w
    movwf    Status2
;---------------------------------------------------------------------
; Pregunto si Var_I llego a 255
;**********************************************************************
    movlw   .255
    subwf   Var_I,0
    btfss   STATUS,Z
    goto    otro
    clrf    Var_I
;-------------------------------------------------------------------
; devuelvo valor a w y status, tambien pongo en bajo Toif
;****************************************************************
    movf    Status2,w
    movwf   STATUS
    movf    W2,W
    BANKSEL INTCON
    bcf     INTCON,T0IF
    bsf     INTCON,GIE
;---------------------------------------------------------------------
; configuro Interrupcion cada 40us
;*********************************************************************
    BANKSEL OPTION_REG
    Movlw   b'00000100'
    Movwf   OPTION_REG
    goto    Carga_duty

otro
    BANKSEL OPTION_REG
    Movlw   b'00000100'
    Movwf   OPTION_REG
    movf    Status2,W
    movwf   STATUS
    movf    W2,W
    bcf     INTCON,T0IF
    BANKSEL TMR0
    Movlw   .255
    Movwf   TMR0
    retfie

Pregunto_Pwm
    BANKSEL TMR0
    Movlw   .255
    Movwf   TMR0
Pregunto_Pwm1
    movf    pwm_r,0
    subwf   Var_I,0
    btfss   STATUS,C
    goto    on_r
    goto    off_r
off_r
    bsf     Led_r
    goto    Pregunto_v
on_r
    bcf     Led_r
    goto    Pregunto_v

Pregunto_v
    movf    pwm_v,0
    subwf   Var_I,0
    btfss   STATUS,C
    goto    on_v
    goto    off_v
off_v
    bsf     Led_v
    goto    Pregunto_a
on_v
    bcf     Led_v
    goto    Pregunto_a

Pregunto_a
    movf    pwm_a,0
    subwf   Var_I,0
    btfss   STATUS,C
    goto    on_a
    goto    off_a
off_a
    bsf     Led_a
    goto    Pregunto_Pwm1
on_a
    bcf     Led_a
    goto    Pregunto_Pwm1
;--------------------------------------------------------------------
;rutina de interrupcion
;********************************************************************

inte
;---------------------------------------------------------------------
;guardamos registros importantes
;*********************************************************************
    incf    Var_I,f
    goto    Pregunto_duty
    end

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Preguntas sobre assembler
« Respuesta #3 en: 04 de Febrero de 2015, 03:24:51 »
Por lo que decis puede ocurrir por 2 cosas:

1- Por los bancos

Citar
   BANKSEL INTCON
    Movlw   b'10100000'
    Movwf   INTCON

No se bien que banco tomara ya que INTCON es accesible de todos los bancos, por ende buscate otro registro que solo pertenesca al banco 0, o fijate en el proteus is cambia el banco a donde corresponde ( banco 0 )

2- Por malas instrucciones:

incf    Var_C,0  es lo mismo que decir  incf Var_C,W

Por lo tanto incrementa y guarda en W, no se salva el valor, deberias poner incf Var_C,F  o incf Var_C,1, de esa forma el resultado se almacena en el registro



Por otra parte todos esos reviso podrias simplificarlo con una tabla

         
Carga_Duty:
        MOVF    Var_C,W
   ADDWF PCL, F
   GOTO  rojo   
   GOTO  Azul
   GOTO  verde
   GOTO  amarillo
        ........ etc

Y seguro que se puede hacer algo parecido con los colores.

Desconectado Fedextrem

  • PIC10
  • *
  • Mensajes: 25
Re: Preguntas sobre assembler
« Respuesta #4 en: 04 de Febrero de 2015, 14:15:59 »
Esta bien hecha esta resta y suma?

BTFSS PIR1,TXIF
   RETURN;Aca me fijo si es de 0 a 9 asi le sumo 0x30 ('0') o si es una A a F asi le sumo una 'A' a DATO_A_ENVIAR
    MOVF    DATO_A_ENVIAR
    SUBLW   .10
    BTFSC   STATUS,Z ; pregunto por si la resta da 0
    GOTO    SUMO30
    GOTO    SUMOA
    MOVWF TXREG      ;Cargo el valor asi se envia
   RETURN

SUMO30       ; el dato que llega es 0 entonces sumo 0x30 a dato a enviar
    ADDLW   0x30
    MOVWF   DATO_A_ENVIAR
    RETURN

SUMOA      ; el dato no es cero por lo tanto sumo A
    ADDLW   0x0A
    MOVWF   DATO_A_ENVIAR
    RETURN
 END

Es cortito pero no estoy seguro de si la estructura esta bien hecha porque casi nunca trabajo con programas asi.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Preguntas sobre assembler
« Respuesta #5 en: 04 de Febrero de 2015, 17:48:12 »
ahi solo estas viendo si el numero es igual a 10
Si quisieras saber si el resultado es negativo deberias de usar el bit Carry.

SUBLW
k - (W) -> (W)

Si k > W .... C = 1 , Z = 0
Si k = W .... C = 1 , Z = 1
Si k < W .... C = 0

es decir:
k >= W ... C = 1
k < W   ... C = 0

Código: [Seleccionar]
   BTFSS PIR1,TXIF
    RETURN;Aca me fijo si es de 0 a 9 asi le sumo 0x30 ('0') o si es una A a F asi le sumo una 'A' a DATO_A_ENVIAR
    MOVF    DATO_A_ENVIAR
    SUBLW   .9
    BTFSC   STATUS,C ; Si esta en 0 es negativo, es decir 9 - DATO_A_ENVIAR = negativo o 9 < DATO_A_ENVIAR  , apartir de 10 se pondria C = 1
    GOTO    SUMO30

SUMOA      ; el dato no es cero por lo tanto sumo A
    MOVF    DATO_A_ENVIAR
    ADDLW   .55 ; 'A' - 10
    MOVWF   DATO_A_ENVIAR
    MOVWF TXREG      ;Cargo el valor asi se envia
    RETURN

SUMO30       ; el dato que llega es 0 entonces sumo 0x30 a dato a enviar
    MOVF    DATO_A_ENVIAR
    ADDLW   0x30
    MOVWF   DATO_A_ENVIAR
    MOVWF TXREG      ;Cargo el valor asi se envia
    RETURN

 END

Arregle el codigo por que habia varios errores (aunque asumi unas cosas, de todas formas te digo los errores asi lo acomodas a lo que queres):

1- Estas intruccion jamas se iban a ejecutar, incluso cambiando los GOTO anteriores por CALL iba a hacer que entrara a ambas subrutinas si daba el caso que entra primero en SUMO30.

 MOVWF TXREG      ;Cargo el valor asi se envia
 RETURN

2- Aca tenes un problema:

SUMO30       ; el dato que llega es 0 entonces sumo 0x30 a dato a enviar
    ADDLW   0x30
    MOVWF   DATO_A_ENVIAR

Tu problema radica que en W no esta "DATO_A_ENVIAR" sino que te quedo el resto de la resta que hiciste con anterioridad, asi que ese dato no es valido. Ademas no se por que volverlo a cargar en "DATO_A_ENVIAR" .... cuando ya lo sumaste... asi que imagino que esa instruccion debe estar de mas, por las dudas no la quite. ya que no se que funcion cumple.
« Última modificación: 04 de Febrero de 2015, 19:46:56 por KILLERJC »

Desconectado Fedextrem

  • PIC10
  • *
  • Mensajes: 25
Re: Preguntas sobre assembler
« Respuesta #6 en: 04 de Febrero de 2015, 19:19:29 »
Okey entiendo donde esta mal, la cuestión es que tengo que mandar el dato a los displays y también al tx por eso lo puse dos veces al MOV, esta mal o al código que me corregiste le cambio eso y ya esta?


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Preguntas sobre assembler
« Respuesta #7 en: 04 de Febrero de 2015, 19:43:41 »
Okey entiendo donde esta mal, la cuestión es que tengo que mandar el dato a los displays y también al tx por eso lo puse dos veces al MOV, esta mal o al código que me corregiste le cambio eso y ya esta?

Y el codigo si estaba mal...
Tu codigo jamas escribiria el TXREG, solo verifica si es igual a 10, luego termina guardando en DATO_A_ENVIAR el valor de la resta + '0' o 'A'

El codigo le cambie:

- el valor a restar de 10 a 9,
- la pregunta por el bit carry.
- Quite un return
- cambie de lugares las subrutinas asi habia un GOTO menos.
- puse el MOVWF TXREG en cada subrutina para que se envie el valor, antes no se ejecutaba
- le agregue un MOVF DATO_A_ENVIAR, para cargar nuevamente W con el valor del registro. Para la "A" no es necesario pero por las dudas lo deje.
- el ASCII de la "A" es 0x41 o .65, como el 10 seria la A, le sumo .55

EDIT: Ahora releo la pregunta, entendi otra cosa. Creo que con el codigo como te lo pase deberia andar bien. No se por que pense que me habias preguntado que le habia corregido a tu codigo.
« Última modificación: 05 de Febrero de 2015, 00:35:44 por KILLERJC »

Desconectado syndu

  • PIC10
  • *
  • Mensajes: 12
Re: Preguntas sobre assembler
« Respuesta #8 en: 04 de Febrero de 2015, 22:42:16 »
Por lo que decis puede ocurrir por 2 cosas:

1- Por los bancos

Citar
   BANKSEL INTCON
    Movlw   b'10100000'
    Movwf   INTCON

No se bien que banco tomara ya que INTCON es accesible de todos los bancos, por ende buscate otro registro que solo pertenesca al banco 0, o fijate en el proteus is cambia el banco a donde corresponde ( banco 0 )

2- Por malas instrucciones:

incf    Var_C,0  es lo mismo que decir  incf Var_C,W

Por lo tanto incrementa y guarda en W, no se salva el valor, deberias poner incf Var_C,F  o incf Var_C,1, de esa forma el resultado se almacena en el registro



Por otra parte todos esos reviso podrias simplificarlo con una tabla

         
Carga_Duty:
        MOVF    Var_C,W
   ADDWF PCL, F
   GOTO  rojo   
   GOTO  Azul
   GOTO  verde
   GOTO  amarillo
        ........ etc

Y seguro que se puede hacer algo parecido con los colores.

con los colores lo he intentado pero no he sabido como hacerlo :/ GRACIAS por la idea con la variable Var_C! la verdad es que no se muy buen como usar las tablas y por ende no se me ocurrio algo asi! :D me facilitaste mucho las cosas  :mrgreen: :mrgreen: :mrgreen: :mrgreen: :mrgreen: :mrgreen: GRACIAS tambien por lo de "W" tienes razon, no se guardaba en la variable el incremento sino en W! q tonta al no fijarme  :oops: :oops: :oops:
Muchisimas gracias por responder :)

Desconectado Fedextrem

  • PIC10
  • *
  • Mensajes: 25
Re: Preguntas sobre assembler
« Respuesta #9 en: 05 de Febrero de 2015, 19:22:09 »
Citar
EDIT: Ahora releo la pregunta, entendi otra cosa. Creo que con el codigo como te lo pase deberia andar bien. No se por que pense que me habias preguntado que le habia corregido a tu codigo.

Bueno dale espero tu respuesta!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Preguntas sobre assembler
« Respuesta #10 en: 05 de Febrero de 2015, 19:45:57 »
Citar
EDIT: Ahora releo la pregunta, entendi otra cosa. Creo que con el codigo como te lo pase deberia andar bien. No se por que pense que me habias preguntado que le habia corregido a tu codigo.

Bueno dale espero tu respuesta!

Yo creo que deberia quedar solo 1, solamente el de TXREG
recorda que inicialmente tu "DATOS_A_ENVIAR" tenian el valor en hexa, lo que luego se trato y se envia a TXREG es el dato en ASCII.
Si yo quisiera mostrar en UN SOLO display y estuviera usando un CD4511 por ejemplo quisiera que "DATOS_A_ENVIAR" no se modifique para nada.
Si lo quisiera mostrar en 2 displays ( de forma decimal ) entonces deberia tratar el valor original y pasarlo a BCD.

En fin :
DATOS_A_ENVIAR es tu valor original.
Con ese valor generas el ASCII lo que pones en TXREG
Con ese valor generas el BCD / o directametne lo usas para la salida del CD4511 con un display

Por lo tanto deberias de mantenerlo "intacto" asi que quitaria el MOVWF DATOS_A_ENVIAR en ambos(SUMOA y SUMO30).

Otra de las cosas que no me fije es que deberias asegurarte que DATOS_A_ENVIAR no supere los 15 del hexa, con lo cual antes de realizar la primer resta ( la de restar 9 ) podrias hacer una ANDLW 0x0F y asi te aseguras que sea lo que pase a traves de esa variable se cumpla que no exceda la "F".

Modifique un poco mas el codigo:

Código: [Seleccionar]
ENVIAR_DATO                             ;Aca me fijo si es de 0 a 9 asi le sumo 0x30 ('0') o si es una A a F asi le sumo una 'A' a DATO_A_ENVIAR

    BTFSS TXSTA,TRMT                ; Pregunto por si esta libre el USART para mandar otro dato
    RETURN
    MOVF    DATO_A_ENVIAR
    ANDLW  0x0F
    SUBLW   .9
    BTFSC   STATUS,C ; Si esta en 0 es negativo, es decir 9 - DATO_A_ENVIAR = negativo o 9 < DATO_A_ENVIAR  , apartir de 10 se pondria C = 1
    GOTO    SUMO30

SUMOA      ; el dato no es cero por lo tanto sumo A
    MOVF    DATO_A_ENVIAR
    ADDLW   .55 ; 'A' - 10
    MOVWF TXREG      ;Cargo el valor asi se envia
    RETURN

SUMO30       ; el dato que llega es 0 entonces sumo 0x30 a dato a enviar
    MOVF    DATO_A_ENVIAR
    ADDLW   0x30
    MOVWF TXREG      ;Cargo el valor asi se envia
    RETURN

Pregunto por el bit TRMT, este bit esta en 0 cuando esta enviando y en 1 cuando puedo cargar otro valor al UART. Y no uso el flag de interrupcion ( que me obligaba a ponerlo en 0 cada ves que envio ), quite los MOVWF DATO_A_ENVIAR. Y agregue la proteccion para que no supere el valor 15 en decimal (0xF). Con respecto al bit TXSTA.TRMT lo tome de un PIC16F887, no que PIC estas usando, pero seguro que debe haber algo parecido.

Y solo deberias llamar a esta subrutina con un CALL ENVIAR_DATO, obviamente cargando antes el valor de dato_a_enviar con lo que deseas
Luego haras una subrutina para mostrar en los displays,etc.
« Última modificación: 05 de Febrero de 2015, 19:48:32 por KILLERJC »

Desconectado syndu

  • PIC10
  • *
  • Mensajes: 12
Re: Preguntas sobre assembler
« Respuesta #11 en: 09 de Febrero de 2015, 22:11:54 »
Buenas.. otra vez yo :( la cosa es que se "SUPONE" que i programa debe encender un led rgb con diferentes colores....
asi que hice lo siguiente: el periodo que use fue de 10ms y lo dividi en 255 partes eso me dio  39.21us
que deje en 40 us

declare una interrupcion del Timer0 cada 40 us y a su vez incremente una variable Var_I

ahora cada vez que Var_I = 255 esta variable regresa a 0

asi hice 1 periodo de 10ms

ahora el PWM

si Var_I >= pwm1 ?
si es asi apago el led rojo
si no es asi prendo el led rojo

ahora repeti esto mismo 2 veces mas
.... como tambien debo modificar si el periodo es 10, 20, 0 30 ms.. hice o mismo del principio.. dividi 20ms/255 y asi con todos los tiempos que necesito, y calcule el valor del timer para que cada vez que Var_I llegara a 255 se cumplieran todos estos periodos.....
la cosa es que no se porque las ondas que deberian ser cuadradas, con los diferentes periodos segun yo escoja..... me salen horribles :( o sea, no salen como deberia :( alguna ayuda se les agradeceria :S

PD: gracias a los que me han ayudado

este es el codigo...

    list p=16f887
    #include   <p16f887.inc>
    __CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
   __CONFIG    _CONFIG2, _WRT_OFF & _BOR21V
       
   ;------------------------------------------------------------------
;configuro inicio del programa con el vector reset/interrupcion
;*****************************************************************
        org 00H

           goto inicio

     org 04h
        goto Interrupcion
;-----------------------------------------------------------------------
; Inicia Programa
; CONFIGURO I/O
;**********************************************************************

inicio
   
;---------------------------------------------------------------------
; configuro Pre-escaler
;*********************************************************************
    clrwdt
    BANKSEL OPTION_REG
    Movlw   b'00000100'
    Movwf   OPTION_REG
    Movlw   b'10100000'
    Movwf   INTCON
    BANKSEL TRISD
    clrf    TRISC
    BANKSEL PORTA
    clrf    PORTC
;-------------------------------------------------------------------------
; Configuro Variables
;*************************************************************************
    CBLOCK  20H
    pwm_r, pwm_v, pwm_a, W2, Status2, Var_I, Var_C, Var_T
    endc
;-------------------------------------------------------------------------
; Defino pin de puertos
;*************************************************************************
    #Define Led_r PORTC,0
    #Define Led_v PORTC,1
    #Define Led_a PORTC,2

;-----------------------------------------------------------------
;Tabla para cargar los valores de Timer que variaran los tiempo
;*****************************************************************
    goto    inicio1
Tiempo
    movf    Var_T,W
    addwf   PCL,F
    retlw   .255    ;10ms
    retlw   .254    ;20ms
    retlw   .252    ;30ms
    retlw   .251    ;40ms
    retlw   .250    ;50ms
    retlw   .249    ;60ms
    retlw   .247    ;70ms
    retlw   .246    ;80ms
    retlw   .245    ;90ms
    retlw   .244    ;100ms = 1s
    retlw   .243    ;110ms
    retlw   .241    ;120ms
    retlw   .240    ;130ms
    retlw   .239    ;140ms
    retlw   .238    ;150ms
    retlw   .236    ;160ms
    retlw   .235    ;170ms
    retlw   .234    ;180ms
    retlw   .233    ;190ms
    retlw   .231    ;200ms = 2s
inicio1
    movlw   .19
    movwf   Var_T
;--------------------------------------------------------------------------
; Pregunto la variable "Var_C" para ver en que color me encuentro
;**************************************************************************
Carga_duty
    movf    Var_C,W
    addwf   PCL, F
    goto    rojo
    goto    Azul
    goto    verde
    goto    amarillo
    goto    agua
    goto    magenta
    goto    orange
    goto    bonito
    goto    morado
    goto    marron
    goto    violeta
    goto    oscuro
    goto    verde1
    goto    rosado
    goto    verde2
    goto    blanco
;-------------------------------------------------------------------------
; Cargo las variables con los distintos dutys para generar
;los colores correspondientes
;*************************************************************************

rojo
    movlw   .255
    movwf   pwm_r
    movlw   .0
    movwf   pwm_v
    movlw   .0
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm

verde
    movlw   .0
    movwf   pwm_r
    movlw   .255
    movwf   pwm_v
    movlw   .0
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm

Azul
    movlw   .0
    movwf   pwm_r
    movlw   .0
    movwf   pwm_v
    movlw   .255
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm

amarillo
    movlw   .255
    movwf   pwm_r
    movlw   .255
    movwf   pwm_v
    movlw   .0
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm
agua
    movlw   .0
    movwf   pwm_r
    movlw   .255
    movwf   pwm_v
    movlw   .255
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm

magenta
    movlw   .255
    movwf   pwm_r
    movlw   .0
    movwf   pwm_v
    movlw   .255
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm

orange
    movlw   .255
    movwf   pwm_r
    movlw   .140
    movwf   pwm_v
    movlw   .0
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm

bonito
    movlw   .0
    movwf   pwm_r
    movlw   .250
    movwf   pwm_v
    movlw   .154
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm

morado
    movlw   .147
    movwf   pwm_r
    movlw   .112
    movwf   pwm_v
    movlw   .219
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm

marron
    movlw   .139
    movwf   pwm_r
    movlw   .69
    movwf   pwm_v
    movlw   .19
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm

violeta
    movlw   .238
    movwf   pwm_r
    movlw   .130
    movwf   pwm_v
    movlw   .238
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm

oscuro
    movlw   .25
    movwf   pwm_r
    movlw   .25
    movwf   pwm_v
    movlw   .112
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm

verde1
    movlw   .46
    movwf   pwm_r
    movlw   .139
    movwf   pwm_v
    movlw   .87
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm

rosado
    movlw   .220
    movwf   pwm_r
    movlw   .20
    movwf   pwm_v
    movlw   .60
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm

verde2
    movlw   .144
    movwf   pwm_r
    movlw   .238
    movwf   pwm_v
    movlw   .144
    movwf   pwm_a
    incf    Var_C
    goto    Pregunto_Pwm

blanco
    movlw   .255
    movwf   pwm_r
    movlw   .255
    movwf   pwm_v
    movlw   .255
    movwf   pwm_a
    clrf    Var_C
    goto    Pregunto_Pwm

;--------------------------------------------------------------------------
; Pregunto que valor tiene la variable "Var_T" para saber cuando durara mi
; Periodo y con eso modificar el valor del Timer0
;*************************************************************************
Pregunto_Pwm
    call    Tiempo
    BANKSEL TMR0
    Movwf   TMR0

Pregunto_Pwm1
    movf    pwm_r,0
    subwf   Var_I,0
    btfss   STATUS,C
    goto    on_r
    goto    off_r
off_r
    bsf     Led_r
    goto    Pregunto_v
on_r
    bcf     Led_r
    goto    Pregunto_v

Pregunto_v
    movf    pwm_v,0
    subwf   Var_I,0
    btfss   STATUS,C
    goto    on_v
    goto    off_v
off_v
    bsf     Led_v
    goto    Pregunto_a
on_v
    bcf     Led_v
    goto    Pregunto_a

Pregunto_a
    movf    pwm_a,0
    subwf   Var_I,0
    btfss   STATUS,C
    goto    on_a
    goto    off_a
off_a
    bsf     Led_a
    goto    Pregunto_Pwm1
on_a
    bcf     Led_a
    goto    Pregunto_Pwm1
;-------------------------------------------------------------------------
;Pregunto si ya cumplieron los ciclos de trabajo
;**************************************************************************
Pregunto_duty
    movwf    W2
    movf     STATUS,w
    movwf    Status2
;---------------------------------------------------------------------
; Pregunto si Var_I llego a 255
;**********************************************************************
    movlw   .255
    subwf   Var_I,0
    btfss   STATUS,Z
    goto    otro
    clrf    Var_I
;-------------------------------------------------------------------
; devuelvo valor a w y status, tambien pongo en bajo Toif
;****************************************************************
    movf    Status2,w
    movwf   STATUS
    movf    W2,W
    bcf     INTCON,T0IF
    bsf     INTCON,GIE
;---------------------------------------------------------------------
; configuro Interrupcion
;*********************************************************************
    goto    Carga_duty

otro
    bcf     INTCON,T0IF
    call    Tiempo
    Movwf   TMR0
    movf    Status2,w
    movwf   STATUS
    movf    W2,W
    retfie

;--------------------------------------------------------------------
;rutina de interrupcion
;********************************************************************

Interrupcion
    incf    Var_I,f
    goto    Pregunto_duty
    end
« Última modificación: 09 de Febrero de 2015, 22:47:48 por syndu »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Preguntas sobre assembler
« Respuesta #12 en: 09 de Febrero de 2015, 23:06:42 »
Tu idea es de realizar un PWM por software

Tu aproximacion es correcta, pero deberias de mantener tu periodo fijo.. es decir 10ms, no se por que cambiarias tu periodo ( frecuencia )

y luego lo unico que modificas es el limite de 0 a 255 para rojo, para verde y para azul. de esa forma pasas a no darle tension al led a darle tension siempre.

La forma de onda obviamente no es cuadrada, estas modificando el ancho del pulso (Pulse Width) Mientras mas grande sea el valor mas cercano a una señal continua es.

Por otro lado veo que estas cargando el valor 255 ( 0xFF ) en el timer, esto significa que apenas cuente 1 solo se produciria la interrupcion. ya que es un contador ascendente, si quisiera que cuente 255 entonces deberia poner 0x01 en el TMR0.
Ojo con eso.. es el complemento a 2. la interrupcion ocurre cuando pasa de 0xFF a 0x00.

Una de las cosas que tenes que tener en cuenta en las interrupciones es que vas a volver a tu programa ( pensalo como un call - return que mete en el programa cuando ocurre algo ).. ejemplo

Código: [Seleccionar]
decf mi_variable
--> Salta a interrupcion
<-- Vuelve de la interrupcion
btfss status,z

Interrupcion
incf otra_variable
retfie

Si hago eso y ocurre la interrupcion donde lo marque... ese INCF me va a modificar los valores del registro STATUS, asi que cuando vuelva y quiera comprobar el flag Z, no voy a estar comprobando el del DECF , sino el del INCF de la rutina de interrupcion.
Por eso mismo se suele guardar el "contexto" al entrar a la interrupcion, esto es guardar lo que esta en el registro W y lo que esta en el registro STATUS. para luego reponerlo cuando salga.

Código: [Seleccionar]
Interrupcion
    incf    Var_I,f
    goto    Pregunto_duty

Otra cosa... asi no funciona la interrupcion.. no podes usar un goto para volver a donde gustes. La interrupcion esta para atender eventos y no afectar el curso del programa.

Código: [Seleccionar]
Interrupcion
  ; Guardo contexto, codigo en el datasheet
  ; Limpio flag de interrupcion
  ; Cargo valor en TMR0 de ser necesario
  INCF  Var_I,F
  ; Devuelvo el contexto
  RETFIE  ; retorna a donde ocurrio la interrupcion y activa nuevamente las interrupciones globales GIE

Con lo cual tu interrupcion seria lo que puse arriba y tu programa algo asi:

Principal:
si Var_I >= pwm_verde ? SI: apago led , NO enciendo led
si Var_I >= pwm_rojo ? SI: apago led , NO enciendo led
si Var_I >= pwm_azul ? SI: apago led , NO enciendo led
Aca pones la condicion para cuando quieras que aumente Var_C, incrementas Var_C y preguntas por los nuevos colores que van a quedar en pwm_verde, pwm_rojo y pwm_azul
GOTO principal.
« Última modificación: 09 de Febrero de 2015, 23:15:19 por KILLERJC »

Desconectado Fedextrem

  • PIC10
  • *
  • Mensajes: 25
Re: Preguntas sobre assembler
« Respuesta #13 en: 10 de Febrero de 2015, 17:16:02 »
Buenas! El programa tiene un defecto, en una parte donde tengo que tomar los datos para después enviarlos no los esta tomando y no le veo el porque, recibe los datos de llaves en binario y los pasa a bcd para que se vean en los displays. Acá el código:
Código: [Seleccionar]
TOMAR_DATOS
MOVF PORTA ;supongo que esta en el porta el dato en el nibble bajo
        ANDLW 0x0F
MOVWF DATO_A_ENVIAR
        addlw    .256-.10       ; C will be set if number was >= 10
        BTFSC    STATUS,C
        addlw    .6                  ; ...adjust for 10..29
        addlw    -(.256-.10)   ; Back to original value;paso a BCD
        ANDLW 0x0F
        MOVWF UNIDADES
SWAPF DATO_A_ENVIAR,W
        ANDLW 0x0F
        MOVWF DECENAS



Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Preguntas sobre assembler
« Respuesta #14 en: 10 de Febrero de 2015, 19:39:54 »
Primero que nada disculpa Fedextrem por si omito algo es que ya no recuerdo exactamente como era tu programa, voy a suponer por lo que recuerdo que los datos se tomaron de las llaves y se guardaron en DATO_A_ENVIAR, y habiamos dicho que DATO_A_ENVIAR se intente mantener lo mas original posible. Ahora que recuerdo un poco mas esta es la parte de donde tomamos los datos y ademas sacamos el BCD de ellos.

Código: [Seleccionar]
       addlw    .256-.10       ; C will be set if number was >= 10
        BTFSC    STATUS,C
        addlw    .6                  ; ...adjust for 10..29
        addlw    -(.256-.10)   ; Back to original value;paso a BCD

Ese codigo toma lo que hay W y luego cuando termina en W queda el codigo BCD, solamente permite 4 bits.

Código: [Seleccionar]
TOMAR_DATOS
MOVF PORTA ;supongo que esta en el porta el dato en el nibble bajo
        ANDLW 0x0F              ; solo dejo pasar el nibble bajo
MOVWF DATO_A_ENVIAR   ; lo guardo en DATO_A_ENVIAR asi las demas subrutinas pueden usar el valor original que se tomo
        addlw    .256-.10       ; Procedo a pasarlo a BCD
        BTFSC    STATUS,C
        addlw    .6                  
        addlw    -(.256-.10)   ; Final del paso a BCD
        MOVWF UNIDADES     ; Utilizo al registro como un registro temporal.  UNIDADES = decenas:unidades
SWAPF  UNIDADES,W  ; Cambio de lugar los nibbles    W = unidades:decenas
        ANDLW 0x0F             ; Elimino las unidades en W, me quedan las decenas ... W = 0:decenas
        MOVWF DECENAS       ; Guardo las decenas
        MOVF UNIDADES        ; Vuelvo a cargar todo el resultado del BCD -> decenas:unidades
        ANDLW 0x0F             ; Elimino las decenas   W = 0:unidades
        MOVWF UNIDADES     ; Guardo las unidades

Es hace que tome el dato del PORTA, guarde las 4 bits de menor peso en DATO_A_ENVIAR asi es tratado en las demas subrutinas y luego lo pasa a BCD y los guarda en DECENAS y UNIDADES

Variables de entrada: Ninguna

Variables de salida:

DATO_A_ENVIAR
DECENAS
UNIDADES



EDIT: ahora vi donde fue, perdon me equivoque en el codigo yo q te habia pasado antes.
« Última modificación: 10 de Febrero de 2015, 19:42:01 por KILLERJC »


 

anything