Resolver problemas con tablas 6 bits.

Iniciado por Meta, 3 Septiembre 2010, 07:32 AM

0 Miembros y 4 Visitantes están viendo este tema.

Tokes

Hola, Meta:

¿Estas seguro que el mensaje guardado en la EEPROM 24lc256 termina en 0 (Me refiero al valor 0 y no al ascii '0')?

La rutina de mensaje a LCD busca el valor 0 para finalizar.

          Nos vemos.

Meta

#21
Hello:

Segurísimo, el 0 lo he puesto en la parte hexadecimal (0x00), no en la parte ASCII (0) del winpic800.

La parte modificada de esta librería. Ya que se me retaban los mensajes. Aunque no lo hay amodificado se comporta igual.

Código (asm) [Seleccionar]
;**************************** Librería "M24LC256.INC" ***********************************
;

;
; Estas subrutinas permiten realizar las tareas de manejo de la memoria EEPROM serie
; 24LC256 que transmite y recibe la información vía serie a través de un bus I2C.
;
; Subrutina "M24LC256_InicializaEscritura" ----------------------------------------------
;
; Prepara la memoria para iniciar su escritura a partir de la posición de memoria fijada
; por los registros:
; - (M24LC256_AddressHigh), indica el número del bloque o página de memoria a escribir.
; - (M24LC256_AddressLow), indica posición a escribir dentro del bloque.

CBLOCK
M24LC256_AddressHigh ; Guarda el valor de la dirección de memoria a
M24LC256_AddressLow ; escribir o leer.
M24LC256_Dato
ENDC
;
M24LC256_DIR_ESCRITURA EQU b'10100000'; Dirección de la memoria 24LC256 para
M24LC256_DIR_LECTURA EQU b'10100001'; escritura y lectura respectivamente.

M24LC256_InicializaEscritura
call I2C_EnviaStart ; Envía condición de Start.
movlw M24LC256_DIR_ESCRITURA ; Envía dirección de escritura del
call I2C_EnviaByte ; esclavo.
movf M24LC256_AddressHigh,W ; A partir de la dirección apuntada por los
call I2C_EnviaByte ; registros M24LC256_AddressHigh y
movf M24LC256_AddressLow,W ; M24LC256_AddressLow.
call I2C_EnviaByte
return

; Subrutina "M24LC256_InicializaLectura" ------------------------------------------------
;
; Prepara la memoria para iniciar su lectura a partir de la posición de memoria fijada
; por los registros:
; - (M24LC256_AddressHigh), indica el número del bloque o página de memoria a leer.
; - (M24LC256_AddressLow), indica posición a escribir dentro del bloque.

M24LC256_InicializaLectura
bcf I2C_UltimoByteLeer ; Todavía no ha comenzado a leer ningún dato.
call I2C_EnviaStart ; Envía condición de Start.
movlw M24LC256_DIR_ESCRITURA ; Envía dirección de escritura del
call I2C_EnviaByte ; esclavo.
movf M24LC256_AddressHigh,W ; A partir de la dirección apuntada por los
call I2C_EnviaByte ; registros M24LC256_AddressHigh y
movf M24LC256_AddressLow,W ; M24LC256_AddressLow.
call I2C_EnviaByte
call I2C_EnviaStop
;
call I2C_EnviaStart ; Envía condición de Start.
movlw M24LC256_DIR_LECTURA ; Indica a la memoria 24LC256 que va a
call I2C_EnviaByte ; proceder a la lectura.
return

; Subrutina "M24LC256_Mensaje_a_LCD" ----------------------------------------------------
;
; Lee el mensaje grabado en la memoria 24LC256 y lo visualiza en la pantalla del módulo LCD.
; En el registro de trabajo W se introduce la página de la memoria a partir de cuya primera
; posición se va a leer. La lectura termina cuando encuentre el código 0x00. Así por ejemplo,
; si (W)=2Fh lee el mensaje que comienza en la posición 0 de la página 2Fh de la memoria,
; que es la posición 2F00h absoluta.
;
CBLOCK
M24LC256_ValorCaracter ; Valor ASCII del carácter leído.
ENDC

M24LC256_Mensaje_a_LCD
movwf M24LC256_AddressHigh ; Apunta al inicio de la página correspondiente.
clrf M24LC256_AddressLow
call M24LC256_InicializaLectura
M24LC256_LeeOtroByte
call I2C_LeeByte ; Lee la memoria 24LC256.
movwf M24LC256_ValorCaracter ; Guarda el valor de carácter.
movf M24LC256_ValorCaracter,F ; Lo único que hace es posicionar flag Z. En caso
btfsc STATUS,Z ; que sea "0x00", que es código indicador final
goto M24LC256_FinMensaje ; del mensaje, sale de la subrutina.
movf M24LC256_ValorCaracter,W ; Recupera el valor leído.
call LCD_Caracter ; Lo visualiza en la pantalla del LCD.
incf M24LC256_AddressLow,F ; Apunta a la siguiente posición.
goto M24LC256_LeeOtroByte
M24LC256_FinMensaje
call M24LC256_FinalizaLectura
return

; Subrutina "M24LC256_FinalizaLectura" ------------------------------------------------
;
; Activa el bit I2C_UltimoByteLeer para que la subrutina I2C_LeeByte ponga en alta
; impedancia la línea SDA y pueda ejecutarse posteriormente la condición de Start o Stop
; que fija el protocolo del bus I2C.

M24LC256_FinalizaLectura
bsf I2C_UltimoByteLeer ; Con estas dos instrucciones se pone en
call I2C_LeeByte ; alta impedancia la línea SDA. No importa el
call I2C_EnviaStop ; resultado de la lectura realizada.
return

; Subrutina "M24LC256_Mensaje_a_LCD" ----------------------------------------------------
;
; Lee un mensaje grabado en la memoria 24LC256 y lo visualiza por el módulo LCD. En caso que
; sea más largo que la longitud de la pantalla se desplaza hacia la izquierda con sensación
; de movimiento. En el registro de trabajo W se introduce la página de la memoria a partir
; de cuya primera posición va a leer. La visualización termina cuando encuentre el código
; 0x00. Así por ejemplo si (W)= 2Fh lee el mensaje que comienza en la posición 0 de la
; página 2Fh de la memoria, que es la posición 2F00h absoluta.
;
CBLOCK
; M24LC256_ValorCaracter ; Valor ASCII del carácter leído.
M24LC256_CursorPosicion
ENDC

;M24LC256_Mensaje_a_LCD
bcf I2C_UltimoByteLeer
movwf M24LC256_AddressHigh ; Apunta al inicio de la página correspondiente.
clrf M24LC256_AddressLow
call M24LC256_InicializaLectura
M24LC256_PrimeraPosicion
clrf M24LC256_CursorPosicion ; El cursor en la posición 0 de la línea.
call LCD_Borra ; Se sitúa en la primera posición de la línea 1 y
M24LC256_VisualizaCaracter ; borra la pantalla.
movlw LCD_CaracteresPorLinea ; ¿Ha llegado a final de línea?
subwf M24LC256_CursorPosicion,W
btfss STATUS,C
goto M24LC256_NoEsFinalLinea
M24LC256_EsFinalLinea
call Retardo_200ms ; Lo mantiene visualizado durante este tiempo.
call Retardo_200ms
call M24LC256_FinalizaLectura
incf M24LC256_AddressLow,F
call M24LC256_InicializaLectura
goto M24LC256_PrimeraPosicion
M24LC256_NoEsFinalLinea
call I2C_LeeByte ; Obtiene el ASCII del carácter apuntado.
movwf M24LC256_ValorCaracter ; Guarda el valor de carácter.
movf M24LC256_ValorCaracter,F ; Lo único que hace es posicionar flag Z. En caso
btfsc STATUS,Z ; que sea "0x00", que es código indicador final
goto M24LC256_FinMensaje ; de mensaje, sale fuera.
M24LC256_NoUltimoCaracter
call LCD_Caracter ; Visualiza el carácter ASCII leído.
incf M24LC256_CursorPosicion,F ; Contabiliza el incremento de posición del
; cursor en la pantalla.
goto M24LC256_VisualizaCaracter ; Vuelve a visualizar el siguiente carácter
;M24LC256_FinMensaje ; de la línea.
; call M24LC256_FinalizaLectura
; return

; -----------------------------------------------------------------------------------------

Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Tokes

Meta:

Acabo de probar tu código y me funciona bien.

Asegúrate de dar click en Debug > Reset Persistent Model Data para que se borre lo que tenía la 24lc256 y se cargue el nuevo archivo .bin

             Hasta pronto.

Meta

Hola:

Lo hago siempre tal como me enseñaste. (Contigo se aprende mucho).

Debe verse el código siempre en la primera línea del LCD. La cosa rara que hace es que al princpio se ve en la primera línea el mensaje, luego salta a la tercera, luego desplazado a la segunda y al final a la cuarta y vuelta a empezar pero con desplazamiento.



Sólo debe mostrarse en la primera línea "Hola amigo del foro", 0x00 (con su cero al final en hex).

Otra cosa que pasa, que cada vez le cuesta leer y tarda más en verse en el LCD. Ya que veo, hace un chequeo cada dos por tres en el puerto de entrada PORTC para detectar algún cambio y cambie de configuración. Como no cambia simpre lee el estado actual varias veces, pero no debería hacer cosas raras en el LCD.

¿Te voy a pasar el proyecto completo  otra vez por e-mail?

Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Tokes

Meta:

Envíame el archivo completo.

              Nos vemos.

Meta

#25
Enviado.

Edito:

En la librería se usa el LCD a 16x2, en mi caso el 20x4. Quizás no sea igual la configuración. Me lo confirmas por si acaso.

Código (asm) [Seleccionar]
LCD_2Lineas4Bits5x7 ; Define la pantalla de 2 líneas, con caracteres
movlw b'00101000' ; de 5x7 puntos y conexión al PIC mediante bus de
; goto LCD_EnviaComando ; 4 bits.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Meta

Esto de usar la EEPROM externas para cambiar de mensajes de avisos rápidamente no vale la pena. ¿Verdad?

A lo mejor es porque es muy lento.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Tokes

#27
Hola, Meta:

En verdad que esta vez sí tenías muchos errores. Te mencionaré unos pocos:

1. La rutina para enviar mensaje al LCD nunca borraba la pantalla. Por eso el mensaje ocupaba todo el LCD.

Aquí te pongo la subrutina corregida. Nota que la única diferencia es que esta vez sí se borra la pantalla.

Código (asm) [Seleccionar]
M24LC256_Mensaje_a_LCD
movwf M24LC256_AddressHigh ; Apunta al inicio de la página correspondiente.
clrf M24LC256_AddressLow
call M24LC256_InicializaLectura
call LCD_Borra    ; Borra la pantalla.
M24LC256_LeeOtroByte
call I2C_LeeByte ; Lee la memoria 24LC256.
movwf M24LC256_ValorCaracter ; Guarda el valor de carácter.
movf M24LC256_ValorCaracter,F ; Lo único que hace es posicionar flag Z. En caso
btfsc STATUS,Z ; que sea "0x00", que es código indicador final
goto M24LC256_FinMensaje ; del mensaje, sale de la subrutina.
movf M24LC256_ValorCaracter,W ; Recupera el valor leído.
call LCD_Caracter ; Lo visualiza en la pantalla del LCD.
incf M24LC256_AddressLow,F ; Apunta a la siguiente posición.
goto M24LC256_LeeOtroByte
M24LC256_FinMensaje
call M24LC256_FinalizaLectura
return


2. En tu programa principal tienes un bucle infinito:

Código (asm) [Seleccionar]
Principal
movlw PAGINA_00
call M24LC256_Mensaje_a_LCD
call Retardo_2s
goto Principal


Si no lo quitas jamás vas a llegar a la zona de configuraciones (mejor, porque en la zona donde están las configuraciones tienes el error más grande).

3. En tu código tienes esto:

Código (asm) [Seleccionar]
movf   PORTC,W
  andlw   b'00111111'
  addwf   PCL,F
  call      Configuracion


Eso está bastante mal, porque la instrucción addwf   PCL,F es el encabezado de las configuraciones. Esa instrucción debería estar dentro de la subrutina Configuracion.

Código (asm) [Seleccionar]
movf   PORTC,W
  andlw   b'00111111'
  call      Configuracion


Y dentro de la rutina Configuracion:

Código (asm) [Seleccionar]
Configuracion
addwf PCL,F   ; Aquí debe estar la instrucción addwf PCL,F.
goto Configuracion0 ; 0 0 0 0 0 0
goto Configuracion1 ; 0 0 0 0 0 1
goto Configuracion2 ; 0 0 0 0 1 0
                         .
                         .
                         .


4. Tu rutina Configuración nunca retorna (nunca ejecuta la instrucción return).

Lo que sucede es que en tu rutina Configuración pones instrucciones de brinco:

   goto   Configuracion0
   goto   Configuracíon1
         .
         .

y en las respectivas zonas de códigos ejecutas un goto al programa principal.

Código (asm) [Seleccionar]
Configuracion1
               goto ActivaSalida
                      .
                      .
                      .
         ActivaSalida
               goto        Principal


Nunca ejecutas Return.

5. Por estética, es mejor que todos los elementos de una rutina estén todos en un mismo archivo. ¿Qué es lo que sucede con tu código?

La rutina Configuracion hace brincos (goto) hacia instrucciones que se encuentran en tu programa principal. Lo mejor es que esas instrucciones se encuentren también dentro del archivo de la subrutina de Cofiguracion.

En fín, te mandé al correo el programa corregido. Este sí debes revisarlo muy bien, porque le corregí muchas cosas.

Sigue echándole muchas ganas. Yo también empecé así. Me ocurrió casi de todo. He cometido casi todos los errores que se pueden cometer en ensamblador y es por eso que he podido resolver los tuyos.

               Saludos.

Meta

Cita de: Tokes en  9 Septiembre 2010, 18:22 PM
Hola, Meta:

En verdad que esta vez sí tenías muchos errores. Te mencionaré unos pocos:

1. La rutina para enviar mensaje al LCD nunca borraba la pantalla. Por eso el mensaje ocupaba todo el LCD.

Aquí te pongo la subrutina corregida. Nota que la única diferencia es que esta vez sí se borra la pantalla.

Código (asm) [Seleccionar]
M24LC256_Mensaje_a_LCD
movwf M24LC256_AddressHigh ; Apunta al inicio de la página correspondiente.
clrf M24LC256_AddressLow
call M24LC256_InicializaLectura
call LCD_Borra    ; Borra la pantalla.
M24LC256_LeeOtroByte
call I2C_LeeByte ; Lee la memoria 24LC256.
movwf M24LC256_ValorCaracter ; Guarda el valor de carácter.
movf M24LC256_ValorCaracter,F ; Lo único que hace es posicionar flag Z. En caso
btfsc STATUS,Z ; que sea "0x00", que es código indicador final
goto M24LC256_FinMensaje ; del mensaje, sale de la subrutina.
movf M24LC256_ValorCaracter,W ; Recupera el valor leído.
call LCD_Caracter ; Lo visualiza en la pantalla del LCD.
incf M24LC256_AddressLow,F ; Apunta a la siguiente posición.
goto M24LC256_LeeOtroByte
M24LC256_FinMensaje
call M24LC256_FinalizaLectura
return


Si lo he hecho en el programa principal y lo he quitado, lo has hecho aquí. Hay que tener en cuenta una cosa. El LDC es de 20x4. Uso las 4 líneas independiente, es decir. En una goto de configuración puede salir un mensaje en la línea 1. Luego otra en la líena 4. Si borra el LCD completo, sólo se ve el último mensaje. Se tiene que ver las 4 líneas independiente. Para mi hay que usar la rutina "LCD_LineaEnBlanco", puede que no sea la adecuata, pero lo nombro por si acaso, debo hacer más pruebas hasta que me salga.

2. En tu programa principal tienes un bucle infinito:

Código (asm) [Seleccionar]
Principal
movlw PAGINA_00
call M24LC256_Mensaje_a_LCD
call Retardo_2s
goto Principal


Si no lo quitas jamás vas a llegar a la zona de configuraciones (mejor, porque en la zona donde están las configuraciones tienes el error más grande).

Dejé ese bucle infinito adrede para hacer pruebas, lo que me olvidé quitarlos con ;.


3. En tu código tienes esto:

Código (asm) [Seleccionar]
movf   PORTC,W
  andlw   b'00111111'
  addwf   PCL,F
  call      Configuracion


Eso está bastante mal, porque la instrucción addwf   PCL,F es el encabezado de las configuraciones. Esa instrucción debería estar dentro de la subrutina Configuracion.

Código (asm) [Seleccionar]
movf   PORTC,W
  andlw   b'00111111'
  call      Configuracion


Y dentro de la rutina Configuracion:

Código (asm) [Seleccionar]
Configuracion
addwf PCL,F   ; Aquí debe estar la instrucción addwf PCL,F.
goto Configuracion0 ; 0 0 0 0 0 0
goto Configuracion1 ; 0 0 0 0 0 1
goto Configuracion2 ; 0 0 0 0 1 0
                         .
                         .
                         .


Lo tendré en cuenta, sólo quería ahorrar espacio, mejor lo pongo en el programa principal otra vez.

4. Tu rutina Configuración nunca retorna (nunca ejecuta la instrucción return).

Lo que sucede es que en tu rutina Configuración pones instrucciones de brinco:

   goto   Configuracion0
   goto   Configuracíon1
         .
         .

y en las respectivas zonas de códigos ejecutas un goto al programa principal.

Código (asm) [Seleccionar]
Configuracion1
              goto ActivaSalida
                      .
                      .
                      .
         ActivaSalida
               goto        Principal


Nunca ejecutas Return.

En los ejemplos del libro www.pic16f84a.org se usa sin el return. Los return se usa en subrutinas, es más aconsejable para que se sepa que si tienes un return, tienes un subrutina que el que lo llama es "call".

En realidad no hace falta los return, si hace falta se los pondré, ya que crees que hay que ponerlos. Recuerdo que en el libro jamás se usa un return en este tipo de tablas.


5. Por estética, es mejor que todos los elementos de una rutina estén todos en un mismo archivo. ¿Qué es lo que sucede con tu código?

La rutina Configuracion hace brincos (goto) hacia instrucciones que se encuentran en tu programa principal. Lo mejor es que esas instrucciones se encuentren también dentro del archivo de la subrutina de Cofiguracion.

En fín, te mandé al correo el programa corregido. Este sí debes revisarlo muy bien, porque le corregí muchas cosas.

Sigue echándole muchas ganas. Yo también empecé así. Me ocurrió casi de todo. He cometido casi todos los errores que se pueden cometer en ensamblador y es por eso que he podido resolver los tuyos.

               Saludos.

Lo voy a meter todo otra vez en el archivo principal. Los gotos. ;)

Gracias por la ayuda.

Hice cambios, puse los gotos otra vez en la primera página. Hice cosas que tocando el RC0 a 1, para que se muestre que el mensje 1 se vea en la primera línea, y si pulsas el RC0 otra vez, se muestre en la tercera línea del LCD pero se ve siempre en la primera.

Recuerda que cada entrade del LCD puede haber mensajes a la vez en diferentes líneas, no que se borre toda la pantalla y que se vea sola una línea por cada actualización. Esto de la EEPROM y asm es un poco infierno.

Gracias de nuevo por tu tiempo.
Te envío otra vez.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Tokes

#29
Hola, Meta:

Bien, para arreglar tus problemas con el LCD vamos a hacer lo siguiente:

CitarRecuerda que cada entrade del LCD puede haber mensajes a la vez en diferentes líneas, no que se borre toda la pantalla y que se vea sola una línea por cada actualización. Esto de la EEPROM y asm es un poco infierno.

Para solucionar eso debes quitar de la subruitna "M24LC256_Mensaje_a_LCD" la instrucción que borra la pantalla (call   LCD_borra).

Bueno, hasta ahí se soluciona el problema de que se borre un mensaje al poner otro.

Ahora, debes tomar en cuenta otro aspecto importantísimo: para visualizar un mensaje en una línea determinada debes:

1. Colocar el cursor al principio de la línea correspondiente.
2. Visualizar espacios en blanco hasta que se llene la línea (es decir, borrar la línea).
3. Regresar el cursor al principio de esa línea.

Aquí te dejo las funciones que hacen eso para cada una de las líneas del LCD.

Código (asm) [Seleccionar]

LCD_Linea1EnBlanco
call LCD_Linea1   ; Sitúa el cursor al principio de la línea 1.
call LCD_LineaEnBlanco  ; Borra la línea.
call LCD_Linea1   ; Regresa el cursor al principio de la línea.
return

LCD_Linea2EnBlanco    ; Similar que la anterior.
call LCD_Linea2
call LCD_LineaEnBlanco
call LCD_Linea2
return

LCD_Linea3EnBlanco   ; Similar que la anterior.
call LCD_Linea3
call LCD_LineaEnBlanco
call LCD_Linea3
return

LCD_Linea4EnBlanco   ; Similar que la anterior.
call LCD_Linea4
call LCD_LineaEnBlanco
call LCD_Linea4
return


Esas rutinas pégalas en tu archivo "LCD_4BIT.INC".

Siempre que quieras visualizar un mensaje en una línea determinada deberás llamar esas rutinas. Por ejemplo, en el caso de la Configuración0, sería algo más o menos así:

Código (asm) [Seleccionar]

Configuracion0
    call LCD_Linea1EnBlanco ; Borra la línea 1 y se sitúa al principio de dicha línea.
movlw PAGINA_00   ; Lee a partir de la dirección 00 de esta página
call M24LC256_Mensaje_a_LCD ; de la memoria.
call Retardo_2s
goto ActivaSalida


Hazlo así y te debería funcionar. Espero tus comentarios.

                ¡¡¡Buen día!!!