CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Initialization problems display ST7565R
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Pichuqy_1



Joined: 03 Aug 2010
Posts: 38

View user's profile Send private message MSN Messenger

Initialization problems display ST7565R
PostPosted: Sun Dec 12, 2021 5:06 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Dec 12, 2021 11:57 pm     Reply with quote

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: 19539

View user's profile Send private message

PostPosted: Mon Dec 13, 2021 3:34 am     Reply with quote

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

View user's profile Send private message MSN Messenger

PostPosted: Mon Dec 13, 2021 1:06 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Dec 13, 2021 2:14 pm     Reply with quote

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

View user's profile Send private message MSN Messenger

PostPosted: Mon Dec 13, 2021 6:46 pm     Reply with quote

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

View user's profile Send private message MSN Messenger

PostPosted: Mon Dec 13, 2021 7:04 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Dec 13, 2021 7:29 pm     Reply with quote

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

View user's profile Send private message MSN Messenger

PostPosted: Mon Dec 13, 2021 8:00 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Dec 13, 2021 8:12 pm     Reply with quote

That is correct.
Pichuqy_1



Joined: 03 Aug 2010
Posts: 38

View user's profile Send private message MSN Messenger

PostPosted: Wed Dec 22, 2021 8:20 pm     Reply with quote

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.
Twisted Evil
Twisted Evil

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

View user's profile Send private message

PostPosted: Thu Dec 23, 2021 5:42 am     Reply with quote

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: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Dec 23, 2021 6:24 am     Reply with quote

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: 19539

View user's profile Send private message

PostPosted: Mon Dec 27, 2021 7:15 am     Reply with quote

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.... Sad
Pichuqy_1



Joined: 03 Aug 2010
Posts: 38

View user's profile Send private message MSN Messenger

PostPosted: Sun Jan 09, 2022 3:44 pm     Reply with quote

Thanks for your reply. The display is working perfectly right now!!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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