# Control GLCD (PCD8544) Nokia 3310-5110 con pbp



## torres.electronico (Nov 5, 2015)

*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*_


```
--------------------------------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.


​

```
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


​

```
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


```
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.


----------



## torres.electronico (Dic 8, 2015)

En breve, un par mas de ejemplos practicos; Estoy batallando con un artilugio que quiero recilcar parte de él para cerrar la idea del proximo proyecto 
Uno de los problemas mas comunes de esas pantallas, es la goma conductora (la que esta en el pcb y el vidrio del lcd)... Tengo tres muertos y probe desarmando calculadoras etc etc para ver si podia solucionar este problema de contacto y en una de las tantas me llego a cansar y arme todo como estaba, con la sorpresa que al presionar y estañar las patillas de sujecion, funciono uno de los tres 
Lo comento a modo de tips por si compran y ven que no les funciona


----------



## papirrin (Dic 8, 2015)

> Lo comento a modo de tips por si compran y ven que no les funciona



A mi me gusto tu proyecto, para hacer la prueba en fisico, ya habia visto otros proyectos pero no estan tan bien documentados. en fin me propuse ir a buscar una pantalla de esas pero no logre conseguir ninguna, ni en los mercaditos de chacharas viejas , espero encontrar alguna algun dia.


----------



## torres.electronico (Dic 8, 2015)

si no tenes problemas de importacion como nosotros en ARG, te envio por correo de regalo una (aca salen mas baratos o casi igual que los display 16x2).


----------



## Inductancio (Sep 5, 2016)

Gran aporte PROFE...Gracias !!! Seguiste con más ejemplos en algún lado, para ir viendo...Mañana compro una pantallita de estas y empiezo a ver si me sale algo de lo que aquí dejás como ejemplos...Encontré poco en la red sobre estas pantallitas y pic, el 99% es para arduino...Si hay algún avance sobre el tema, me gustaría seguir leyendo...Un abrazo !!!


----------



## torres.electronico (Sep 5, 2016)

Inductancio dijo:


> Gran aporte PROFE...Gracias !!! Seguiste con más ejemplos en algún lado, para ir viendo...Mañana compro una pantallita de estas y empiezo a ver si me sale algo de lo que aquí dejás como ejemplos...Encontré poco en la red sobre estas pantallitas y pic, el 99% es para arduino...Si hay algún avance sobre el tema, me gustaría seguir leyendo...Un abrazo !!!



Jugue en C y basic; intente algo en asm y me pudrio de tan largo que se me hacia el programa..






Hay un par mas en mi canal... Pasa que ando a mil y muchas veces se me pasa de suvir mas ejemplos


----------



## Inductancio (Sep 6, 2016)

Gracias...este solo video es alentador para seguir mirando...Donde debería mirar MARTIN...Tu canal es de YouTube, FaceBook, acá en el foro, etc ??? Disculpá la ignorancia...Por ahora con esto que hay acá me voy a animar a conectar la pantallita que compré hoy y que sea lo que Dios quiera, jaja...Este sencillo viedo me sirvio para despejar para que lado escribe la pantalla, parece que el perfil ancho queda para arriba nomás...Algo es algo, jaja...


----------



## torres.electronico (Sep 6, 2016)

en mi canal de youtube y en mi googledrive... en mi pagina ETI hay un proyecto de un controlador PWM para celda de hidrogeno con este display... tenes para revolver un buen rato y encontrar.
Lo que no entendi a que te referis con mencionar "_para que lado escribe la pantalla, parece que el perfil ancho queda para arriba nomás_"
saludos


----------



## Inductancio (Sep 7, 2016)

No me anduvo...compré una pantallita 5110 SPI, la alimenté con 3,3v y seguí una recomendación que vi, hacen para el ARDUINO, donde ponen en serie con las entradas de DATA, DC, CLK, RST una R de 10K, aunque creo que sería mejor un 4050 para adaptar niveles...el SCE (chip selet) lo pongo a masa...la pata LIGHT no la uso o la conecto con 330 a masa...la configuración de inicialización es la que parece una incognita, hay valores de configuración que no se bien para que sirven...y si el orden en que se escriben es importante o no...En fin, seguiré leyendo e intentando..................


----------



## torres.electronico (Sep 8, 2016)

Inductancio dijo:


> No me anduvo...compré una pantallita *5110* SPI, la alimenté con *3,3v* y seguí una recomendación que vi, hacen para el *ARDUINO*, donde ponen en serie con las entradas de DATA, DC, CLK, RST una R de 10K, aunque creo que sería mejor un 4050 para adaptar niveles...el SCE (chip selet) lo pongo a masa...la pata LIGHT no la uso o la conecto con 330 a masa...



 si observas, yo presenté un shield determinado, mostré y sugerí un conexionado y el lenguaje de programación es en PBP (Picbasic pro)...



Inductancio dijo:


> ...la configuración de inicialización es la  que parece una incognita, hay valores de configuración que no se bien  para que sirven...y si el orden en que se escriben es importante o  no...En fin, seguiré leyendo e intentando..................



 solo estoy pensando que leíste el articulo salteando líneas y no prestaste atención al inicio del artículo cuando hablo de la comunicación SPI y de la forma en que trabaja la pantalla





O sea, no lograste interpretar los programas de ejemplos y fuiste derecho a meter manos... Mi consejo es que leas nuevamente el artículo, sepas diferenciar cuales son las rutinas de control del glcd y luego, copies y pegues... Ya sabiendo que parte no hay que meter mano (la sección de inicialización de la pantalla y la parte de control e impresión), luego edita corta y pega tus programas en el resto de lo que era el programa antiguo... osea, tómalo como ejemplo base. mete mano ahí, allá, fíjate que paso, búscale el porque, etc etc..


PD: Lee lo que hablo sobre la alimentación  ...


----------



## Inductancio (Sep 8, 2016)

Gracias MARTIN...la verdad es que no modifiqué nada más que algunos parámetros que tienen que ver con la inicialización, ya que en el primer ejemplo hay valores diferentes que en el segundo...20, 0C, 21, 06,13, C8 y en el segundo 21, C8, 06, 13, 20, 0C...Fue ahí que me di cuenta que el segundo parámetro es el del contraste, y lo fui cambiando hasta empezar a ver algo, por ahí leí que alguien sugería (( Set LCD Vop (Contrast): Try 0xB1(good @ 3.3V) or 0xBF if your display is too dark)) entonces pensé que no se podía quemar nada si probaba...me quedó bien con C4 y 3,3v o C2 y 4,2v...Tenía alimentado el display con 3,3v y el micro con 5v, pero como los niveles de salida del micro, seguían siendo de 5v, hice unos divisores a cada entrada del LCD para que trabaje con 3,3v...También intenté hacer andar todo con 3,3v hasta 4,2v (incluido el micro), y recién ahí empezó a asomar la "a", jaja...En definitiva, entre los valores de alimentación y el parámetro del contraste, estaba la solución...Los programas son muy didácticos, y aprendí lo básico como para arrancar con algo, vamos a ver que otra cosa me sale...Como mencionaba antes, hay muchísimo para arduino, tienen todas las librerías listas para trabajar, pero no se si se aprende algo de ese modo...Creeme, leí varias veces la información de este hilo, y de hecho aprendí a programar con tus aportes en este y otros foros desde donde también estudié y estudio tus ejemplos y el de otros participantes...Algún día te voy a contar de mis viajes a Comodoro y a la Rada !!! ABRAZO !!!


----------



## torres.electronico (Sep 12, 2016)

consulta... tu modulo es el rojo o el azul? tenes fotos 
Cuando andes por la zona chiflame


----------



## Inductancio (Sep 12, 2016)

Algunos avances...dibuje un marco usando LOOKUP, escribí HOLA TORRES con la técnica que explicás acá para posicionar cursor, tomando caracteres de EEPROM y también usando LOOKUP (una y una) y finalmente lo más dificil, los NUMEROS EN GIGANTE, técnica que tomé del foro de PBP (UK), creo que lo termina haciendo un italiano...con STRING y LOOKDOWN y SHIFTOUT y bla, bla...Todo en un pobre 628 que lo uso para todo...quiero empezar a hacer algo con los ADS de algún otro micro, pero chico (F88 o similar)...Para hacer el marco, escribir HOLA TORRES y los Nros.grandes ocupe casi 1K de los 2k, jaja...Y la EEPROM con todo el ABECEDARIO...Tengo también una pantalla GLCD de las que se parecen a los LCD 16x4, voy a ver si encuentro algo de información como esta que dejaste, para empezar a hacer algo.

El que tengo es ROJO, ahora veo si puedo subir una foto.

Un abrazo.


----------



## torres.electronico (Sep 12, 2016)

Para ganar un poco de espacio, fíjate que en algún lado en PBP uk, había una librería en ASM que dentro de todo ayudaba bastante a reducir el programa y espacio.
Leí en algún lado que no son el 100% iguales los modulitos ronos y azules


----------



## Inductancio (Sep 13, 2016)

Voy a mirar, a ver si encuentro algo...Gracias por el dato.

Quiero hacerme ese miniosciloscopio y el generador del funciones...los hiciste con el NOKIA 5110 ??? Con el generador me conformo, me puede servir para laburar...Por donde empiezo ??? Que micro me haría falta ??? Por algún lado conté que empecé con PBP apenas el año pasado, y ya hacía unos cuantos meses que no lo tocaba, refrescar memoria me tomó unos días...Siempre programé en ASM, pero me gustaría intentar hacerlo en PBP.

Trabajé durante varios años en Comodoro, en realidad viajaba con frecuencia para hacerle el mantenimiento a un aparatito de alta complejidad médica, el cual además de ser el primero en la provincia, instalé yo mismo, y como los pasajes siempre los sacaba abiertos, me volvía a la semana, asi que conozco un poco el lugar (te cuento por privado si te interesa).

Nose si tenés contactos acá en BsAs, pero podés contar conmigo por si querés conseguir de estos display o algún componente electrónico que no consigas...Este lo compré por MERCADO LIBRE, en un lugar que me queda relativamente cerca, no sería molestia...Aveces comprar directamente es más barato, al menos podés pelearles la comisión que les cobra ML a ellos (los vendedores)...Estoy cerca de CIKA y de ELEMON, tienen casi todo lo que se te ocurra...Cualquier cosa avisame.

Abrazo.


----------



## alex leal (Sep 23, 2016)

Saludos amigo torres.electronico me gusto mucho tu video de mini osciloscopio col la pantalla de nokia 5110 y de verdad te felicito esto me dio pie a seguir tus paso y tratar desarrollar mi propio osciloscopio con la misma pantalla incluso ya estoy haciendo pruebas y ya pinto puntos en la glcd pero estoy frenado ya q tengo que pintar una línea entre puntos para mejorar la visualización del osc y no consigo como hacer esa rutina de codigo estoy usando bpb y un 16f887 me gustaría me echaras la mano amigo torres mil gracias de antemano


----------



## torres.electronico (Sep 26, 2016)

Por el momento estoy bastante liado con mi trabajo e incluída la construcción de mi casa. Cuando este mas tranqui se vendrá un segundo artículo sobre gráficos analógicos y estáticos. Saludos


----------



## alex leal (Sep 27, 2016)

saludos hermano Torres tranquilo estare esperando tu segundos articulo debe ser muy interesante de todas forma estaré pensando como salir del atolladero gracias hermano


----------

