torres.electronico
Well-known-Alfil
Introducción
Para quienes ya han estado experimentando con proyectos microcontrolados , y/o recién se están introduciendo en este mundo apasionante de los microcontroladores, se han dado cuenta que llega un momento dado que nuestra sed por aprender más, debe ser saciada con más proyectos, con más ejemplos… Con más conocimientos para simplificar.
Dejando de lado el famoso “Hola mundo” con un display LCD 16x2 o encender un simple led, en esta ocasión, vamos a ver cómo controlar e implementar los “display gráficos” NOKIA 3310 – 5110 para que nuestros proyectos queden más vistosos y ganen más vida aún.
Conociendo el GLCD
Esta es una pantalla LCD GRÁFICA (GLCD) con resolución matriz de 84x48 puntos, caracteres en blanco y negro, interfaz SPI con una velocidad de datos máxima de 4 Mbit /s. , y como vimos en el articulo anteriormente del display LCD16x2 (que usa un controlador interno HD44780), este display también contiene internamente un controlador, que es el PCD8544.
La alimentación de este dispositivo puede variar según la marca y modelo de fabricantes; La hoja de datos del controlador, comenta que la Tensión de alimentación, ronda los + 2.7V y + 3.6V; Pero en la práctica, el modulo completo que estoy trabajando, funcionó correctamente con 4.2v (En tensiones inferiores, el contraste es muy bajo y apenas pueden ver los caracteres).
Un poco de teoría sobre cómo trabaja el controlador de la pantalla
Inmediatamente después de encender nuestra pantalla, el contenido de los registros de este, contendrán valores indefinidos, por lo que es necesario generar un reset poniendo en estado bajo el pin “Reset” (RST).
Poniendo el pin /RES a nivel bajo durante un tiempo limitado (máx. 100mS) generamos el reset para poner a cero los registros del LCD, pero la RAM seguirá conteniendo datos indefinidos por lo tanto, después habrá que pintar toda la RAM a cero, para que el LCD quede limpio; Es necesario asegurarse de que todos los pasos se tengan en cuenta, ya que implementar mal el control de los pines, al poner en alto algunos pines específicos en un momento dado que no es el correcto, podemos dañar el controlador, y este no tiene reparación alguna.
Después del reset, ponemos en estado alto el PIN RST, y el controlador está listo para trabajar y grabar la secuencia de comandos que viene... Ahora mandaremos los comandos de puesta en marcha y configuración.
Function Set: Con el tipo de direccionamiento que queremos usar (Vertical u Horizontal), Chip activo, y juego de instrucciones básico o avanzado, seguido de los ajustes de coeficiente de temperatura, ajuste de Vop y BIAS. Todo esto según especificaciones en el datasheet.
El pin encargado de establecer el modo de trabajo del controlador, es el pin “Data Comand Select” (DC);
O sea, para establecer si esta en modo escritura (data) o lectura (comand), se pone en nivel bajo o alto este pin (0=comand – 1=data).
Al poner el PIN DC en estado bajo, habilitamos el controlador en modo lectura y se queda a la espera de los datos que afectaran los registros comandos para el control del display.
Estos datos son enviados mediante el protocolo SPI estándar:
Habilitamos SPI poniendo en bajo el PIN SCE, y se hace recepción de los bits de datos por el PIN SDIN. El PIN SDIN o DN, también es conocido como MOSI (Master Out Slave IN).
El PIN SCE o CS (Chip Select), debe activarse para indicarle al dispositivo que se le van a enviar datos. Para los que ya conocen el protocolo SPI y han trabajado con otros dispositivos, SCE / CS, también es conocido como SS (Slave Select).
La transferencia de datos, se lleva a cabo en el flanco ascendente del PIN SCLK, o sea, este pin es el que rige la comunicación y transferencia de datos.
Viéndolo de otra manera, la secuencia seria así:
Con todo esto el LCD ya está listo para ser usado, pero nos queda aun una cosa por hacer.. y es borrar la RAM del display que contiene datos aleatorios, así que deberemos direccionar toda la memoria mandando 0x00 en el modo adecuado.
Registros de Control
Toda la pantalla se divide en bancos (alto 8 bits de longitud y ancho de la pantalla 48px). El manejo de esta es similar al de una matriz ya que la salida de video, corresponde a una unidad (pixel negro).
Variando los bytes de la pantalla de vídeo, podemos cambiar la imagen; O sea, para mostrar la información en la pantalla, es necesario poner el cursor sobre el banco deseado e imprimir el punto. Dicho en otras maneras, seleccionamos las coordenadas X e Y, y dibujamos el punto.
Dicho de una manera más práctica. Esto seria así:
LCD_GotoXY:
LOW DC
LcdData= %01000000 | PosY: GOSUB LCD_ByteOut ' 0х40+numero de banco (0…5)
LcdData= %10000000 | PosX: GOSUB LCD_ByteOut ' 0х80+coordenanda X (0…83)
RETURN
Invirtiendo el estado de DC, pasamos el display a modo de visualización
Cada columna (Xi) de una línea determinada (Yj) corresponde a 1 byte de memoria (Figura superior), el píxel superior corresponde al bit menos significativo (LSB). Seleccionamos el número de fila y columna, colocamos el valor de los datos de estas en formato byte, y se muestra la columna 8x1. Después de un byte de escritura incrementa automáticamente la dirección del puntero de la columna. Por lo tanto, el siguiente byte se muestra en la misma línea, pero con un desplazamiento de 1 pixel a la derecha.
Cuando la impresión llegue al final de la recta:
y=yi
x = 83
Salta a la siguiente línea:
y = yi + 1
x = 0
Tener en cuenta que si el puntero se encuentra ubicado casi al final de la recta, y los bits que tenemos superan las posiciones que quedan libres, estos saltarán automáticamente a la línea siguiente.
Lo que vimos anteriormente, es válido cuando el bit de direccionamiento es cero V = 0.
Cuando el bit de direccionamiento es uno V = 1, la impresión se produce de manera similar, pero cada byte subsiguiente se muestra con un desplazamiento de 8 píxeles hacia abajo.
Pasemos a la práctica con PBP… Vamos a ver como se inicializa nuestro GLCD
Resumiendo, como verán, la inicialización de la pantalla LCD no es complicada. Al iniciar el dispositivo, solo tenemos que implementar la rutina LCD_Init tan solo una vez, y luego, seguir con el resto del cuerpo del programa sin necesidad de volver a implementarlo.
La rutina LCD_Clear, se implementará si usted tiene que limpiar la pantalla de las entradas anteriores.
Las subrutinas LCD_GotoXY y LCD_ByteOut, serán las más implementadas en el resto del programa, ya que estas son las rutinas para cambiar de fila, columna, parte del procedimiento de impresión, etc. Ahora veamos lo que más nos interesa; Imprimir el primer “HOLA MUNDO” en la pantalla.
Imprimir en pantalla
Un poco de teoría nuevamente... A diferencia de los display alfa numéricos 16x2 con controlador HD44780, la pantalla del Nokia 3310 es gráfica y no contiene una biblioteca de símbolos. Esto significa que todos los elementos (números, letras) tienen que crearlos para luego imprimirlos (Algo similar a lo ya expuesto en el artículo de los display lcd16x2, creación de caracteres CGRAM). Por un lado es bueno (se pueden crear bibliotecas de símbolos), pero por otro lado, el problema radica en que esta acción toma una gran cantidad de memoria del microcontrolador.
El método de creación de caracteres es simple; Tomando como dato que el tamaño completo de cada matriz de carácter es de 5x8 pixel. Hacemos la tabla, y completamos con ceros y unos cada espacio, donde el uno marca el pixel color negro, y cero en blanco.
En el siguiente ejemplo, se ve la creación del carácter “A”. Una vez que tenemos la tabla completa, tomamos el número BINARIO y lo convertimos en HEX.
Recuerden que para escribir el numero binario, debemos escribirlo del byte menor al más alto; Veámoslo con un ejemplo $ 7E = St.b. 0111 Ml.b. 1110 = 0111111
En la practica, para hacer esta acción en PBP, el carácter generado se guarda de la siguiente manera:
'.............................................................. DEC | Chr | HEX
Data $ 7E, $ 11, $ 11, $ 11, $ 7E, $ 00 '65 | A | 41
'Data registra en EEPROM cinco símbolos del caracteres en un byte, comenzando en la posición de memoria 'cero. Al final de una columna, se necesita separar los caracteres uno de otro con el signo $ y 00.
Primer ejemplo práctico
En el siguiente ejemplo, lo que vamos a realizar, es imprimir tan solo un carácter; Recuerden que el carácter dibujado/creado, se almacena en la eeprom mediante el comando DATA.
Excelente, si ya estamos en estas líneas, tomo por superado lo visto anteriormente… Ahora vamos a implementar una tabla con más gráficos y vamos a imprimir un par de símbolos estáticos en la pantalla
Como pudimos ver en el ejemplo anterior, generamos una tabla con los distintos caracteres generados; Cada carácter, ocupa 5 espacios de cada posición; Disculpen que sea reiterativo, pero hay cosas que es mejor repetirlas varias veces para que queden en claro… Bien, si la tabla la organizamos de tal manera de recordar en que posición de ésta está cada carácter, fíjense en el programa que asignando a la variable “char” el valor de la posición y llamando la rutina “PrintChar”, leemos la posición de la eeprom e imprimimos el carácter.
Ahora… ¿como las posicione automáticamente en la pantalla?
Partiendo de las líneas donde establecemos como inicio del puntero en los ejes X e Y con un agregado en cada eje (+17 para el eje X y +40 para el eje Y), esto significa que de las coordenadas 0-0, estaremos desplazados 17 pixeles para un lado, y 40 pixeles para el otro.
Lcddata = %10100000 + 17 ' cursor X en posicion 17
call PrintCtrlLcd
Lcddata = %01000010 +40 ' cursor Y en posicion 40
call PrintCtrlLcd
Si queremos que inicie desde la posicion 1-1 (esquina superior izquierda), tendríamos que colocar los siguientes valores
Lcddata = %01000000+1 ' cursor X en posición 1
call PrintCtrlLcd
Lcddata = %01000000 +1 ' cursor Y en posición 1
call PrintCtrlLcd
Bien, hay muchas maneras de desplazar el puntero e imprimir cada carácter; Eso está en el ingenio de cada programador; En mi caso, para poder no repetir líneas de programación cada vez que quiero desplazar posiciones e imprimir cada carácter, implemente las siguientes líneas:
PrintChar:
offset = Char * 5
for a = 1 to 5
read offset, LcdData
call PrintDataLcd
offset = offset + 1
next a
LcdData = 0
call PrintDataLcd
return
Básicamente, la idea fue partir de la posición del puntero, e ir sumando saltos de 5 pixeles (que es la anchura de cada carácter) para luego imprimir…
Veamos un último ejemplo para ir cerrando la idea de cómo manejar / controlar estos display gráficos…
Hasta acá, hemos visto como inicializar el display gráfico, vimos como crear, generar un carácter, vimos como crear una tabla con los caracteres, vimos como imprimir estos carácter…etc.
Ahora vamos a ver cómo hacer un programa, interactuar con las variables del programa e imprimir el valor de estas variables, para que pasemos un paso más adelante, y dejemos atrás el “hola mundo” estático al que estamos acostumbrados desde el inicio de este articulo…
Como el pic 16F628 no tiene ADC, para realizar el próximo ejemplo, vamos a implementar un PIC 16F876A y armaremos un simple monitor de tensión y corriente.
Como carga, para poder simular nuestro proyecto, notarán que implementé tres motores en paralelo con sus respectivos switch para habilitar y así poder sumar o decrementar peso a la carga.
Antes que nada, veamos un poco que nos ofrece PicBasic Pro, para realizar nuestro programa, ya que nosotros ahora tenemos que llevar el valor binario de la variable, al formato decimal.
Cuando nos vemos en la necesidad de hacer una conversión de Binario a Decimal, picbasic pro incluye un operador que puede ser empleado para este propósito...
El operador DIG (mal llamado comando); El operador DIG devuelve el valor de un dígito decimal. Simplemente se le indica el número de dígito a conocer ( 0 - 4 , siendo 0 el primero de la derecha) y ya está.
Dicho de otra manera, para desglosar el valor binario y extraer el valor deseado, hay que especificar con el número de dígito siguiente de la variable a la que vas a extraer el dígito... Suponiendo que solo quieres que extraiga el segundo valor, tienes que poner el bit 1 lógicamente, y te funcionara, si quieres el tercer valor tienes que poner el bit2 y así sucesivamente.
Acordate que el operador funciona de la siguiente forma :
Variable = DIG Value , Digit number
_Donde variable es la variable donde guardará el valor extraído
_DIG es el comando
_Value es el valor o la variable de donde vas a extraer el dígito
_y numero digito es el BIT que quieres extraer de Value
Un ejemplo sencillo:
B0 = 123 ;setea B0 en 123
B1 = B0 DIG 1 ;setea B1 en 2 (dígito 1 de 123)
Ahora sí; Veamos el ejemplo práctico, en el cual transformamos el valor binario de las distintas variables (tensión y corriente) a decimal empleando el operador DIG, para luego imprimir en el display
DERECHOS DE COPIA
Prohibida la reproducción parcial o total de este articulo sin previa autorización previa escrita del autor y / o responsable del foro www.forosdeelectronica.com, Sr. Andres Cuenca. La reproducción en medios gráficos, ya sea en formato digital, impreso, u cualquier otro modo sin la autorización pertinente, está penada por la Ley.
Este material es con fines educativos, y no comerciales.
Para quienes ya han estado experimentando con proyectos microcontrolados , y/o recién se están introduciendo en este mundo apasionante de los microcontroladores, se han dado cuenta que llega un momento dado que nuestra sed por aprender más, debe ser saciada con más proyectos, con más ejemplos… Con más conocimientos para simplificar.
Dejando de lado el famoso “Hola mundo” con un display LCD 16x2 o encender un simple led, en esta ocasión, vamos a ver cómo controlar e implementar los “display gráficos” NOKIA 3310 – 5110 para que nuestros proyectos queden más vistosos y ganen más vida aún.
Conociendo el GLCD
Esta es una pantalla LCD GRÁFICA (GLCD) con resolución matriz de 84x48 puntos, caracteres en blanco y negro, interfaz SPI con una velocidad de datos máxima de 4 Mbit /s. , y como vimos en el articulo anteriormente del display LCD16x2 (que usa un controlador interno HD44780), este display también contiene internamente un controlador, que es el PCD8544.
La alimentación de este dispositivo puede variar según la marca y modelo de fabricantes; La hoja de datos del controlador, comenta que la Tensión de alimentación, ronda los + 2.7V y + 3.6V; Pero en la práctica, el modulo completo que estoy trabajando, funcionó correctamente con 4.2v (En tensiones inferiores, el contraste es muy bajo y apenas pueden ver los caracteres).
Un poco de teoría sobre cómo trabaja el controlador de la pantalla
Inmediatamente después de encender nuestra pantalla, el contenido de los registros de este, contendrán valores indefinidos, por lo que es necesario generar un reset poniendo en estado bajo el pin “Reset” (RST).
Poniendo el pin /RES a nivel bajo durante un tiempo limitado (máx. 100mS) generamos el reset para poner a cero los registros del LCD, pero la RAM seguirá conteniendo datos indefinidos por lo tanto, después habrá que pintar toda la RAM a cero, para que el LCD quede limpio; Es necesario asegurarse de que todos los pasos se tengan en cuenta, ya que implementar mal el control de los pines, al poner en alto algunos pines específicos en un momento dado que no es el correcto, podemos dañar el controlador, y este no tiene reparación alguna.
Después del reset, ponemos en estado alto el PIN RST, y el controlador está listo para trabajar y grabar la secuencia de comandos que viene... Ahora mandaremos los comandos de puesta en marcha y configuración.
Function Set: Con el tipo de direccionamiento que queremos usar (Vertical u Horizontal), Chip activo, y juego de instrucciones básico o avanzado, seguido de los ajustes de coeficiente de temperatura, ajuste de Vop y BIAS. Todo esto según especificaciones en el datasheet.
El pin encargado de establecer el modo de trabajo del controlador, es el pin “Data Comand Select” (DC);
O sea, para establecer si esta en modo escritura (data) o lectura (comand), se pone en nivel bajo o alto este pin (0=comand – 1=data).
Al poner el PIN DC en estado bajo, habilitamos el controlador en modo lectura y se queda a la espera de los datos que afectaran los registros comandos para el control del display.
Estos datos son enviados mediante el protocolo SPI estándar:
Habilitamos SPI poniendo en bajo el PIN SCE, y se hace recepción de los bits de datos por el PIN SDIN. El PIN SDIN o DN, también es conocido como MOSI (Master Out Slave IN).
El PIN SCE o CS (Chip Select), debe activarse para indicarle al dispositivo que se le van a enviar datos. Para los que ya conocen el protocolo SPI y han trabajado con otros dispositivos, SCE / CS, también es conocido como SS (Slave Select).
La transferencia de datos, se lleva a cabo en el flanco ascendente del PIN SCLK, o sea, este pin es el que rige la comunicación y transferencia de datos.
Viéndolo de otra manera, la secuencia seria así:
Con todo esto el LCD ya está listo para ser usado, pero nos queda aun una cosa por hacer.. y es borrar la RAM del display que contiene datos aleatorios, así que deberemos direccionar toda la memoria mandando 0x00 en el modo adecuado.
Registros de Control
Toda la pantalla se divide en bancos (alto 8 bits de longitud y ancho de la pantalla 48px). El manejo de esta es similar al de una matriz ya que la salida de video, corresponde a una unidad (pixel negro).
Variando los bytes de la pantalla de vídeo, podemos cambiar la imagen; O sea, para mostrar la información en la pantalla, es necesario poner el cursor sobre el banco deseado e imprimir el punto. Dicho en otras maneras, seleccionamos las coordenadas X e Y, y dibujamos el punto.
Dicho de una manera más práctica. Esto seria así:
LCD_GotoXY:
LOW DC
LcdData= %01000000 | PosY: GOSUB LCD_ByteOut ' 0х40+numero de banco (0…5)
LcdData= %10000000 | PosX: GOSUB LCD_ByteOut ' 0х80+coordenanda X (0…83)
RETURN
Invirtiendo el estado de DC, pasamos el display a modo de visualización
Cada columna (Xi) de una línea determinada (Yj) corresponde a 1 byte de memoria (Figura superior), el píxel superior corresponde al bit menos significativo (LSB). Seleccionamos el número de fila y columna, colocamos el valor de los datos de estas en formato byte, y se muestra la columna 8x1. Después de un byte de escritura incrementa automáticamente la dirección del puntero de la columna. Por lo tanto, el siguiente byte se muestra en la misma línea, pero con un desplazamiento de 1 pixel a la derecha.
Cuando la impresión llegue al final de la recta:
y=yi
x = 83
Salta a la siguiente línea:
y = yi + 1
x = 0
Tener en cuenta que si el puntero se encuentra ubicado casi al final de la recta, y los bits que tenemos superan las posiciones que quedan libres, estos saltarán automáticamente a la línea siguiente.
Lo que vimos anteriormente, es válido cuando el bit de direccionamiento es cero V = 0.
Cuando el bit de direccionamiento es uno V = 1, la impresión se produce de manera similar, pero cada byte subsiguiente se muestra con un desplazamiento de 8 píxeles hacia abajo.
Pasemos a la práctica con PBP… Vamos a ver como se inicializa nuestro GLCD
Código:
--------------------------------Configuración de Puertos ---------------------------------------------------
DC VAR GPIO.2 'especifica el puerto que conecta la pantalla
DTA VAR GPIO.1
RST VAR GPIO.4
CLK VAR GPIO.0
'--------------------------------Definición de Variables-----------------------------------------------------
Chr VAR Byte 'Para contador del bucle para limpiar la pantalla
Posición PosX VAR Byte 'el cursor en la coordenada X
Posición PosY VAR Byte 'el cursor sobre coordenada
Datos LcdData VAR Byte 'para enviar el SPI
PAUSE 100
GOSUB LCD_INIT
PAUSE 100
GOSUB LCD_Clear 'para borrar la pantalla
Menu::
'Programa principal
'aquí colocamos nuestro programa principal…
End
'--------------------------------------------------------------------------------------------------------------
'-------------------------------------- Sub-inicializar la pantalla --------------------------------------
'--------------------------------------------------------------------------------------------------------------
LCD_Init: 'display rutinas de inicialización
LOW RST: Pause 20: HIGH RST 'y restablecer la pantalla LCD de reinicio
LOW DC 'Nivel Bajo para Modo Comando
LcdData = $ 20: GOSUB LCD_ByteOut 'Función Comando SET ($ = 20% 0010 0000) p = 0, V = 1, H = 0 - normal,
LcdData = $ 0c: GOSUB LCD_ByteOut 'Control Display ($ 0c =% 0000 1100) D = 1, E = 0
LcdData = $ 21: GOSUB LCD_ByteOut 'Función Comando SET ($ = 21% 0010 0001) p = 0, V = 1, H = 1-avanzada
LcdData = $ 06: GOSUB LCD_ByteOut 'Control de Temperatura ($ 06 = 0000 0110) para establecer el coeficiente de temperatura
LcdData = $ 13: GOSUB LCD_ByteOut 'Sistema de Bias($ 13 = 0001 0011) control para suministro de energía
LcdData = $ c8: GOSUB LCD_ByteOut 'Set Vop ($ c8 = 1100 1000) Invertir opción de energía
RETURN
'--------------------------------------------------------------------------------------------------------------
'------------------------------------------ es enviar comandos de SPI - ---------------------------------------
'Esta rutina es proporcionar por separado de todo el proceso de inicialización, ya que constantemente
'buscar para transmitir registros de control comandos
'--------------------------------------------------------------------------------------------------------------
LCD_ByteOut: 'rutina es para enviar comandos de SPI
SHIFTOUT DTA, CLK, 1, [LcdData] 'pereda?m por SPI byte de comando.
RETURN
'--------------------------------------------------------------------------------------------------------------
'------------------------------------------- borrar la pantalla --- -------------------------------------------
'--------------------------------------------------------------------------------------------------------------
LCD_Clear: 'Sub-borrar la pantalla
PosX = 0: PosY = 0 'Set X = 0, Y = 0 origen
GOSUB LCD_GotoXY
HIGH DC 'ALTA alto nivel de modo de datos DC '
FOR Chr = 1 TO 252 'Borrar la pantalla llenándolo de "0" - punto de luz
LcdData = 0: GOSUB LCD_ByteOut
LcdData = 0: GOSUB LCD_ByteOut
NEXT Chr
RETURN
'--------------------------------------------------------------------------------------------------------------
'------------------------------- Sub posicionar el cursor -------------- --------------------------------------
'Esta rutina es proporcionar por separado de todo el proceso de inicialización, ya que constantemente
'tratar de establecer el derecho de tener una fila o columna
'--------------------------------------------------------------------------------------------------------------
LCD_GotoXY: 'definir la posición del cursor
LOW DC ' BAJA bajo nivel de modo de comando DC '
LcdData =% 01000000 | PosY: GOSUB LCD_ByteOut '0x40 + numero de banco (0 ... 5)
LcdData =% 10000000 | PosX: GOSUB LCD_ByteOut '0x80 + X de coordenadas (0 ... 83)
RETURN
Resumiendo, como verán, la inicialización de la pantalla LCD no es complicada. Al iniciar el dispositivo, solo tenemos que implementar la rutina LCD_Init tan solo una vez, y luego, seguir con el resto del cuerpo del programa sin necesidad de volver a implementarlo.
La rutina LCD_Clear, se implementará si usted tiene que limpiar la pantalla de las entradas anteriores.
Las subrutinas LCD_GotoXY y LCD_ByteOut, serán las más implementadas en el resto del programa, ya que estas son las rutinas para cambiar de fila, columna, parte del procedimiento de impresión, etc. Ahora veamos lo que más nos interesa; Imprimir el primer “HOLA MUNDO” en la pantalla.
Imprimir en pantalla
Un poco de teoría nuevamente... A diferencia de los display alfa numéricos 16x2 con controlador HD44780, la pantalla del Nokia 3310 es gráfica y no contiene una biblioteca de símbolos. Esto significa que todos los elementos (números, letras) tienen que crearlos para luego imprimirlos (Algo similar a lo ya expuesto en el artículo de los display lcd16x2, creación de caracteres CGRAM). Por un lado es bueno (se pueden crear bibliotecas de símbolos), pero por otro lado, el problema radica en que esta acción toma una gran cantidad de memoria del microcontrolador.
El método de creación de caracteres es simple; Tomando como dato que el tamaño completo de cada matriz de carácter es de 5x8 pixel. Hacemos la tabla, y completamos con ceros y unos cada espacio, donde el uno marca el pixel color negro, y cero en blanco.
En el siguiente ejemplo, se ve la creación del carácter “A”. Una vez que tenemos la tabla completa, tomamos el número BINARIO y lo convertimos en HEX.
Recuerden que para escribir el numero binario, debemos escribirlo del byte menor al más alto; Veámoslo con un ejemplo $ 7E = St.b. 0111 Ml.b. 1110 = 0111111
En la practica, para hacer esta acción en PBP, el carácter generado se guarda de la siguiente manera:
'.............................................................. DEC | Chr | HEX
Data $ 7E, $ 11, $ 11, $ 11, $ 7E, $ 00 '65 | A | 41
'Data registra en EEPROM cinco símbolos del caracteres en un byte, comenzando en la posición de memoria 'cero. Al final de una columna, se necesita separar los caracteres uno de otro con el signo $ y 00.
Primer ejemplo práctico
En el siguiente ejemplo, lo que vamos a realizar, es imprimir tan solo un carácter; Recuerden que el carácter dibujado/creado, se almacena en la eeprom mediante el comando DATA.
Código:
DEFINE OSC 4
CLK VAR PORTB.3
DTA VAR PORTB.2
DC VAR PORTB.1
RST VAR PORTB.0
TRISA=%1
TRISB=%11110000
Chr VAR Byte
BitMap VAR Word
PosX VAR Byte
PosY VAR Byte
columna VAR Byte [6] 'array
LcdData VAR Byte
PAUSA 100
GOSUB LCD_INIT
PAUSA 100
GOSUB LCD_Clear
inicio:
PosX = 0: PosY = 0 : GOSUB LCD_GotoXY 'coloca el cursor en la posición deseada
FOR Chr = 0 TO 5
READ Chr, Columna (Chr) 'se lee de la EEPROM a partir de 0, y el dato se coloca en
'array columna (Chr)
NEXT Chr
HIGH DC
SHIFTOUT DTA, CLK, 1, [columna (0),columna (1), columna (2), columna (3),columna (4),columna (5)]
GOTO inicio
LCD_Init:
LOW RST : PAUSE 100 : HIGH RST: LOW DC 'LCD RESET
LcdData = $21: GOSUB LCD_ByteOut
LcdData = $c8: GOSUB LCD_ByteOut 'CONTRASTE
LcdData = $06: GOSUB LCD_ByteOut 'SET coeficiente TEMP
LcdData = $13: GOSUB LCD_ByteOut 'LCD MODO BIAS
LcdData = $20: GOSUB LCD_ByteOut
LcdData = $0c: GOSUB LCD_ByteOut 'LCD modo normal
RETURN
LCD_ByteOut:
SHIFTOUT DTA, CLK, 1, [LcdData]
RETURN
LCD_Clear:
PosX = 0 : PosY = 0 : GOSUB LCD_GotoXY
HIGH DC
FOR Chr = 1 TO 252
LcdData = 0: GOSUB LCD_ByteOut
LcdData = 0: GOSUB LCD_ByteOut
NEXT Chr
RETURN
LCD_GotoXY:
LOW DC
LcdData =%01000000 | PosY: GOSUB LCD_ByteOut
LcdData =%10000000 | PosX: GOSUB LCD_ByteOut
RETURN
'-------------------------------------------------
'Tabla de DATOS de las Fuentes
'-------------------------------------------------
DATA $20, $54, $54, $54, $78, $00
Excelente, si ya estamos en estas líneas, tomo por superado lo visto anteriormente… Ahora vamos a implementar una tabla con más gráficos y vamos a imprimir un par de símbolos estáticos en la pantalla
Código:
DEFINE OSC 4
CLK VAR PORTB.3
DTA VAR PORTB.2
DC VAR PORTB.1
RST VAR PORTB.0
TRISA=%1
TRISB=%11110000
x VAR byte
a VAR byte
Chr_1 VAR Byte
Chr VAR Byte
char VAR byte
offset VAR byte
BitMap VAR Word
PosX VAR Byte
PosY VAR Byte
Columna VAR Byte [6]
LcdData VAR Byte
'-------------------------------------------------
'Tabla de DATOS de las Fuentes
'-------------------------------------------------
DATA @0,$3E,$51,$49,$45,$3E,_ ;/caracter en posicion 0/ numero 0
$00,$42,$7F,$40,$00,_ ;/caracter en posicion 1/ numero 1
$42,$61,$51,$49,$46,_ ;/caracter en posicion 2/ numero 2
$21,$41,$45,$4B,$31,_ ;/caracter en posicion 3/ numero 3
$18,$14,$12,$7F,$10,_ ;/caracter en posicion 4/ numero 4
$27,$45,$45,$45,$39,_ ;/caracter en posicion 5/ numero 5
$3C,$4A,$49,$49,$30,_ ;/caracter en posicion 6/ numero 6
$01,$71,$09,$05,$03,_ ;/caracter en posicion 7/ numero 7
$36,$49,$49,$49,$36,_ ;/caracter en posicion 8/ numero 8
$06,$49,$49,$29,$1E,_ ;/caracter en posicion 9/ numero 9
$08,$08,$3E,$08,$08,_ ;/caracter en posicion 10/ signo +
$08,$08,$08,$08,$08,_ ;/caracter en posicion 11/ signo -
$00,$60,$60,$00,$00,_ ;/caracter en posicion 12/ signo .
$7E,$11,$11,$11,$7E,_ ;/caracter en posicion 13/ letra A
$1F,$20,$40,$20,$1F,_ ;/caracter en posicion 14/ letra V
$7F,$09,$09,$09,$01 ;/caracter en posicion 15/ letra F
PAUSE 100
GOSUB LCD_INIT
PAUSE 100
GOSUB LCD_Clear
PosX = 0 : PosY = 0 : GOSUB LCD_GotoXY
inicio:
; posicionamos el puntero en los ejes X e Y
Lcddata = %01000000 + 17 ' cursor X en posicion 17
call PrintCtrlLcd
Lcddata = %10000000 +40 ' cursor Y en posicion 40
call PrintCtrlLcd
Char = 2 ;caracter de la posicion 2 (que es el numero "2")
call PrintChar
Char = 1 ;caracter de la posicion 1 (que es el numero "1")
call PrintChar
Char = 12 ;caracter de la posicion 12 (que es el signo ".")
call PrintChar
Char = 5 ;caracter de la posicion 5 (que es el numero "5")
call PrintChar
Char = 4 ;caracter de la posicion 4 (que es el numero "4")
call PrintChar
Char = 14 ;caracter de la posicion 14 (que es la letra "V")
call PrintChar
goto inicio
PrintChar:
offset = Char * 5
for a = 1 to 5
read offset, LcdData
call PrintDataLcd
offset = offset + 1
next a
LcdData = 0
call PrintDataLcd
return
PrintCtrlLcd:
DC = 0
PrintDataLcd:
for x = 1 to 8
DTA = LcdData.7
CLK = 1
LcdData = LcdData << 1
CLK = 0
next x
DC = 1
return
LCD_Init:
low RST : Pause 20: high RST : LOW DC
LcdData = $21: GOSUB LCD_ByteOut
LcdData = $c8: GOSUB LCD_ByteOut
LcdData = $06: GOSUB LCD_ByteOut
LcdData = $13: GOSUB LCD_ByteOut
LcdData = $20: GOSUB LCD_ByteOut
LcdData = $0c: GOSUB LCD_ByteOut
RETuRN
LCD_ByteOut:
SHIFTOUT DTA, CLK, 1,[LcdData]
RETuRN
LCD_Clear:
PosX = 0 : PosY = 0 : GOSUB LCD_GotoXY
high DC
for Chr = 1 to 252
LcdData = 0 : GOSUB LCD_ByteOut
LcdData = 0 : GOSUB LCD_ByteOut
next Chr
RETuRN
LCD_GotoXY:
LOW DC
LcdData =%01000000 | PosY : GOSUB LCD_ByteOut
LcdData =%10000000 | PosX : GOSUB LCD_ByteOut
RETURN
END
Como pudimos ver en el ejemplo anterior, generamos una tabla con los distintos caracteres generados; Cada carácter, ocupa 5 espacios de cada posición; Disculpen que sea reiterativo, pero hay cosas que es mejor repetirlas varias veces para que queden en claro… Bien, si la tabla la organizamos de tal manera de recordar en que posición de ésta está cada carácter, fíjense en el programa que asignando a la variable “char” el valor de la posición y llamando la rutina “PrintChar”, leemos la posición de la eeprom e imprimimos el carácter.
Ahora… ¿como las posicione automáticamente en la pantalla?
Partiendo de las líneas donde establecemos como inicio del puntero en los ejes X e Y con un agregado en cada eje (+17 para el eje X y +40 para el eje Y), esto significa que de las coordenadas 0-0, estaremos desplazados 17 pixeles para un lado, y 40 pixeles para el otro.
Lcddata = %10100000 + 17 ' cursor X en posicion 17
call PrintCtrlLcd
Lcddata = %01000010 +40 ' cursor Y en posicion 40
call PrintCtrlLcd
Si queremos que inicie desde la posicion 1-1 (esquina superior izquierda), tendríamos que colocar los siguientes valores
Lcddata = %01000000+1 ' cursor X en posición 1
call PrintCtrlLcd
Lcddata = %01000000 +1 ' cursor Y en posición 1
call PrintCtrlLcd
Bien, hay muchas maneras de desplazar el puntero e imprimir cada carácter; Eso está en el ingenio de cada programador; En mi caso, para poder no repetir líneas de programación cada vez que quiero desplazar posiciones e imprimir cada carácter, implemente las siguientes líneas:
PrintChar:
offset = Char * 5
for a = 1 to 5
read offset, LcdData
call PrintDataLcd
offset = offset + 1
next a
LcdData = 0
call PrintDataLcd
return
Básicamente, la idea fue partir de la posición del puntero, e ir sumando saltos de 5 pixeles (que es la anchura de cada carácter) para luego imprimir…
Veamos un último ejemplo para ir cerrando la idea de cómo manejar / controlar estos display gráficos…
Hasta acá, hemos visto como inicializar el display gráfico, vimos como crear, generar un carácter, vimos como crear una tabla con los caracteres, vimos como imprimir estos carácter…etc.
Ahora vamos a ver cómo hacer un programa, interactuar con las variables del programa e imprimir el valor de estas variables, para que pasemos un paso más adelante, y dejemos atrás el “hola mundo” estático al que estamos acostumbrados desde el inicio de este articulo…
Como el pic 16F628 no tiene ADC, para realizar el próximo ejemplo, vamos a implementar un PIC 16F876A y armaremos un simple monitor de tensión y corriente.
Como carga, para poder simular nuestro proyecto, notarán que implementé tres motores en paralelo con sus respectivos switch para habilitar y así poder sumar o decrementar peso a la carga.
Antes que nada, veamos un poco que nos ofrece PicBasic Pro, para realizar nuestro programa, ya que nosotros ahora tenemos que llevar el valor binario de la variable, al formato decimal.
Cuando nos vemos en la necesidad de hacer una conversión de Binario a Decimal, picbasic pro incluye un operador que puede ser empleado para este propósito...
El operador DIG (mal llamado comando); El operador DIG devuelve el valor de un dígito decimal. Simplemente se le indica el número de dígito a conocer ( 0 - 4 , siendo 0 el primero de la derecha) y ya está.
Dicho de otra manera, para desglosar el valor binario y extraer el valor deseado, hay que especificar con el número de dígito siguiente de la variable a la que vas a extraer el dígito... Suponiendo que solo quieres que extraiga el segundo valor, tienes que poner el bit 1 lógicamente, y te funcionara, si quieres el tercer valor tienes que poner el bit2 y así sucesivamente.
Acordate que el operador funciona de la siguiente forma :
Variable = DIG Value , Digit number
_Donde variable es la variable donde guardará el valor extraído
_DIG es el comando
_Value es el valor o la variable de donde vas a extraer el dígito
_y numero digito es el BIT que quieres extraer de Value
Un ejemplo sencillo:
B0 = 123 ;setea B0 en 123
B1 = B0 DIG 1 ;setea B1 en 2 (dígito 1 de 123)
Ahora sí; Veamos el ejemplo práctico, en el cual transformamos el valor binario de las distintas variables (tensión y corriente) a decimal empleando el operador DIG, para luego imprimir en el display
Código:
DEFINE OSC 4
;**************** ADC chanel setting ************************
DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 3
DEFINE ADC_SAMPLEUS 50
INTCON = 0
CMCON=7
ADCON1=%10000010
TRISA=%00001111
TRISB=%00000000
TRISC=%00000000
PORTA=0
PORTB=0
PORTC=0
CLK VAR PORTB.2
DTA VAR PORTB.3
DC VAR PORTB.0
RST VAR PORTB.1
SCE VAR PORTB.4
'-------------------------------------------------
; variables para control del programa
'-------------------------------------------------
HAM VAR word
HAM2 VAR WORD
X1 VAR WORD
VOLT VAR WORD
HVD VAR word
AMPER VAR word
MV VAR BYTE
MA VAR BYTE
'-------------------------------------------------
; variables para control del display
'-------------------------------------------------
x var byte
y var byte
z var byte
a var byte
PosX var byte
PosY var byte
Chr var byte
LcdData var byte
Offset var byte
Char var byte
adval var word
w1 var word
vt var word
cnt var byte
grup var word
'-------------------------------------------------
'Tabla de DATOS de las Fuentes
'-------------------------------------------------
DATA @0,$3E,$51,$49,$45,$3E,_ ;/caracter en posicion 0/ numero 0
$00,$42,$7F,$40,$00,_ ;/caracter en posicion 1/ numero 1
$42,$61,$51,$49,$46,_ ;/caracter en posicion 2/ numero 2
$21,$41,$45,$4B,$31,_ ;/caracter en posicion 3/ numero 3
$18,$14,$12,$7F,$10,_ ;/caracter en posicion 4/ numero 4
$27,$45,$45,$45,$39,_ ;/caracter en posicion 5/ numero 5
$3C,$4A,$49,$49,$30,_ ;/caracter en posicion 6/ numero 6
$01,$71,$09,$05,$03,_ ;/caracter en posicion 7/ numero 7
$36,$49,$49,$49,$36,_ ;/caracter en posicion 8/ numero 8
$06,$49,$49,$29,$1E,_ ;/caracter en posicion 9/ numero 9
$08,$08,$3E,$08,$08,_ ;/caracter en posicion 10/ signo +
$08,$08,$08,$08,$08,_ ;/caracter en posicion 11/ signo -
$00,$60,$60,$00,$00,_ ;/caracter en posicion 12/ signo .
$7E,$11,$11,$11,$7E,_ ;/caracter en posicion 13/ letra A
$1F,$20,$40,$20,$1F,_ ;/caracter en posicion 14/ letra V
$7F,$09,$09,$09,$01 ;/caracter en posicion 15/ letra F
PAUSe 100
GOSUB LCD_INIT
PAUSe 100
GOSUB LCD_Clear
PosX = 0 : PosY = 0 : GOSUB LCD_GotoXY
;================ programa principal ==============================
INICIO:
ADCIN 0,HAM
BAK:
IF ADCON0.2=1 THEN BAK
PAUSE 5
GOSUB F_VOLT
ADCIN 1,HAM
PAUSE 5
GOSUB F_AMP
PAUSE 1000
GOSUB N3310
GOTO INICIO
;========================= V - A ==================================
F_VOLT:
HVD=((HAM+1)*/875)/10
VOLT=HVD/10
MV=(HVD)//10
RETURN
F_AMP:
HVD=(HAM+1)*/250
AMPER=HVD/100
MA=HVD//100
RETURN
'================== L C D N3310 ========================================
N3310:
'~~~~~~~~~~~~~~~~~ cursor display volt
Lcddata = %10100000 + 17 ' cursor X
call PrintCtrlLcd
Lcddata = %01000010 +40 ' cursor Y
call PrintCtrlLcd
Char = (VOLT dig 1)
call PrintChar
Char = (VOLT dig 0)
call PrintChar
Char = 12
call PrintChar
Char = (MV dig 0)
call PrintChar
;Char = (MV dig 1)
;call PrintChar
Char = 14
call PrintChar
'~~~~~~~~~~~~~~~~~ cursor display amp
Lcddata = %10100000 + 17 ' cursor X
call PrintCtrlLcd
Lcddata = %01000010 + 50 ' cursor Y
call PrintCtrlLcd
Char = (amper dig 1)
call PrintChar
Char = (amper dig 0)
call PrintChar
Char = 12
call PrintChar
Char = (Ma dig 1)
call PrintChar
Char = 13
call PrintChar
RETURN
PrintChar:
offset = Char * 5
for a = 1 to 5
read offset, LcdData
call PrintDataLcd
offset = offset + 1
next a
LcdData = 0
call PrintDataLcd
return
PrintCtrlLcd:
DC = 0
PrintDataLcd:
for x = 1 to 8
DTA = LcdData.7
CLK = 1
LcdData = LcdData << 1
CLK = 0
next x
DC = 1
return
LCD_Init:
low RST : Pause 20: high RST : LOW DC
LcdData = $21: GOSUB LCD_ByteOut
LcdData = $c8: GOSUB LCD_ByteOut
LcdData = $06: GOSUB LCD_ByteOut
LcdData = $13: GOSUB LCD_ByteOut
LcdData = $20: GOSUB LCD_ByteOut
LcdData = $0c: GOSUB LCD_ByteOut
RETuRN
LCD_ByteOut:
SHIFTOUT DTA, CLK, 1,[LcdData]
RETuRN
LCD_Clear:
PosX = 0 : PosY = 0 : GOSUB LCD_GotoXY
high DC
for Chr = 1 to 252
LcdData = 0 : GOSUB LCD_ByteOut
LcdData = 0 : GOSUB LCD_ByteOut
next Chr
RETuRN
LCD_GotoXY:
LOW DC
LcdData =%01000000 | PosY : GOSUB LCD_ByteOut
LcdData =%10000000 | PosX : GOSUB LCD_ByteOut
RETuRN
DERECHOS DE COPIA
Prohibida la reproducción parcial o total de este articulo sin previa autorización previa escrita del autor y / o responsable del foro www.forosdeelectronica.com, Sr. Andres Cuenca. La reproducción en medios gráficos, ya sea en formato digital, impreso, u cualquier otro modo sin la autorización pertinente, está penada por la Ley.
Este material es con fines educativos, y no comerciales.