Autor Tema: trabajar con 16 bits en un pic  (Leído 7011 veces)

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

agaran

  • Visitante
trabajar con 16 bits en un pic
« en: 15 de Diciembre de 2005, 06:20:00 »
Muy buenas,

Quisiera saber si es posible trabajar con valores de 16 bits en un pic que según tengo entendido el tamacho de palabra en los registros es de 8 bits.

Por ejemplo, que sucede si sumo 1111d con 1111d

Muchas gracias

Desconectado Artifox

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 455
    • Quadbot
RE: trabajar con 16 bits en un pic
« Respuesta #1 en: 15 de Diciembre de 2005, 07:29:00 »
Hola, de ser posible es posible, pero necesitas hacer tus algoritmos para trabajarlos en asembler, me parece que en la pagina de microchip hay algo de eso. Por otro lado si quieres trabajar con 16 bits podrias utilizar compiladores en Basic o C, los cuales ya tienen implementado el trabajo con 16 bits.

Nos vemos, un abrazo RebotadoRebotado
Video Quadbot
Saludos desde mi querido Perú.
Si realmente queremos que el mundo cambie debemos empezar por nosotros mismos... ;)

Desconectado vszener

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2395
RE: trabajar con 16 bits en un pic
« Respuesta #2 en: 15 de Diciembre de 2005, 09:13:00 »
Holaa!!!bueno para trabajar con 16bits como bien a dicho el amigo Artifox necesitamos nuestros propios algoritmos, para eso declaras cuatro variables de 8 bits donde dos de ellas seran un numero y las otras dos seran el otro numero, es decir, por ejemplo declaramos numA_bajo y numA_alto, dichas variables definen el numero de 16bits identificadas por su parte alta y baja. Y cuando sumes las partes bajas de los dos numeros mira haber si ha habido desvordamiento, si lo ha habido deberas sumar un 1 a la suma de la parte alta de los dos numeros.

Suerte!!!Giño
· Nos vemos en los bares!!!!!
· Mi Blog: Aqueronte

Desconectado Azicuetano

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1020
    • Aplicaciones Electrónicas en Alicante.
RE: trabajar con 16 bits en un pic
« Respuesta #3 en: 16 de Diciembre de 2005, 18:53:00 »
Hola agaran!

Estas son las rutinas que yo personalmente utilizo. En su día las busqué, me funcionaron bien y... nunca me ha dado por optimizarlas (no he tenido tiempo).

Codigo:
suma_16_bits

      movf   Dato_A_L,W      ;Carga menos peso del dato A
      addwf   Dato_B_L,W      ;Suma menos peso del dato B
      movwf   Resultado_L      ;Almacena el resultado
      movf   Dato_A_H,W      ;Carga más peso del dato A
      btfsc   STATUS,C                      ;Hubo acarreo anterior ??
      addlw   1         ;Si, suma 1 al acumulador
      addwf   Dato_B_H,W      ;Suma más peso del dato B
      movwf   Resultado_H      ;Guarda el resultado

      return



Codigo:
resta_16_bits

      movf   Dato_B_L,W      ;Carga menos peso del dato B (sustraendo)
      subwf   Dato_A_L,W      ;Resta menos peso del dato A (minuendo)
      movwf   Resultado_L      ;Almacena el resultado
      movf   Dato_B_H,W      ;Carga más peso del dato B (sustraendo)
      btfss   STATUS,C                      ;Hubo acarreo (CARRY = 0) anterior ??
      addlw   1                      ;Si, añade 1 al acumulador (sustraendo)
      subwf   Dato_A_H,W      ;Resta más peso del dato A (minuendo)
      movwf   Resultado_H      ;Guarda el resultado

      return



Codigo:
; MULTIPLY multiplier, multiplicand
; Multiply two 16-bit numbers into a 16-bit product, permitting overflow.


Multiply
             CLRF prodH                 ; Clear product to make
             CLRF prodL                 ; way for new calculation.
             MOVLW d"16"                ; Number of bits to calc.
             MOVWF index
Multiply_loop
             BCF STATUS,C              
             RLF prodL                  ; Shift product left.
             RLF prodH                  
             BCF STATUS,C              
             RLF mulcL                  ; Shift multiplicand left.
             RLF mulcH                  
             BTFSS STATUS,C             ; If carry, add multiplier
             GOTO Multiply_skip
             MOVF mulpL,w               ; to the product. Else skip.
             ADDWF prodL
             BTFSC STATUS,C             ; 16-bit addition: prod+mulp
             INCF prodH                
             MOVF mulpH,w              
             ADDWF prodH
Multiply_skip
             DECFSZ index              
             GOTO Multiply_loop
             RETLW 0h





Codigo:
; ; DIVIDE
; Divide one 16-bit number into another, returning the 16-bit result and
; the remainder. Upon entry, the top of the division fraction (the dividend)
; must be in topH and topL, and the bottom (divisor) in btmH and btmL.
; If division by zero is attempted, the routine will return immediately with
; the error code of 0FFh in w. Otherwise, it will perform the division, leaving
; the remainder in topH and topL and the result (quotient) in qH and qL.
; Upon return from a successful division, w contains 0.


Divide       MOVF btmH,w                ; Check for division by 0.
             IORWF btmL,w              
             BTFSC STATUS,Z            
             RETLW d"255"               ; Error code= 255: return.
             MOVLW d"1"                 ; Otherwise, initialize variables
             MOVWF count
             CLRF index                 ; for the division.
             CLRF qH                    
             CLRF qL                    

Divide_sh_loop  BTFSC btmH,d"7"         ; Shift divisor left
             GOTO Divide_d1
             BCF STATUS,C               ; until msb is in
             RLF btmL                   ; btmH.7.
             RLF btmH                   ; count = no. of shifts+1.
             INCF count                
             GOTO Divide_sh_loop        
Divide_d1    BCF STATUS,C              
             RLF qL                     ; Shift quotient left.
             RLF qH                    
             MOVF btmL,w                ; top = top - btm.
             SUBWF topL
             BTFSC STATUS,C             ; If top - btm < 0 then
             GOTO Divide_d2
             MOVLW d"1"                 ; top = top + btm
             SUBWF topH
             BTFSC STATUS,C             ; The idea is to do the
             GOTO Divide_d2
             INCF topH                  ; the subtraction and comparison
             MOVF btmL,w                ; (top > btm?) in one step.
             ADDWF topL
             goto Divide_reentr         ; Then, if btm > top, undo <Microchip instruction>
Divide_d2    MOVF btmH,w                ; the subtraction by adding
             SUBWF topH
             BTFSS STATUS,C             ; top and btm back together
             goto Divide_less           ; <Microchip instruction>
             BSF qL,d"0"                
Divide_reentr
             BCF STATUS,C              
             RRF btmH                  
             RRF btmL                  
             DECFSZ count              
             GOTO Divide_d1
             RETLW 0h                   ; Return w/ remainder in top
                                        ; and result in q.&nsp;
Divide_less  MOVF btmL,w                ; btm > top, so
             ADDWF topL
             BTFSC STATUS,C             ; undo the subtraction by
             INCF topH                  ; adding them back together.
             MOVF btmH,w                
             ADDWF topH
             goto    Divide_reentr      ; <Microchip instruction>




Vamos a  sumar 1111+3333 (el resultado será 4444).

1111 (decimal) = 00000100 01010111

3333 (decimal) = 00001101 00000101

movlw     b"00000100"
movwf    Dato_A_H
movlw     b"01010111"
movwf    Dato_A_L

movlw     b"00001101"
movwf    Dato_B_H
movlw     b"00000101"
movwf    Dato_B_L

call         suma_16_bits

El resultado lo tienes en las variables Resultado_H y Resultado_L

Resultado_H = 00010001
Resultado_L = 01011100


La resta no tienes más que pegarle un vistazo (es prácticamente igual).


Para explicar la multiplicación haremos la siguiente operación.

133 * 99 = 13167

133 = 00000000 10000101
99   = 00000000 01100011

movlw    b"00000000"
movwf    mulcH
movlw    b"10000101"
movwf    mulcL

movlw    b"00000000"
movwf    mulpH
movlw    b"01100011"
movwf    mulpL

call         Multiply

El resultado lo tienes en las variables prodH y prodL

prodH = 00110011
prodL = 01101111

Para la división puedes leer el comentario de la función (explican como utilizarla).

Ya me comentas como te va la cosa.

Un saludo desde Alicante.