Autor Tema: PIC16F1707 Ejemplos básicos  (Leído 18465 veces)

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

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:PIC16F1707 Ejemplos básicos
« Respuesta #15 en: 07 de Noviembre de 2015, 19:38:25 »
Te puedo dar ejemplos de aplicacion que seria mejor con un acceso indirecto que uno directo. El mas clasico es un buffer. Comencemos por un buffer de 4 lugares. En el que recibis datos por la UART o SPI y vas guardando los valores, finalmente tenes que hacer un checksum de esos valores. Como harias con direccionamiento directo el guardar estos 4 lugares ?

Código: ASM
  1. Guardado
  2.         MOVF    Indice, W       ;El indice de mi dato
  3.         ADDWF   PCL, F          ; Utilizo una tabla para ir al programa donde debo guardarlo
  4.         GOTO    Dato0
  5.         GOTO    Dato1
  6.         GOTO    Dato2
  7.  
  8.         MOVF    DatoUART, W
  9.         MOVWF   Buffer3
  10.         CLRF    Indice          ; Comienzo de nuevo
  11.         RETURN
  12.  
  13. Dato0
  14.         MOVF    DatoUART, W     ; Tomo dato y guardo
  15.         MOVWF   Buffer0
  16.         RETURN
  17. Dato1
  18.         MOVF    DatoUART, W
  19.         MOVWF   Buffer1
  20.         RETURN
  21. Dato2
  22.         MOVF    DatoUART, W
  23.         MOVWF   Buffer2
  24.         RETURN


Y eso es solo para guardarlo. Ahora debo sumarlos

Código: ASM
  1. MOVF    Buffer0, W
  2.         ADDWF   Buffer1, W
  3.         ADDWF   Buffer2, W
  4.         ADDWF   Buffer3, W

Bien, solo 4 instrucciones, bastante simple, o podria sumarlos apenas van llegando eso me ahorraria instrucciones. Ahora veamos usando acceso indirecto

Antes de comenzar cargo en el FSR los el valor de buffer0, es decir su direccion.

Código: ASM
  1. MOVLW   low(Buffer0)
  2.         MOVWF   FSR0L
  3.         MOVLW   high(Buffer0)
  4.         MOVWF   FSR0H

Lo que hago con eso es decir que cuando yo acceda a INDF0 , es lo mismo que acceder a la direccion de memoria que esta cargada en FSR0, en mi caso de acceder a INDF0 accederia a Buffer0. En los PIC16 normales harias eso, aca tenes una instruccion que lo hace por si solo, solo tenes que indicarle que FSR estas tratando y que hace depues
Ahora a guardar el dato:

Código: ASM
  1. Guardado
  2.         MOVLW   d'4'
  3.         MOVWF   Contador
  4. Loop
  5.         MOVF    DatoUART, W
  6.         MOVWI   FSR0++
  7.         DECFSZ  Contador, F
  8.         RETURN
  9.  
  10. Recargar_FSR
  11.  
  12.         MOVLW   low(Buffer0)
  13.         MOVWF   FSR0L
  14.         MOVLW   high(Buffer0)
  15.         MOVWF   FSR0H
  16.         RETURN
La instruccion MOVWI, lo que hace es guardar el dato de W en la direccion que tiene FSR0 (Buffer0 ) Luego a esa direccion la incrementa por 1 apuntando ahora a Buffer1 (Al incrementar por 1 tiene en cuenta ambos registros FSR0 L y H). Entonces la proxima ves que entre va a guardar W en Buffer1 y va a apuntar a Buffer2 y asi hasta que guarde en Buffer3 y apunte a lo que sigue, ahi en ese momento me va a dar una igualdad el codigo y va a reponer el valor de FSR

Para sumar seria algo parecido

Código: ASM
  1. Guardado
  2.         MOVLW   d'4'
  3.         MOVWF   Contador
  4.         CLRF    Suma_Total
  5.         CALL    Recargar_FSR    ;Nos aseguramos que empezamos del comienzo
  6. Loop:
  7.         MOVIW   FSR0++
  8.         ADDWF   Suma_Total, F
  9.         DECFSZ  Contador, F
  10.         GOTO    Loop                    ; Todavia quedan para sumar asi que vuelve al loop
  11.         RETURN                          ; No queda mas nada

Nuevamente veo a que llegue al final y de ser asi salgo. Esta ves la instruccion es inversa (MOVIW ), tomo desde donde apunta el FSR0 y lo guardo en W. Y luego aumento FSR0.

Perfecto, pero para que complicarse la vida por 4 valores? Ahora supone que tenes un buffer de 32 lugares. No es nada lindo hacerlo con acceso directo, Y con acceso indirecto solo deberia cambiar esto (en ambos lugares ):

Código: ASM
  1. MOVLW   d'4'

por un

Código: ASM
  1. MOVLW   d'32'

Y listo funcionando :P.

Solo hay incrementos ? No. Esa instruccion permite pre y post incremento y decremento

Código: ASM
  1. MOVWI FSR0++      ; Guarda y luego aumenta
  2. MOVWI  ++FSR0     ; Aumenta y luego guarda
  3. MOVWI  FRS0--       ; Guarda y luego decrementa
  4. MOVWI  --FRS0       ; Decrementa y luego guarda.
  5. MOVWI  k[FSR0]     ; Guarda solamente, no incrementa ni decrementa., igual que hacer MOVWF INDF0

--------------------------------------------------------------------------------------------------------------

Ahora veamos un poco mas tu ejemplo.
viste el codigo que te llevo hacer un Hola no ?

Entonces hagamos algo simple para comenzar.

Vamos a crear una tabla ( no recuerdo si esta correctamente definida asi, no tuve tiempo de mirar el manual del MPASM )

Tabla:
.dt 0x00, 0xFE, 0x10, 0x10, 0xFE, 0xFC, 0x82, 0x82, 0x7C
.dt 0x00, 0xFE, 0x80, 0x80, 0x80, 0x00, 0xFC, 0x12, 0x12
.dt 0xFC, 0x00

Es un total de ... 20 datos que envias. En ves de binario los puse como hexadecimal

Código: ASM
  1. Tabla:
  2. .dt 0x00, 0xFE, 0x10, 0x10, 0xFE, 0xFC, 0x82, 0x82, 0x7C
  3. .dt 0x00, 0xFE, 0x80, 0x80, 0x80, 0x00, 0xFC, 0x12, 0x12
  4. .dt 0xFC, 0x00
  5.  
  6.  
  7.         MOVLW   low(Tabla)              ;Cargo Valor inicial de la tabla
  8.         MOVWF   FSR0L
  9.         MOVLW   high(Tabla) | 0x80
  10.         MOVWF   FSR0H
  11.  
  12.         MOVLW   d'20'                   ;Pongo la cantidad de datos a enviar
  13.         MOVWF   Contador
  14.  
  15. Loop
  16.         MOVIW   FSR0++                  ; Leo la tabla guardo en W y apunto al siguiente dato
  17.         CALL    DATO_SPI                ; LLamo a la funcion de enviar
  18.         DEFSZ   Contador, F             ; Decremetno el contador y si llego a 0 salgo, sino envio el siguiente
  19.         GOTO    Loop
  20.         ;Fin

Y listo. con acceso indirecto accediste a la memoria de programa, tomaste todos los datos que necesitaste y listo. Pero esto seguro que lo hiciste antes.. antes hacias:

Código: ASM
  1. ADDWF   PCL, F
  2.         RETLW   0x00
  3.         RETLW   0xFE
  4.         RETLW   0x10
  5.         RETLW   0x10
  6.         RETLW   0xFE
  7.         ....
  8.         RETLW   0x00

O podias usar la misma tabla que antes.. Pero esto se complicaba si la tabla estaba entre 2 paginas.
Recorda que PCL es un registros de 8 bits y por lo tanto solo puede direccionar 256 lugares. Si querias uno mas ya se ponia mas complejo por que tenias que modificar PCLATH a la entrada y a la salida de la funcion.

Esto con el acceso indirecto que permite leer la memoria de programa no hace falta. Ya que FSR0 ( Ly H ) son 16 bits y permiten direccionar toda la memoria, si hay un incremento de 1 no es complicacion para el mismo.

EDIT: Estos codigos ninguno esta probado, asi que tal ves tengan errores, pero es para que te des una idea de como usarlos, seguro que no deben de estar MUY errados. pero si puden tener algunos errores.
Corregido el tema de usar un contador
« Última modificación: 09 de Noviembre de 2015, 12:37:50 por KILLERJC »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:PIC16F1707 Ejemplos básicos
« Respuesta #16 en: 07 de Noviembre de 2015, 20:32:49 »
Otro ejemplo bastante simple y "tonto" seria el de tener que estar cambiando de bancos a cada rato. Aunque el PIC agrupa todo en un solo banco, a veces tenes que cambiar.
Supongamos que estas continuamente cambiando el valor de LATB, y ademas queres leer el PORTB. Uno esta en el banco 2 y otro en el banco 0.

Formas mas comun:

Código: ASM
  1. MOVLB   0
  2.         ;Leo PORTB
  3.         MOVF    PORTB, W
  4.  
  5.         MOVLB   2
  6.         ;Escribo LATB
  7.         MOVLW   0x10
  8.         MOVWF   LATB


Ahora con acceso indirecto, al comienzo le cargo el valor de direccion del LATB

Código: ASM
  1. MOVLW   low(LATB)
  2.         MOVWF   FSR0L
  3.         MOVLW   high(LATB)
  4.         MOVWF   FSR0H


Luego lo unico que hago es:

Código: ASM
  1. MOVLB   0       ; Estoy en el banco 0, me aseguro
  2.         ;Leo PORTB
  3.         MOVF    PORTB, W
  4.  
  5.         ;Escribo LATB
  6.         MOVLW   0x10
  7.         MOVWF   INDF0

Como el acceso indirecto tiene 16 bits para direccionar no le hace falta tener que cambiar de "bancos". En cambio las instrucciones comunes que usan acceso directo ( es decir el dato esta en su opcode) solo usan 8 bits, por lo tanto es necesario cambiar de "banco". Para el acceso indirecto no existen los bancos, es lo mejor que podes tener ya que podes direccionar toda la memoria. Utiles en casos como grandes lugares de datos a rellenar. o incluso pedir datos.

Si quisiera leer los datos del PORTA, PORTB y PORTC como estan todos seguidos podria hacerlo tanto como un acceso directo como indirecto.
Como ves es medio complejo cargar la direccion en los registros, pero si va a un PIC18 te encontras que tenes una instruccion que te permite cargar la direccion.

Entonces en ves de hacer lo que hicismos arriba solo haria un

Código: [Seleccionar]
   LFSR 0, LATB
Y cargaria toda la direccion ( por mas que sean mas de 8 bits ) al FSR0. Esto en los PIC18, este no lo posee.
« Última modificación: 07 de Noviembre de 2015, 20:39:04 por KILLERJC »

Desconectado Pinolillo16

  • PIC18
  • ****
  • Mensajes: 324
Re:PIC16F1707 Ejemplos básicos
« Respuesta #17 en: 08 de Noviembre de 2015, 05:32:35 »
KillerJc muchas gracias por esos ejemplos. Vamos por partes para que termine de entender:

Cuando hablamos de FSRL y FSRH entiendo que estamos refiriéndonos a la dirección únicamente?
y cuando hablamos de INDF es el dato o valor contenido dentro de esa dirección o el que vamos a mover a esa direccion?

La instrucción MOWI es nueva para mi y me quedo clara. Un pequeño ejemplo si no me equivoco si yo tengo un DatoX alojado en una dirección 0x34 por decir un ejemplo. Puedo cargar un valor a DatoX poniendo las direcciones en FSRl y FSRH. Y la literal cargarla a INDF?

La instrucción MOVIW es inversa tal cual lo dijiste del INDF movemos a W y aumenta en 1 FSR. Entendido.

Muy claros todos los ejemplos ahora, una pregunta algo tonta las direcciones de los registros que utilizo como variables siempre las he utilizado con un CBLOCK 0x020 entonces la primera enseguida corresponde a 0x020 y así sucesivamente? Si es así hasta que dirección me limita?

Y respecto al último ejemplo, anexo una imagen de los SFRs sacada del Data donde encierro la dirección del registro LATA, aquí dos preguntas. La dirección que yo debería cargar es FSRH=0x01  y FSRL=0x0C ?

Y la otra es, si yo no le indico al FSR que incremente o decremente guarda la última dirección? Por ejemplo si siempre quisiera mostrar datos por LATB puedo dejar la dirección y solo mandarlos al INDF?

Perdón se me olvidaba, en los PIC18F esa última instrucción que mencionas es para cargar la dirección del registro que indicas?

LFSR 0, LATB

De tu ejemplo,  LFSR 0,LATB   quiero entender que LSFR es algo como cargar al FSR  con dirección de R(LatB). El cero a que se refiere?


Gracias KillerJC y disculpa tantas preguntas. Me interesa aprender a manejarlos.
« Última modificación: 08 de Noviembre de 2015, 05:35:39 por Pinolillo16 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:PIC16F1707 Ejemplos básicos
« Respuesta #18 en: 08 de Noviembre de 2015, 10:08:17 »
Empecemos por que no hay preguntas tontas.

Citar
Cuando hablamos de FSRL y FSRH entiendo que estamos refiriéndonos a la dirección únicamente?
y cuando hablamos de INDF es el dato o valor contenido dentro de esa dirección o el que vamos a mover a esa direccion?

Exacto, tenes varios FSR, en ese pic hay 2 FSR0 y FSR1, cada uno con su propio INDF. en los FSR la direccion y el INDF como decis accedes a la direccion que apunta el FSR

Citar
La instrucción MOWI es nueva para mi y me quedo clara. Un pequeño ejemplo si no me equivoco si yo tengo un DatoX alojado en una dirección 0x34 por decir un ejemplo. Puedo cargar un valor a DatoX poniendo las direcciones en FSRl y FSRH. Y la literal cargarla a INDF?

Correcto. La instruccion es nueva para mi tambien. Pero la MOVWI te permite hacerlo sin tener que especificar que lo moves a INDF. Por eso puse que podias hacerlo de 2 formas

MOVWI  k[FSR0]
MOVWF INDF0

Ambos son equivalentes. Utilizas distintas instrucciones,, pero el objetivo es el mismo, es guardar lo de W a donde apunta el FSR0, y no incrementar ni nada.

Citar
Muy claros todos los ejemplos ahora, una pregunta algo tonta las direcciones de los registros que utilizo como variables siempre las he utilizado con un CBLOCK 0x020 entonces la primera enseguida corresponde a 0x020 y así sucesivamente? Si es así hasta que dirección me limita?
Tenes que entender que hace CBLOCK, Con CBLOCK vos lo unico que haces es darle un valor constante a una palabra. Esto hace que tu codigo sea absoluto, es decir vos controlas exactamente donde va a estar cada variable

CBLOCK 0x20
Var1
Var2
ENDC

Var1 es una constante 0x20, y Var2 es una constante 0x21
Esto al ser una constante permite que uno pueda hacer:

MOVLW Var1
MOVLW Var2

Y es correcto, por que justamente Var1 es una constante. Hay otras formas para definir una variable, yo en un post de PIC18 creo que se trato el tema.
http://www.todopic.com.ar/foros/index.php?topic=45254.msg376570#msg376570

El usarlo asi o no hace de tu codigo por ahi mas dependiente del PIC y mas dificil de portar a otro PIC, ya que no solo te preocuparias sobre las instrucciones que son distintas sino que ademas tendrias que ver la memoria exacta. De la forma que digo yo el compilador se encarga solo de acomodar las variables donde hay lugar. Y puede evitar algunos problemas

Ahora respondiendo tu pregunta, No estas limitado en direccion. Personalmente si yo hubiera necesitado de variables muy usadas las hubiera posicionado de 0x70 a 0x7F que es compartido por todos los bancos, sino podes usar cualquier direccion que este como General Purpose Register, es decir:
0x20 a 0x6F - Banco 0
0xA0 a 0xEF - Banco 1
0x120 a 0x16F - Banco 2

Esos serian los unicos limites a respetar.

Citar
Y respecto al último ejemplo, anexo una imagen de los SFRs sacada del Data donde encierro la dirección del registro LATA, aquí dos preguntas. La dirección que yo debería cargar es FSRH=0x01  y FSRL=0x0C ?
Si asi es. Pero supongamos que cambias de micro y LATB ahora se encuentra en 0x0212 , si pones solo constantes vas a tener que cambiar eso tambien. con low(LATB) te da 0x0C y con high(LATB) te da 0x01, si por alguna razon existiera 3 bytes por que la memoria es MUY grande (24 bits), podrias usar upper(xx) esto daria el byte mas importante. Pero lo que queria recalcar es que usando high y low te olvidas de luego cambiar lo demas. si te fijas en tu .inc LATB esta definido como

LATB EQU 0x10C

Citar
Y la otra es, si yo no le indico al FSR que incremente o decremente guarda la última dirección? Por ejemplo si siempre quisiera mostrar datos por LATB puedo dejar la dirección y solo mandarlos al INDF?
El FSR no se modifica jamas por si solo, vos cargas la direccion, y a no ser que vos expresamente pidas con una instruccion que incremente o decremente, no lo va a hacer y va a mantener la misma direccion. Con lo cual tenes las dos opciones que nombre antes tanto con el MOVWI /IW como MOVWF para "acceder" a INDFx

Citar
Perdón se me olvidaba, en los PIC18F esa última instrucción que mencionas es para cargar la dirección del registro que indicas?

LFSR 0, LATB

De tu ejemplo,  LFSR 0,LATB   quiero entender que LSFR es algo como cargar al FSR  con dirección de R(LatB). El cero a que se refiere?

La instruccion que puse no recuerdo si es correcta o no. Pero no debe estar muy lejos. Esa instruccion ocupa 2 lugares de memoria, pero en su opcode pueden tener hasta 12bits ( y no 8 como la mayoria ) entonces lo que hace es cargar los 12 bits de direccion de LATB a FSR0 , el 0 indica a que FSR lo envio.

Cualquier otra pregunta que se te ocurra, podes hacerla sin problemas

Desconectado Pinolillo16

  • PIC18
  • ****
  • Mensajes: 324
Re:PIC16F1707 Ejemplos básicos
« Respuesta #19 en: 08 de Noviembre de 2015, 11:09:52 »
Creo que explicas demasiado bien KillerJC  ((:-)) muchisimas gracias, bueno pues como me dejas la puerta abierta a otras preguntas. Los otros FSRs, funcionan igual? Y acaso sirven para poder manejar direccionamiento indirecto con 2 registros diferentes sin que se alteren el uno al otro?

Saludos y de nuevo muchas gracias.


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:PIC16F1707 Ejemplos básicos
« Respuesta #20 en: 08 de Noviembre de 2015, 23:29:39 »
En ese PIC tenes 2 FSR, independientes uno de otro. Y si funcionan igual.

En otros PICs a veces algun FSR tiene unas propiedas mas. Por ejemplo en el PIC18 el FSR2 se usa en el modo extendido de instrucciones, los demas FSR ( 0 y 1 ) no se pueden usar para el acceso a memoria + offset. En fin esto es un caso especial, y activar el set de instrucciones extendido es un caso MUY raro de ver si alguno programa en ASM.

Respecto a un programa que use 2 FSR podria ser el de copiar un buffer a otro lado.

FSR0 = Buffer0
FSR1 = Buffer1

Y luego haces un

MOVIW FSR0++
MOVWI FSR1++

Repetis eso varias veces y estarias copiando los valores a otro buffer.  Por mas que sean 64 valores solo necesitas repetir esas 2 instrucciones 64 veces. El FSR0 seria el origen y el FSR1 el destino, podria haber cargado la ultima posicion de memoria y haber invertido el buffer
« Última modificación: 09 de Noviembre de 2015, 00:03:52 por KILLERJC »

Desconectado Pinolillo16

  • PIC18
  • ****
  • Mensajes: 324
Re:PIC16F1707 Ejemplos básicos
« Respuesta #21 en: 09 de Noviembre de 2015, 00:57:16 »
Excelente información KillerJC  :-/ deberiamos tener en el foro puntos por consejos dados y tu estarias repleto de puntos. Bueno sigo trabajando en ejemplos y los colgaré espero no equivocarme. Solo una pregunta más, las tablas las he manejado muy poco solo con el PCL y a lo mucho unos 20 saltos no más. Como ingreso la dirección de la tabla? Es decir como se donde le puedo asignar un origen? Si ocupo varias tablas para generar distintos caracteres que direccion le puedo dar a cada una?


Saludos

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:PIC16F1707 Ejemplos básicos
« Respuesta #22 en: 09 de Noviembre de 2015, 01:23:35 »
De la misma forma que te di el ejemplo antes.. Supongamos que tenes una tabla

Código: ASM
  1. Tabla:
  2. .dt 0x00, 0xFE, 0x10, 0x10, 0xFE, 0xFC, 0x82, 0x82, 0x7C
  3. .dt 0x00, 0xFE, 0x80, 0x80, 0x80, 0x00, 0xFC, 0x12, 0x12
  4. .dt 0xFC, 0x00
  5.  
  6.  
  7.         MOVLW   low(Tabla)              ;Cargo Valor inicial de la tabla
  8.         MOVWF   FSR0L
  9.         MOVLW   high(Tabla) | 0x80
  10.         MOVWF   FSR0H

El .dt hace que los datos que pones se transformen en instrucciones RETLW

.dt 0xFC, 0x00, 0x75

El compilador lo transforma en

RETLW 0xFC
RETLW 0x00
RETLW 0x75

Y Tabla ( es decir la etiqueta ) es la direccion del primer elemento de todos esos RETLW

Citar
Si ocupo varias tablas para generar distintos caracteres que direccion le puedo dar a cada una?
No entiendo por que necesitas tantos caracteres, si las letras estan en la ROM

Si vos decis que queres tener varios mensajes a mostrar en el LCD podrias tener algo asi:

Código: ASM
  1. Mensaje1: .dt "Hola Hola Hola",0x00
  2. Mensaje2: .dt "Aca otro mensaje",0x00
  3. Mensaje3: .dt "Nuevo mensaje",0x00

Entonces luego cargas en el FSR la direccion de Mensaje1 2 o 3 segun quieras mostrar y envias al LCD hasta que encuentre un 0x00 el cual le va a indicar que termine el string ese

Código: ASM
  1. Enviar_mensajes
  2.  
  3.         MOVLW   low(Mensaje1)           ;Cargo Valor inicial de la tabla
  4.         MOVWF   FSR0L
  5.         MOVLW   high(Mensaje1) | 0x80
  6.         MOVWF   FSR0H
  7.         CALL Enviar                     ;Envio Mensaje1
  8.  
  9.         MOVLW   low(Mensaje2)           ;Cargo Valor inicial de la tabla
  10.         MOVWF   FSR0L
  11.         MOVLW   high(Mensaje2) | 0x80
  12.         MOVWF   FSR0H
  13.         CALL Enviar                     ;Envio Mensaje2
  14.  
  15.         MOVLW   low(Mensaje3)           ;Cargo Valor inicial de la tabla
  16.         MOVWF   FSR0L
  17.         MOVLW   high(Mensaje3) | 0x80
  18.         MOVWF   FSR0H
  19.         CALL Enviar                     ;Envio Mensaje3
  20.  
  21.         RETURN
  22.  
  23. Enviar
  24.         MOVIW   FSR0++          ; W = [FSR0] , luego FSR0 = FSR0 + 1
  25.         CALL    Enviar_a_LCD    ; Llamo a la rutina para que envie el valor de W
  26.         MOVIW   k[FSR0]         ; Pregunto si el valor que esta ahora es 0, W = [FSR0], la instruccion actualiza Z
  27.         BTFSS   STATUS,Z       
  28.         GOTO    Enviar          ; No es 0 entonces la palabra sigue
  29.         RETURN                  ; Es 0 entonces salgo

Observa que en los comentarios puse [FSR0] como para indicar el contenido de lo que apunta el FSR0.

Si tenes mas dudas te las repsondo, si seguis con los ejemplos veo si es posible indicarte algo para que quede mas compacto por ejemplo.

------------------

EDIT: No se si el valor que se carga es correcto y perteneciente a la etiqueta, tal ves para acceder correctamente a la memoria de probramaa se necesite ponerle un 1 en el bit 7
Tal cual puse en el caso del Mensaje 3.
Esto por que se necesita ese bit en 1 para acceder a la memoria de programa. Hay que probar , ya que es nuevo para mi tambien.
« Última modificación: 09 de Noviembre de 2015, 12:37:20 por KILLERJC »

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2062
Re:PIC16F1707 Ejemplos básicos
« Respuesta #23 en: 09 de Noviembre de 2015, 12:05:11 »
Hola amigos.
Killerjc, que hace esta instruccion:  MOVLW   low(Tabla), low(tabla) es una etiqueta?no entiendo como haces el llamado a la tabla y la toma de datos de la misma  :? me lo podrias aclarar  :mrgreen:

Gracias

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:PIC16F1707 Ejemplos básicos
« Respuesta #24 en: 09 de Noviembre de 2015, 12:34:11 »
Tabla es una etiqueta. La etiqueta no es mas que una direccion. Ejemplo cuando haces:

Código: ASM
  1. Loop:
  2.    GOTO  Loop


Eso es un loop infinito, "Loop" representa la direccion. "Loop" no es una instruccion y no ocupa espacio de memoria. Entonces el compilador luego reemplaza eso. Suponete que ese GOTO ocupa la posicion de memoria 0x350 , entonces Loop vale/representa 0x350, el compilador luego cuando lo pasa a codigo maquina o opcode pasa eso a

Código: ASM
  1. GOTO 0x350

Recorda que el GOTO recibe un literal de hasta 11 bits ( no como la mayoria que solo acepta 8 bits )

Ahora con eso en mente, en el que el Label ( Etiqueta ) es simplemente la direccion. Cuando uno hace esto:

Código: ASM
  1. low(Loop)

el resultado es un numero igual a 0x50 y si hago el high() el numero es un 0x03, como eso es un numero, muevo ese numero a W y luego lo pongo en el registro FSR, asi indicando el comienzo.

Solo decirte que este PIC es "especial" y permite que el acceso indirecto pueda acceder a la memoria de programa, ya que para el acceso directo esta mapeado como una memoria lineal
Un error mio es poner los valores asi nomas

Código: ASM
  1. MOVLW   low(Tabla)              ;Cargo Valor inicial de la tabla
  2.         MOVWF   FSR0L
  3.         MOVLW   high(Tabla)
  4.         MOVWF   FSR0H

Eso es incorrecto. La direccion de memoria es correcta, pero la memoria mapeada comienza en 0x8000 para la flash.
Es decir En el acceso indirecto (FSR) la direccion 0x8000 corresponde al 0x0000 de la flash

Por eso mi edit diciendo que me habia equivocado. Y lo correcto seria

Código: ASM
  1. MOVLW   low(Tabla)           ;Cargo Valor inicial de la tabla
  2.         MOVWF   FSR0L
  3.         MOVLW   high(Tabla) | 0x80       ; Aca ademas de tomar la direccion alta de memoria le pongo un 1 al bit 7 asi acceder a la flash
  4.         MOVWF   FSR0H

Espero que esto resuelva tu pregunta y ademas aclare a Pinolillo el error que estuve cometiendo todo este tiempo en los anteriores post. Tal ves sea mejor editarlos a todos asi nadie termina confundido la primera ves que lo lee e intenta probarlos
EDITADO y corregido lo anterior
« Última modificación: 09 de Noviembre de 2015, 13:09:33 por KILLERJC »

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2062
Re:PIC16F1707 Ejemplos básicos
« Respuesta #25 en: 09 de Noviembre de 2015, 13:21:39 »
A ok, ahora si entiendo, no habia visto esas instruccion en asm de low(table) o high(tabla) de alli mi duda  :mrgreen:
Y bien claro lo del acceso a la memoria flash por medio de los FSR  :mrgreen:

Gracias


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:PIC16F1707 Ejemplos básicos
« Respuesta #26 en: 09 de Noviembre de 2015, 13:29:45 »
Lo que ahora me hiciste dudar es si es low(Tabla) y high(Tabla)

Y puede ser

Código: ASM
  1. MOVLW   LOW Tabla              ;Cargo Valor inicial de la tabla
  2.         MOVWF   FSR0L
  3.         MOVLW   HIGH (Tabla | 0x8000)
  4.         MOVWF   FSR0H

Esto me pasa por que se me mezclan todos los assemblers entre pic16/18/dsPIC

Desconectado Pinolillo16

  • PIC18
  • ****
  • Mensajes: 324
Re:PIC16F1707 Ejemplos básicos
« Respuesta #27 en: 09 de Noviembre de 2015, 21:06:03 »
Que tal KillerJC ya quede un poco confundido con lo de la memoria,  :shock: no me terminaba de quedar clara la dirección que me genera cada etiqueta, y en los ejemplos que me diste en MOVLW LOW(TABLA) no sabia si era literalmente hablando escribirlo. Y sí si fue así  :) es nuevo para mi todo esto pero es bastante interesante saber que puedes optimizar mucho código. Bueno la primera que modificación que hice fue esta:

Código: ASM
  1. INIT_NOKIA
  2.     MOVIW   FSR0++
  3.     CALL    COMANDO_SPI
  4.     ;MOVIW   k[FSR0]
  5.     ;BTFSS   STATUS,Z
  6.     ;GOTO    INIT_NOKIA
  7.      MOVIW   FSR0++
  8.      CALL    COMANDO_SPI
  9.      MOVIW   FSR0++
  10.      CALL    COMANDO_SPI
  11.      MOVIW   FSR0++
  12.      CALL    COMANDO_SPI
  13.      MOVIW   FSR0++
  14.     CALL    COMANDO_SPI
  15.     RETURN

Esto lo hice así porque al principio no me funcionaba bien esta instrucción:

Código: ASM
  1. MOVIW   k[FSR0]

Primero me genero un error, despues busque información sobre esa instrucción y lei que K es una constante que se suma a FSR0 cuando se mueve a W entonces al estar asignando cualquier numero no me funcionaba porque nunca se activaba mi bit Zero.

Finalmente el código de inicialización me quedo así y funciono perfectamente.
Código: ASM
  1. INIT_NOKIA
  2.     MOVIW   FSR0++
  3.     CALL    COMANDO_SPI
  4.     MOVIW   [FSR0]
  5.     BTFSS   STATUS,Z
  6.     GOTO    INIT_NOKIA
  7.     RETURN
  8.    
  9.    
  10.     INICIA_NOKIA: dt 0X21,0XCF,0X20,0X0C,0X00

Sustituyendolo por los MOVLW de configuración que tenia en un principio.

Desconectado Pinolillo16

  • PIC18
  • ****
  • Mensajes: 324
Re:PIC16F1707 Ejemplos básicos
« Respuesta #28 en: 09 de Noviembre de 2015, 21:14:37 »
Perdón y mis direcciones quedaron de la siguiente manera:
Código: ASM
  1. MOVLW   LOW(INICIA_NOKIA)
  2.     MOVWF   FSR0L
  3.     MOVLW   HIGH(INICIA_NOKIA)
  4.     MOVWF   FSR0H

Entonces con lo último que me dices, está bien mi codigo? Refiriendonos a la parte de las direcciones de la tabla?. Las instrucciones de las direcciones en tabla como lo acabamos de hacer si se han asignado de manera correcta se puede hacer esto con cualquier PIC? y por último no se si he encontrado el correcto data pero no encuentro las direcciones donde tengo los caracteres de esta LCD, no la he manejado mucho solo he realizado pequeños dibujitos en ella pero nunca mire que ya tenia los caracteres, no sera mucha molestia si me dices en que parte puedo encontrarlos?

Saludos y de nuevo muchas gracias.

Desconectado Pinolillo16

  • PIC18
  • ****
  • Mensajes: 324
Re:PIC16F1707 Ejemplos básicos
« Respuesta #29 en: 09 de Noviembre de 2015, 21:48:14 »
Bueno aca otra modificación del mismo programa ahora usando los FSRs para enviar los mensajes, en definitiva mucho mejor.  :-/
Código: ASM
  1. #INCLUDE "P16F1707.INC"
  2.  __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOREN_OFF & _CLKOUTEN_OFF
  3.  __CONFIG _CONFIG2, _WRT_OFF & _PPS1WAY_ON & _ZCDDIS_OFF & _PLLEN_ON & _STVREN_ON & _BORV_LO & _LPBOR_OFF & _LVP_OFF
  4.  
  5.     CBLOCK  0X020
  6.     RET
  7.     RET2
  8.     CONTADOR_BYTES
  9.     ENDC
  10.  
  11.     ORG     0X00
  12.     GOTO    CONFIGURA_PIC
  13.     ORG     0X04
  14.     RETFIE
  15.  CONFIGURA_PIC
  16.     BANKSEL OSCCON
  17.     MOVLW   B'11111011'
  18.     MOVWF   OSCCON
  19.     MOVLW   B'00011111'
  20.     MOVWF   OSCTUNE
  21.     BANKSEL PORTA
  22.     CLRF    PORTA
  23.     CLRF    PORTB
  24.     CLRF    PORTC
  25.     BANKSEL LATA
  26.     CLRF    LATA
  27.     CLRF    LATB
  28.     CLRF    LATC
  29.     BANKSEL ANSELA
  30.     CLRF    ANSELA
  31.     CLRF    ANSELB
  32.     CLRF    ANSELC
  33.     BANKSEL TRISA
  34.     CLRF    TRISA
  35.     CLRF    TRISB
  36.     CLRF    TRISC
  37. ; NOS POSICIONAMOS EN BANCO DE PPSLOCK
  38. ; PARA DELBLOQUEARLO
  39.     BANKSEL PPSLOCK
  40.     MOVLW   0X55
  41.     MOVWF   PPSLOCK
  42.     MOVLW   0XAA
  43.     MOVWF   PPSLOCK
  44.     BCF     PPSLOCK,PPSLOCKED
  45.     BANKSEL RC0PPS
  46.     MOVLW   B'00010010'
  47.     MOVWF   RC0PPS
  48.     MOVLW   B'00010000'
  49.     MOVWF   RC1PPS
  50. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  51.     BANKSEL PPSLOCK
  52.     MOVLW   0X55
  53.     MOVWF   PPSLOCK
  54.     MOVLW   0XAA
  55.     MOVWF   PPSLOCK
  56.     BSF     PPSLOCK,PPSLOCKED
  57. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  58.     BANKSEL SSP1CON1
  59.     MOVLW   B'00110000'
  60.     MOVWF   SSP1CON1
  61.     BANKSEL PORTB
  62.    
  63.     #DEFINE LCD_NOKIA   PORTC,2
  64.     #DEFINE RST_NOKIA   PORTC,3
  65.     #DEFINE DC_NOKIA    PORTC,4
  66.  
  67.     BSF     RST_NOKIA
  68.     BSF     LCD_NOKIA
  69.     CALL    INI_LCD_NOKIA
  70.  
  71.  PRINCIPAL
  72.     MOVLW   LOW(HOLA_MENSAJE)
  73.     MOVWF   FSR0L
  74.     MOVLW   HIGH(HOLA_MENSAJE)
  75.     MOVWF   FSR0H
  76.     MOVLW   .20
  77.     CALL    MENSAJE_X_BYTES
  78.     GOTO    PRINCIPAL
  79. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  80. MENSAJE_X_BYTES
  81.     MOVWF   CONTADOR_BYTES
  82. WRITING_LCD    
  83.     MOVIW   FSR0++
  84.     CALL    DATO_SPI
  85.     DECFSZ  CONTADOR_BYTES,F
  86.     GOTO    WRITING_LCD
  87.     RETURN
  88.    
  89.    
  90.    
  91. INI_LCD_NOKIA
  92.     BCF     RST_NOKIA
  93.     NOP
  94.     BSF     RST_NOKIA
  95.     ;CREAMOS UN RESET POR SOFTWARE DE LA LCD
  96.     MOVLW   LOW(INICIA_NOKIA)
  97.     MOVWF   FSR0L
  98.     MOVLW   HIGH(INICIA_NOKIA)
  99.     MOVWF   FSR0H
  100. INIT_NOKIA
  101.     MOVIW   FSR0++
  102.     CALL    COMANDO_SPI
  103.     MOVIW   [FSR0]
  104.     BTFSS   STATUS,Z
  105.     GOTO    INIT_NOKIA
  106.     RETURN
  107. SET_Y
  108.     ADDLW   B'01000000'
  109.     CALL    COMANDO_SPI
  110.     RETURN
  111. SET_X
  112.     ADDLW   B'10000000'
  113.     CALL    COMANDO_SPI
  114.     RETURN
  115.    
  116.    
  117.     INICIA_NOKIA: dt 0X21,0XCF,0X20,0X0C,0X00
  118.    
  119.     HOLA_MENSAJE: dt 0XFE,0X10,0X10,0XFE,0X00,0X7C,0X82,0X82,0X7C,0X00,0XFE,0X80,0X80,0X80,0X00,0XFC,0X12,0X12,0XFC,0X00;A
  120.  
  121.  
  122.  
  123. DATO_SPI
  124.     BSF     DC_NOKIA
  125.     BCF     LCD_NOKIA
  126.     BANKSEL SSP1BUF
  127.     MOVWF   SSP1BUF
  128.     BANKSEL PIR1
  129.     BCF     PIR1,SSP1IF
  130. WSPI
  131.     BTFSS   PIR1,SSP1IF
  132.     GOTO    WSPI
  133.     BCF     PIR1,SSP1IF
  134.     BANKSEL PORTA
  135.     BSF     LCD_NOKIA
  136.     RETURN
  137. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  138. COMANDO_SPI
  139.     BCF     DC_NOKIA
  140.     BCF     LCD_NOKIA
  141.     BANKSEL SSP1BUF
  142.     MOVWF   SSP1BUF
  143.     BANKSEL PIR1
  144.     BCF     PIR1,SSP1IF
  145. WSPIC
  146.     BTFSS   PIR1,SSP1IF
  147.     GOTO    WSPIC
  148.     BCF     PIR1,SSP1IF
  149.     BANKSEL PORTA
  150.     BSF     LCD_NOKIA
  151.     RETURN
  152. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  153.  
  154.    
  155. RETARDO
  156.     MOVLW   0XFF
  157.     MOVWF   RET
  158.     MOVWF   RET2
  159. ESP
  160.     DECFSZ  RET,F
  161.     GOTO    ESP
  162.     MOVLW   0XFF
  163.     MOVWF   RET
  164.     DECFSZ  RET2,F
  165.     GOTO    ESP
  166.     RETURN
  167.     END


 

anything