|
|
View previous topic :: View next topic |
Author |
Message |
Pichuqy_1
Joined: 03 Aug 2010 Posts: 38
|
Initialization problems display ST7565R |
Posted: Sun Dec 12, 2021 5:06 pm |
|
|
Hello everyone!
I've been trying to initialize the following display for days, working with different codes and tutorials and I've just about to give it up. . I don't know if the initialization code is written in the correct way as well as the glcd_command and glcd_data functions. Can you help me to understand what the problem is, please?
The display is the following:
URL https://es.aliexpress.com/item/1005001621784395.html?spm=a2g0s.9042311.0.0.56fb63c0DvXFmX /url
The datasheet:
URL https://pdf1.alldatasheet.com/datasheet-pdf/view/326163/SITRONIX/ST7565R.html /url
I'm using the following hardware:
For the initialization function "glcd_init()" I use from datasheet page 51:
When it comes to SPI configuration, I use the following from datasheet page 24:
And the code is:
Main
Code: | #include <18F46K20.h> //pic a utilizar
#fuses HS,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOPBADEN // el fuse
#use delay(clock=4000000)
#use STANDARD_IO(B)
#use STANDARD_IO(C)
#use STANDARD_IO(D)
#use STANDARD_IO(E)
#include "ST7565R_2.h"
void main(void)
{
glcd_init();
delay_ms(500);
setpixel(10, 10, BLACK);
delay_ms(2000);
clear_display();
} |
ST7565R Library
Code: | #include <stdlib.h>
const int8 pagemap[] = {3, 2, 1, 0, 7, 6, 5, 4};
#ifndef _ST7565_H_ // Explicación directivas https://www.youtube.com/watch?v=qy14Ac4ICHc
#define _ST7565_H_
// Configuración pines SPI
#define GLCD_CS PIN_C1 // Selección de chip.
#define GLCD_RESET PIN_C2 // Si /RES =0 el registro seleccionado se limpia
#define GLCD_RS PIN_C3 // A0 = 1: D0 a D7 se configuran como datos de visualización. A0 = 0: son pines de control
#define GLCD_SCK PIN_D0 // Pin de clock
#define GLCD_SI PIN_D1 // Pin de data
#define BLACK 1
#define WHITE 0
#define SCREEN_WIDTH 128 // Ancho de pantalla
#define SCREEN_HEIGHT 64 // Largo pantalla
/** Define this if your screen is incorrectly shifted by 4 pixels */
#define ST7565_REVERSE
/** By default we only write pages that have changed. Undefine this
if you want less/faster code at the expense of more SPI operations. */
//#undef ST7565_DIRTY_PAGES 1
//COMANDOS
#define GLCD_CMD_DISPLAY_ON 0b10101111 // Encendemos el display
#define GLCD_CMD_DISPLAY_OFF 0b10101110 // Apagamos el display
#define GLCD_CMD_ALL_NORMAL 0b10100100 // Permite forzar todos los puntos del display en ON sin importar en contenido de la RAM. MODO NORMAL. El contenido de la RAM no se pierde.
#define GLCD_CMD_ALL_ON 0b10100101 // Permite forzar todos los puntos del display en ON sin importar en contenido de la RAM. MODO ON. El contenido de la RAM no se pierde.
// Cuando el dsiplay está OFF, ejecutando este el comando GLCD_CMD_ALL_ON el display se pondrá en modo SLEEP.
#define GLCD_CMD_DISPLAY_NORMAL 0b10100110 // Permite invertir la pantalla sin sobreescribir la memoria RAM. MODO NORMAL
#define GLCD_CMD_DISPLAY_REVERSE 0b10100111 // Permite invertir la pantalla sin sobreescribir la memoria RAM. MODO INVERTIDO
#define GLCD_CMD_BIAS_9 0b10100010 // Seleciona el voltaje requerido para el display. 1/9 th
#define GLCD_CMD_BIAS_7 0b10100011 // Seleciona el voltaje requerido para el display. 1/7 th (ST7565R)
//Se revierte la correspondencia entre los datos de las columnas de la RAM y los segmentos de salida del driver.
//Se deberá usar la instrucción la función glcd_flip_screen para que el ancho se configure correctamente.
#define GLCD_CMD_HORIZONTAL_NORMAL 0b10100000 // MODO NORMAL
#define GLCD_CMD_HORIZONTAL_REVERSE 0b10100001 // MODO REVERSE
// Permite revertir la pantalla verticalmente.
#define GLCD_CMD_VERTICAL_NORMAL 0b11000000 // MODO NORMAL
#define GLCD_CMD_VERTICAL_REVERSE 0b11001000 // MODO REVERSE
// Configura la fuente de alimentación. Tiene tres modos: 1) Booster circuits, 2) Voltage regulator, 3) Voltage follower cirtuits.
// Estos modos pueden ser usados independientente del uso del los comandos Power Control Set.
// Ver pag. 31 datasheet
#define GLCD_CMD_POWER_CONTROL 0b00101000 // Solo utiliza la fuente de alimentación externa
// Este comando configura el Vo= (1+Rb/Ra)*Vev. Puede ser utilizado para controlar por comandos (sin añadir resistencias externas) el brillo de la pantalla. Paguina 33/46 datasheet.
// Se utilizan 2 bytes para la configuración.
// El "Electronic Volume Set" se configura con "Electronic Volume Mode SET" y "Electronic Volume Register Set"
#define CMD_SET_RESISTOR_RATIO 0b00100000 // 0b00000000 63 0b00111111 0. The "Electronic Volume Register SET"
#define GLCD_ELECTRONIC_VOLUME_MODE_SET 0b10000001
#define GLCD_CMD_VOLUME_REGISTER_SET 0b00000000 // The Electronic Volume Mode Set. Cuando se ingresa este comando se habilita el "Electronic Volume Set"
// Este comando se utiliza para especificar la posición de inicio en la memoria RAM. 0b01000000 posición 0. 0b01111111 posición 63
// Se puede utilizar para hacer screen srolling, page swapping. INTERESANTE PAGUINA 26
#define GLCD_CMD_DISPLAY_START 0b01000000 // POSICIÓN 0
// Este comando especifica la dirección de la columna de los datos mostrados en RAM. La columna de direcciones se divide en dos secciones ( higher 4 bits y lower 4 bits). PAGUINA 42
#define GLCD_CMD_COLUMN_LOWER 0b00000000 // 0b00000000 Column address 0 0b10000011 Column address 131
#define GLCD_CMD_COLUMN_UPPER 0b00010000 // Se selecciona los 4 bits mas significantes de la columna.
#define GLCD_CMD_SET_PAGE 0b10110000 // Se selecciona la paguina actual (0..7))
// Este comando inicializa: la linea de inicio, la dirección de la columna, la dirección de la paguina, el Vo, el common output mode, the electronic volume y read/modify/write mode
// El test mode se libera
// No impacta en los datos de la RAM.
#define GLCD_CMD_RESET 0b11100010
#define COMMON_OUTPUT_MODE_SELECT 0b11000000
#define CMD_RMW 0b11100000 // Read-modify-write
// No realiza operación alguna. El datasheet suguiere enviar este comando periodicamente.
#define GLCD_CMD_NOP 0b11100011
#endif // _ST7565_H_
/////////////////////////////////////////////////////////////////////////
// Funciones
/////////////////////////////////////////////////////////////////////////
void glcd_init(); // Inicializamos la pantalla. Tenemos que llamar a esta rutina primero
void glcd_command(char); // Enviamos un comando al Display.
void glcd_data(char); // Enviamos un dato al Display.
void glcd_contrast(int8 val);
void clear_display(void);
void clear(void);
void display();
void drawchar(int8 x, int8 line, char c);
void drawstring(int8 x, int8 line, char *c);
void setpixel(int8 x, int8 y, int8 color);
/////////////////////////////////////////////////////////////////////////
// Buffer para el display
static int8 buffer[1024] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x3, 0x7, 0xF, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x7F, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x1F, 0x3F, 0x70, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x6, 0x0, 0x0, 0x0, 0x3, 0x3,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0xF, 0x7, 0x7,
0x7, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0x3F,
0x70, 0x60, 0x60, 0x60, 0x60, 0x30, 0x7F, 0x3F, 0x0, 0x0, 0x1F, 0x3F, 0x70, 0x60, 0x60, 0x60,
0x60, 0x39, 0xFF, 0xFF, 0x0, 0x6, 0x1F, 0x39, 0x60, 0x60, 0x60, 0x60, 0x30, 0x3F, 0x7F, 0x0,
0x0, 0x60, 0xFF, 0xFF, 0x60, 0x60, 0x0, 0x7F, 0x7F, 0x70, 0x60, 0x60, 0x40, 0x0, 0x7F, 0x7F,
0x0, 0x0, 0x0, 0x0, 0x7F, 0x7F, 0x0, 0x0, 0x0, 0x7F, 0x7F, 0x0, 0x0, 0x60, 0xFF, 0xFF,
0x60, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x80, 0xF8, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xE7, 0xE7, 0xE3,
0xF3, 0xF9, 0xFF, 0xFF, 0xFF, 0xF7, 0x7, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF,
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0xF, 0x7, 0x3, 0x0, 0x0, 0x0, 0xC0,
0xE0, 0x60, 0x20, 0x20, 0x60, 0xE0, 0xE0, 0xE0, 0x0, 0x0, 0x80, 0xC0, 0xE0, 0x60, 0x20, 0x60,
0x60, 0xE0, 0xE0, 0xE0, 0x0, 0x0, 0x80, 0xC0, 0x60, 0x60, 0x20, 0x60, 0x60, 0xE0, 0xE0, 0x0,
0x0, 0x0, 0xE0, 0xE0, 0x0, 0x0, 0x0, 0xE0, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xE0,
0x60, 0x60, 0x60, 0x60, 0xE0, 0x80, 0x0, 0x0, 0x0, 0xE0, 0xE0, 0x0, 0x0, 0x0, 0xE0, 0xE0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x3, 0x7, 0x1F, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xF1, 0xE3,
0xE3, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFC, 0x7F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xF0, 0xE0, 0x80, 0x0, 0x0, 0x0, 0xC,
0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0x7F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x7, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1C, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFE, 0xFC, 0xF8,
0xF8, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF,
0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xE0, 0xC0, 0xC0, 0xC0, 0xFF, 0x7F, 0x0, 0x0, 0x1E, 0x7F,
0xE1, 0xC0, 0xC0, 0xC0, 0xC0, 0x61, 0xFF, 0xFF, 0x0, 0x0, 0xFE, 0xFF, 0x1, 0x0, 0x0, 0x0,
0xFF, 0xFF, 0x0, 0x0, 0x21, 0xF9, 0xF8, 0xDC, 0xCC, 0xCF, 0x7, 0x0, 0xC0, 0xFF, 0xFF, 0xC0,
0x80, 0x0, 0xFF, 0xFF, 0xC0, 0xC0, 0x80, 0x0, 0x0, 0xFF, 0xFF, 0x0, 0x0, 0x1F, 0x7F, 0xF9,
0xC8, 0xC8, 0xC8, 0xC8, 0x79, 0x39, 0x0, 0x0, 0x71, 0xF9, 0xD8, 0xCC, 0xCE, 0x47, 0x3, 0x0,
0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xC0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC0,
0xC0, 0x0, 0x0, 0x0, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0x0, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0x80,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0x80, 0xC0, 0xC0, 0xC0, 0xC0,
0xC0, 0x80, 0x0, 0x0, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0xC0, 0xC0, 0x0,
0x0, 0x0, 0xC0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0x80, 0xC0,
0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x0, 0x0, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};
/*// Inicialización del Display Paguina 51
void glcd_init()
{
//output_low(GLCD_CS); // Select the chip
//output_low(GLCD_RESET); // PASO 1
// Se estable 50 ms para estabilizar la tensión de alimentación.
//delay_ms(5); // PASO 2
//output_high(GLCD_RESET); // PASO 3
output_low(GLCD_SI); // Initialize SCL
output_low(GLCD_SCK); // Initialize SDA
output_low(GLCD_CS);
output_low(GLCD_RESET); // PASO 1
// Se estable 50 ms para estabilizar la tensión de alimentación.
delay_ms(50); // PASO 2
output_high(GLCD_RESET);
//0b10100010 // seleccionamos el voltaje requerido para el display // PASO 5
glcd_command(GLCD_CMD_BIAS_9);
// Modo Horizontal de la pantalla NORMAL
glcd_command(GLCD_CMD_HORIZONTAL_NORMAL); //0b10100000 // // PASO 6
// Modo Vertical de la pantall NORMAL
glcd_command(GLCD_CMD_VERTICAL_NORMAL); //0b11000000 // PASO 7
// Posición de inicio en la memoria RAM.
glcd_command(GLCD_CMD_DISPLAY_START); //0b10000000
// Solo utiliza la fuente de alimentación externa. Turn on voltage converter (VC=1,VR=0,VF=0)
glcd_command(GLCD_CMD_POWER_CONTROL | 0x4); // 0b00101000
delay_ms(50);
// Solo utiliza la fuente de alimentación externa. Turn on voltage converter (VC=1,VR=1,VF=0)
glcd_command(GLCD_CMD_POWER_CONTROL | 0x6); // 0b00101000
delay_ms(50);
// Solo utiliza la fuente de alimentación externa. Turn on voltage converter (VC=1,VR=1,VF=0)
glcd_command(GLCD_CMD_POWER_CONTROL | 0x7); // 0b00101000
delay_ms(10);
// Se selecciona el valor interno de resistencia. Por default usamos un valor medio
glcd_command(CMD_SET_RESISTOR_RATIO | 0x15); // 0b00100000
output_high(GLCD_CS);
}
*/
void glcd_init()
{
output_low(GLCD_SI); // Initialize SCK
output_low(GLCD_SCK); // Initialize SDA
output_low(GLCD_CS);
output_low(GLCD_RESET); //Datasheet says "wait for power to stabilise
delay_ms(50);
output_high(GLCD_RESET);
//datasheet 1ms
delay_us(500);
//0b10100010 // seleccionamos el voltaje requerido para el display
glcd_command(GLCD_CMD_BIAS_7);
// Modo Horizontal de la pantalla NORMAL
glcd_command(GLCD_CMD_HORIZONTAL_NORMAL); //0b10100000 //
// Common output mode select.
glcd_command(COMMON_OUTPUT_MODE_SELECT); // 0b11000***
// Set internal resistor Vo voltage.
glcd_command(CMD_SET_RESISTOR_RATIO | 0x02);
glcd_command(GLCD_CMD_VERTICAL_NORMAL); //0b11000000
// Reset start position to the top
glcd_command(GLCD_CMD_DISPLAY_START);
//Electronic volume mode set
glcd_command(GLCD_ELECTRONIC_VOLUME_MODE_SET); //0b10000001
//Electronic volume register set
glcd_command(GLCD_CMD_VOLUME_REGISTER_SET | 0x25); //0b00000000
//Power Controler SET. See page 31 table 8. Only the internal power supply is used.
glcd_command(GLCD_CMD_POWER_CONTROL | 0x07); // 0b00101000
// Reset start position to the top
glcd_command(GLCD_CMD_DISPLAY_START);
/// Turn the display on
glcd_command(GLCD_CMD_DISPLAY_ON);
// Unselect the chip
output_high(GLCD_CS);
}
void glcd_command(char command) {
int n;
output_low(GLCD_RS); // A0 low para que el dato enviado sea un comando
delay_us(5);
output_low(GLCD_CS); // Seleccionamos el chip
delay_us(5);
// output_high(GLCD_SCK);
//0x80 = 0b10000000
//El primer bit que pone en PIN es el mas significativo (8) y mediante (command & 0x80) se verifica si dicho bit es 1 o 0, para escribir 1 o 0 en SDA.
//Luego se realiza un rotación con command <<= 1 para comparar los bits menos significatos. De esta forma se transmite el comando.
for (n = 0; n < 8; n++) {
if (command & 0x80) { //Si la comparación es 1 se pone GLCD_SDA a 1 logico, Si es 0 GLCD_SDA se pone a 0.
output_high(GLCD_SI); // Pin de datos
} else {
output_low(GLCD_SI);
}
output_high(GLCD_SCK);
delay_us(100);
output_low(GLCD_SCK); // Reloj regresa a 1
delay_us(50);
command <<= 1;
}
// Unselect the chip
output_high(GLCD_CS);
}
void glcd_data(unsigned char data) {
int n;
output_high(GLCD_RS); // A0 HIGH para que el dato enviado sea un data
delay_us(5);
output_low(GLCD_CS); // Seleccionamos el chip
delay_us(5);
for (n = 0; n < 8; n++) {
if (data & 0x80) {
output_high(GLCD_SI);
} else {
output_low(GLCD_SI);
}
output_high(GLCD_SCK);
delay_us(100);
output_low(GLCD_SCK); // Reloj regresa a 1
delay_us(50);
data <<= 1;
}
// Unselect the chip
output_high(GLCD_CS);
}
void clear_display(void)
{
int8 p,c;
for(p = 0; p < 8; p++) {
glcd_command(GLCD_CMD_SET_PAGE | p);
for(c = 0; c < 129; c++) {
glcd_command(GLCD_CMD_COLUMN_LOWER | (c & 0xf));
glcd_command(GLCD_CMD_COLUMN_UPPER | ((c >> 4) & 0xf));
glcd_data(0x0);
}
}
}
void clear(void){
memset(buffer,0,1024);
}
void display(void){
int8 c, p;
for(p = 0; p < 8; p++) {
glcd_command(GLCD_CMD_SET_PAGE | pagemap[p]);
glcd_command(GLCD_CMD_COLUMN_LOWER | (0x00 & 0xf));
glcd_command(GLCD_CMD_COLUMN_UPPER | ((0x00 >> 4) & 0xf));
glcd_command(CMD_RMW);
glcd_data(0xff);
for(c = 0; c < 128; c++) {
glcd_data(buffer[(128*p)+c]);
}
}
}
void drawchar(int8 x, int8 line, char c){
for (int8 i =0; i<5; i++ ) {
// buffer[x + (line*128) ] = font[ (c*5) + i];
x++;
}
}
void drawstring(int8 x, int8 line, char *c){
while (c[0] != 0) {
drawchar(x, line, c[0]);
c++;
x += 6; // 6 pixels wide
if (x + 6 >= SCREEN_WIDTH) {
x = 0; // ran out of this line
line++;
}
if (line >= (SCREEN_HEIGHT/8))
return; // ran out of space :(
}
}
// the most basic function, set a single pixel
void setpixel(int8 x, int8 y, int8 color) {
if ((x >= SCREEN_WIDTH) || (y >= SCREEN_HEIGHT))
return;
// x is which column
if (color)
buffer[ x+ (y / 8) * 128] |= (1 << (7 - (y % 8)));
else
buffer[ x+ (y / 8) * 128] &= ~(1 << (7 - (y % 8)));
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Dec 12, 2021 11:57 pm |
|
|
Look closely at your schematic, at pins D0 and D1 on the PIC.
Just to the left of the PIC symbol, you have a dot, connecting
the D0 and D1 lines together. This means CLK and SI are shorted.
That dot should be removed. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19505
|
|
Posted: Mon Dec 13, 2021 3:34 am |
|
|
Also, why not just use the CCS SPI code.
Much faster, less to go wrong. The #use spi command offers a software spi
in just one direction like you need here. Though I cannot see a specification
for a minimum spi frequency, some chips do have this hidden inside. You
are clocking the SPI so slowly, that I wonder if this could be a problem.... |
|
|
Pichuqy_1
Joined: 03 Aug 2010 Posts: 38
|
|
Posted: Mon Dec 13, 2021 1:06 pm |
|
|
Pcm Programmer: You are right, but this is just a schematic mistake. In the real board it is correct. Thanks for make me know.
Ttelmah: I know you are right. The problem is that I don't how to configure it yet. On the other hand, I'm not sure what kind of SPI mode the display use as well as the frequency. The datasheet doesn't specify anything about it as you mention.
What is the #USE SPI command you recommend in this case? Can I choose whichever pin I want? I'll make a try, I really want to turn this display on.
Thanks so much!
Emilio |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 13, 2021 2:14 pm |
|
|
Quote: | void glcd_init()
{
output_low(GLCD_SI); // Initialize SCK
output_low(GLCD_SCK); // Initialize SDA
output_low(GLCD_CS);
|
Chip select should be initialized to a high level. Low is the active state.
You want to initialize it to the inactive state. Change that line to: Code: |
output_high(GLCD_CS); |
|
|
|
Pichuqy_1
Joined: 03 Aug 2010 Posts: 38
|
|
Posted: Mon Dec 13, 2021 6:46 pm |
|
|
Thanks for your reply. What do you think about the clock's initial state? According to the SPI diagram, it should be initialized to a high level too, isn't it? |
|
|
Pichuqy_1
Joined: 03 Aug 2010 Posts: 38
|
|
Posted: Mon Dec 13, 2021 7:04 pm |
|
|
This is the clock and data diagram that I got in the LCD when the program executes the code 0b10100011. I think it is ok.
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 13, 2021 7:29 pm |
|
|
I'm not sure how you get that timing diagram, because your posted
code uses SPI Mode 0, but the timing diagram shows SPI Mode 3.
SPI Mode 0 has the clock idle low, and Mode 3 has it idle high.
Those two modes are usually interchangeable for chips that use
either one. |
|
|
Pichuqy_1
Joined: 03 Aug 2010 Posts: 38
|
|
Posted: Mon Dec 13, 2021 8:00 pm |
|
|
The reason is that I've tried with the two SPI mode, 1 and 3, in order to make it works and maybe I took the picture and then I change the code.
So, one of my doubts here is: according to the datasheet this display uses the SPI mode 3, right?
Thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 13, 2021 8:12 pm |
|
|
That is correct. |
|
|
Pichuqy_1
Joined: 03 Aug 2010 Posts: 38
|
|
Posted: Wed Dec 22, 2021 8:20 pm |
|
|
Hello everybody!
Unfortunately, I've not found a way to turn on the display. I've been struggling with it for weeks, but I am not able to make it work. I'd like to share with you the changes I made so as to find together the mistake in my code.
1) First, I changed the XT 4 MHz for 16 MHz. I thought that maybe with 4 MHz the clock wasn't fast enough. Even though the communication is working perfectly, the LCD doesn't work. The clock is running at 13 KHz. See the picture below.
2) Second, I'm using the #use spi mode instead of the code one.
3) Third, I've been testing two different initialization ways, one at a time of course. I'll share it below, please let me know if you notice something wrong. I'm losing my cool with this program.
This is the main.c file
Code: |
#include <18F46K20.h>
#fuses HS,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOPBADEN // el fuse
#use delay(clock=16000000)
#use STANDARD_IO(B)
#use STANDARD_IO(C)
#use STANDARD_IO(D)
#use STANDARD_IO(E)
#include "ST7565R_2.h"
void main(void)
{
do{
glcd_init();
clean_LCD(0x00);
PUNTO_LCD(20,20,0x01);
Transferir_LCDRAM_LCD();
}while(true);
|
This is the library file. I'll add only the most important routines.
Code: |
#include <stdlib.h>
const int8 pagemap[] = {3, 2, 1, 0, 7, 6, 5, 4};
#use spi(MASTER, CLK=PIN_D0, DO=PIN_D1, FORCE_SW, MODE=3, BITS=8, MSB_FIRST, stream=BUSSPI)
void glcd_init()
{
output_low(GLCD_RS);
output_high(GLCD_CS);
output_low(GLCD_RESET);
delay_ms(1);
output_high(GLCD_RESET);
delay_ms(1);
glcd_command(GLCD_CMD_DISPLAY_ON); //0xAF
glcd_command(GLCD_CMD_DISPLAY_START); //0x40
glcd_command(GLCD_CMD_HORIZONTAL_NORMAL); //0xa1
glcd_command(GLCD_CMD_DISPLAY_NORMAL); // 0xa6
glcd_command(GLCD_CMD_ALL_NORMAL); // 0xa4
glcd_command(GLCD_CMD_BIAS_9); // 0xa2
glcd_command(COMMON_OUTPUT_MODE_SELECT); //0xc0
glcd_command(GLCD_ALL_ON); //Ox2f
glcd_command(CMD_SET_RESISTOR_RATIO); //0x25
glcd_command(Booster_Ratio); glcd_command(Booster_Ratio_1); //0b11111000 ; 0b00000000
glcd_command(GLCD_ELECTRONIC_VOLUME_MODE_SET); glcd_command(GLCD_CMD_VOLUME_REGISTER_SET ); //0b10000001 ; 0b00100001
}
*/
void glcd_init_1()
{
output_low(GLCD_RS);
output_high(GLCD_CS);
output_low(GLCD_RESET);
delay_ms(1);
output_high(GLCD_RESET);
delay_ms(1);
glcd_command(GLCD_CMD_RESET);
//b10100011 //
glcd_command(GLCD_CMD_BIAS_9);
glcd_command(GLCD_CMD_HORIZONTAL_NORMAL); //0b10100000 //
// Common output mode select.
glcd_command(COMMON_OUTPUT_MODE_SELECT); // 0b11000***
glcd_command(CMD_SET_RESISTOR_RATIO | 0x02);
glcd_command(GLCD_CMD_VERTICAL_NORMAL); //0b11000000
glcd_command(GLCD_CMD_DISPLAY_START);
//Electronic volume mode set
glcd_command(GLCD_ELECTRONIC_VOLUME_MODE_SET);
//0b10000001
//Electronic volume register set
glcd_command(GLCD_CMD_VOLUME_REGISTER_SET | 0x25); //0b00000000
//Power Controler SET. See page 31 table 8. Only the internal power supply is used.
glcd_command(GLCD_CMD_POWER_CONTROL | 0x07); // 0b00101000
// Reset start position to the top
glcd_command(GLCD_CMD_DISPLAY_START);
/// Turn the display on
glcd_command(GLCD_CMD_DISPLAY_ON);
}
*/
void glcd_command(char command) {
output_low(GLCD_CS);
// delay_ms(1);
output_low(GLCD_RS);
delay_us(10);
spi_xfer(BUSSPI,command);
}
void glcd_data(unsigned char data) {
output_low(GLCD_CS);
//delay_ms(1);
output_high(GLCD_RS);
delay_us(10);
spi_xfer(BUSSPI,data);
}
unsigned char LCDRAM[8][128];
void clean_LCD(unsigned char DesdeDonde)
{
unsigned char i;
unsigned char j;
//Confi_LCDG();
for(i = DesdeDonde; i < 8;i++)
{
//LCD_Instrucciones(i); // LCD lista para instrucciones
glcd_command(0xb0 | i); // select page 0~7
glcd_command(0x10); // start form column 0
glcd_command(0x00); // (2byte command)
for(j = 0; j < 128; ++j)
{
glcd_data(0x00);//LCD_ESCRIBIR(0,SicoyLogo[s++]); // Los pixeles encendidos a OFF
LCDRAM[i][j] = 0;
}
}
}
const unsigned char DOSENE [8] = { 1,2,4,8,16,32,64,128};
void PUNTO_LCD(unsigned char x, unsigned char y,unsigned char color)
{
unsigned char data;
unsigned char auxi;
data = LCDRAM[y/8][x];
auxi = DOSENE[ y%8];
if (color)
data = data | auxi;
else
data = data & (~auxi);
LCDRAM[y/8][x] = data;
}
void Transferir_LCDRAM_LCD(void)
{
unsigned char i;
unsigned char j;
for(i = 0; i < 8; ++i)
{
//LCD_Instrucciones(i); // LCD lista para instrucciones
glcd_command(0xb0 | i); // select page 0~7
glcd_command(0x10); // start form column 0
glcd_command(0x00); // (2byte command)
for(j = 0; j < 128; ++j) glcd_data(LCDRAM[i][j]);//LCD_ESCRIBIR(0,solintecelogo[s++]); // Los pixeles encendidos a OFF
}
delay_us(150);
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 23, 2021 5:42 am |
|
|
I translated the init code from these two web pages.
Try it and see if it works.
https://github.com/adafruit/ST7565-LCD/blob/master/c/stlcd.c
https://github.com/adafruit/ST7565-LCD/blob/master/c/stlcd.h
The code below uses your pin numbers. But it's doing the reset
and the Chip Select differently than your code. Try it.
Code: |
//------------------------------------
void glcd_command(unsigned int8 cmd)
{
output_low(GLCD_RS);
delay_us(10);
spi_xfer(BUSSPI, cmd);
}
//---------------------------------------
void glcd_data(unsigned int8 data)
{
output_high(GLCD_RS);
delay_us(10);
spi_xfer(BUSSPI, data);
}
//--------------------------------------------
void glcd_set_brightness(unsigned int8 value)
{
glcd_command(0x81);
glcd_command(value & 0x3F);
}
//---------------------------------
void glcd_init(void)
{
output_low(GLCD_CS); // Set it low (TRUE) and keep it there
output_low(GLCD_RESET);
delay_ms(500); // If this works, try 50 ms
output_high(GLCD_RESET);
delay_ms(100); // If this works, try 10 ms
glcd_command(0xA3); // Set bias = 7
glcd_command(0xA0); // Set ADC = normal
glcd_command(0xC0); // Set COM = normal
glcd_command(0x40); // Set display start line
glcd_command(0x28 | 0x04); // Turn on Voltage converter
delay_ms(50);
glcd_command(0x28 | 0x06); // Turn on Voltage reg.
delay_ms(50);
glcd_command(0x28 | 0x07); // Set Power control
delay_ms(10);
glcd_command(0x20 | 0x06); // Set resistor ratio
delay_ms(10);
glcd_command(0xAF); // Display on
glcd_command(0xA4); // Set Allpts normal
glcd_set_brightness(0x18);
clear_display();
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Thu Dec 23, 2021 6:24 am |
|
|
I'm wondering if you should put a
delay_ms(500);
in main() before you try to access the LCD
This has always been required for text LCDs as it gives time for the LCD module to properly powerup. I downloaded a version of the GLCD datasheet but didn't see a spec on 'powerup delay before accessing the LCD'.
If you put the code it, try it and it still doesn't work, you've eliminated it as a possible cause.
Are you 100% sure the PIC and LCD are connected properly ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19505
|
|
Posted: Mon Dec 27, 2021 7:15 am |
|
|
To use standard SPI, select MODE=3. This is what the display is doing.
Commands would then become:
Code: |
#use SPI(MASTER, bits=8, baud=1000000, MODE=3, DO=PIN_B1, CLK=
PIN_B0, STREAM=DISPLAY)
void glcd_command(char command)
{
int8 dummy; //This is not needed on the latest compilers
output_low(GLCD_CS); // Select the display
output_low(GLCD_RS); // Say this is a command write (this is read
//on the eighth clock)
dummy=spi_xfer(DISPLAY, command);
//forcing a read ensures clocking has finished - not needed on new
//compilers
output_high(GLCD_CS); //idle HIGH
output_high(GLCD_RS); //ensure this defaults to DATA
}
void glcd_data(char data)
{
int8 dummy; //This is not needed on the latest compilers
output_low(GLCD_CS); // Select the display
output_high(GLCD_RS); // Say this is a DATA write (this is read
//on the eighth clock), so can be done at any point before data is sent.
dummy=spi_xfer(DISPLAY, data);
//forcing a read ensures clocking has finished - not needed on new
//compilers
output_high(GLCD_CS); //idle HIGH
}
|
Agree wholeheartedly with Temtronic. Pause at the start before trying to
initialise the display. PIC's wake up very quickly as the supply rises. A lot
of peripheral devices do not, so there has to be a pause before starting to
talk to them.
Have your wake up code do:
Code: |
void glcd_init(void)
{
//0b10100010 // seleccionamos el voltaje requerido para el display
glcd_command(GLCD_CMD_BIAS_7);
// Modo Horizontal de la pantalla NORMAL
glcd_command(GLCD_CMD_HORIZONTAL_NORMAL); //0b10100000 //
// Common output mode select.
glcd_command(COMMON_OUTPUT_MODE_SELECT); // 0b11000***
// Set internal resistor Vo voltage.
glcd_command(CMD_SET_RESISTOR_RATIO | 0x02);
glcd_command(GLCD_CMD_VERTICAL_NORMAL); //0b11000000
// Reset start position to the top
glcd_command(GLCD_CMD_DISPLAY_START);
//Electronic volume mode set
glcd_command(GLCD_ELECTRONIC_VOLUME_MODE_SET); //0b10000001
//Electronic volume register set
glcd_command(GLCD_CMD_VOLUME_REGISTER_SET | 0x25); //0b00000000
//Power Controler SET. See page 31 table 8. Only the internal power supply is used.
glcd_command(GLCD_CMD_POWER_CONTROL | 0x07); // 0b00101000
// Reset start position to the top
glcd_command(GLCD_CMD_DISPLAY_START);
/// Turn the display on
glcd_command(GLCD_CMD_DISPLAY_ON);
}
void main(void)
{
output_low(RES);
output_high(CS); //ensure idles high.
delay_ms(100); //ensure supply is stable before reset.
output_high(RES);
delay_ms(1); //must wait after reset before first instruction.
glcd_init(); //now send initialisation
/////// other code
}
|
Your problem may actually be that your initialisation is much too slow.
The data sheet specifically says that the initialisation code must be sent
within 5mSec of reset being released. Your SPI is so slow that this is not
going to happen...
You have to send a total of 9 commands in 4mSec max, so the SPI must
run at about 20KHz to do this. Your current SPI is running at 150uSec/bit
so only about 6KHz.... |
|
|
Pichuqy_1
Joined: 03 Aug 2010 Posts: 38
|
|
Posted: Sun Jan 09, 2022 3:44 pm |
|
|
Thanks for your reply. The display is working perfectly right now!! |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|