Hola a todos.
Queria consultarles si tienen conocimiento donde puedo conseguir una libreria para CCS C para un LCD SPI con controlador ST7565R. Lo busqué en el foro pero hay poca información al respecto.
Muchas gracias.
Saludos a todos
Gracias Dominus por el aporte. Lo voy a intentar y voy subiendo los avances al foro. Asi lo tenemos todos (si logro hacerlo funcionar) :oops:
Un abrazo
Código: C
if (command & 0x80) // Porque utiliza 0x80?? { output_high(GLCD_SDA); } else { output_low(GLCD_SDA); }
Código: C
if (command & 0x80) // Porque utiliza 0x80?? { output_high(GLCD_SDA); } else { output_low(GLCD_SDA); }
Está utilizando un PIN como salida SPI:
EL primer bit que pone en el PIN es el 8 y mediante (command & 0x80) verificas si dicho bit es 1 ó 0, para escribir 1 o cero en SDA
Luego el bit 7 pasa al 8, el 6 al 7, etc mediante command <<= 1; es decir lo rotas a la izquierda una vez y repites de nuevo el if hasta enviar los 8 bits del byte de comando.
Claro que si tienes un módulo SPI en tu micro, es mucho mejor utilizar eso, pero para pruebas estaría bien por el momento.
Hola DominusDRR. Gracias por la aclaración. Voy a tratar de desarrollar la librería para que se pueda utilizar tanto por software SPI y por hardware SPI.
Quedaría así :?:
if (command & 0x80)
{
output_high(GLCD_SDA);
output_high(GLCD_SCL);
}
else
{
output_low(GLCD_SDA);
output_low(GLCD_SCL);
}
Hola DominusDRR. Gracias por la aclaración. Voy a tratar de desarrollar la librería para que se pueda utilizar tanto por software SPI y por hardware SPI.
Quedaría así :?:
if (command & 0x80)
{
output_high(GLCD_SDA);
output_high(GLCD_SCL);
}
else
{
output_low(GLCD_SDA);
output_low(GLCD_SCL);
}
Deberías conocer que modo de operación trabaja tu LCD, en SPi hay cuatro.
(https://aws1.discourse-cdn.com/arduino/original/4X/4/a/0/4a0f0eb9ff1f294710aec4f56b17016762163f9a.png)
Debería existir un retardo al crear la señal de reloj. Ahí le estás dando a toda la velocidad que puede ejecutar el microcontrolador. O sea la pregunta es: Sin retardos a que frecuencia es la señal de reloj.
Sin retardos en el código y suponiendo que tengo el micro corriendo a 20 Mhz la frecuencia del de la señal de reloj máxima quedaría: para 20 mhz--> 20/4=5 Mbps ----> 1/5 mhz=0,0000002 seg =0,2uS por ciclo de instrucción. Si utilizo el SPI por hardware, podré alcanzar una mayor velocidad?
Luego, como se muestra en el diagrama de arriba, habla que A0 se utiliza para determinar si los datos ingresados al display son, comandos o datos. Pero esté pin tampoco está fisicamente. Estoy tratando de ver a que se refieron los pin RES (supongo reset) y RS. Los pines 10,11,12,13 ¿?
A0 - sometiimes called RS
Otra duda que me surge, es la siguiente:
En la hoja de datos dice que este controlador, ST7565R, tiene dos terminales para la selección de chip. /CS1 y CS2. Cuando /CS1 =L y CS2 = H se habilita la recepción de datos. La cuestión con esto es que en el Display fisico solo se puede ver /CS, lo cual me hace suponer que CS2 está siempre con un estado lógico fijo.
Hola otra ves, :-/
Parte del código que estoy terminando para esta librería, tiene la siguiente función. pgm_read_byte();. Se suponia que el codigo estaba escrito en C y esto parece ser una instrucción de ardruino.. :lol: Lo que pude ver es que esta instrucción funciona como macro que lee una palabra guardada en una posición de memoria. El código es el siguiente:
void drawchar(int8 x, int8 line, char c){
for (int8 i =0; i<5; i++ ) {
buffer[x + (line*128) ] = pgm_read_byte(font+(c*5)+i);
x++;
}
}
Mi idea es utilizar la función strcpy para reemplazarla. Esta función se utiliza para copiar una cadena de caracteres (fuente) en el lugar que ocupaba otra (destino). Pero no estoy seguro:
void drawchar(int8 x, int8 line, char c){
for (int8 i =0; i<5; i++ ) {
buffer[x + (line*128) ] = strcpy (font, (c*5) + i);
x++;
}
}
Voy a seguir tu consejo de escribir una simple coordenada en el Display, haber si puedo lograrlo.
Ya voy subiendo mas avances. Tengo que encender esta cosa.. :lol:
Estoy empezando otra vez, repasando todo porque no logro inicializar el display.
Con respecto a la comunicación estoy capturando los datos del clock y data para ver como están sincronizados. El dato que estoy enviando al PIC es 0b10100011. Como puede verse en la imagen el byte está presente en el pin GLCD_SI y el clock también. Ustedes ven algo mal con respecto a esto? (quiero descartar que no sea un problema de comunicación). El código para esto lo listo abajo.
El programa ingresa a glcd_init(); y luego ejecuta el primer comando que es el que se ve en la foto.
img (https://i.ibb.co/LYZ6pb8/Whats-App-Image-2021-12-11-at-21-42-59.jpg) (https://ibb.co/BcCjsdt) /img
#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_1.h"
void main(void)
{
output_high(GLCD_CS); // Seleccionamos el chip
output_high(GLCD_SCK); // Reloj en alto
glcd_init();
glcd_command(GLCD_CMD_DISPLAY_ON);
glcd_command(GLCD_CMD_ALL_NORMAL);
glcd_contrast(0x5);
do{
setpixel(20, 20, WHITE);
display();
}while(true);
}
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(500); // PASO 2
output_high(GLCD_RESET); // PASO 3
//0b10100010 // seleccionamos el voltaje requerido para el display // PASO 5
glcd_command(GLCD_CMD_BIAS_7);
// 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 | 0x6); // 0b00100000
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);
if (command & 0x80) { //Si la comparación es 1 se pone GLCD_SDA a 1 lógico, Si es 0 GLCD_SDA se pone a 0.
output_high(GLCD_SI); // Pin de datos
} else {
output_low(GLCD_SI);
}
output_low(GLCD_SCK);
delay_us(100);
output_high(GLCD_SCK); // Reloj regresa a 1
delay_us(50);
command <<= 1;
}
// Unselect the chip
output_high(GLCD_CS);
}
Me parece que te falta un pulso más en el reloj.
img (https://i.ibb.co/LYZ6pb8/Whats-App-Image-2021-12-11-at-21-42-59.jpg) (https://ibb.co/BcCjsdt) /img
Estoy empezando otra vez, repasando todo porque no logro inicializar el display.
Con respecto a la comunicación estoy capturando los datos del clock y data para ver como están sincronizados. El dato que estoy enviando al PIC es 0b10100011. Como puede verse en la imagen el byte está presente en el pin GLCD_SI y el clock también. Ustedes ven algo mal con respecto a esto? (quiero descartar que no sea un problema de comunicación). El código para esto lo listo abajo.
El programa ingresa a glcd_init(); y luego ejecuta el primer comando que es el que se ve en la foto.
img (https://i.ibb.co/LYZ6pb8/Whats-App-Image-2021-12-11-at-21-42-59.jpg) (https://ibb.co/BcCjsdt) /img
#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_1.h"
void main(void)
{
output_high(GLCD_CS); // Seleccionamos el chip
output_high(GLCD_SCK); // Reloj en alto
glcd_init();
glcd_command(GLCD_CMD_DISPLAY_ON);
glcd_command(GLCD_CMD_ALL_NORMAL);
glcd_contrast(0x5);
do{
setpixel(20, 20, WHITE);
display();
}while(true);
}
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(500); // PASO 2
output_high(GLCD_RESET); // PASO 3
//0b10100010 // seleccionamos el voltaje requerido para el display // PASO 5
glcd_command(GLCD_CMD_BIAS_7);
// 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 | 0x6); // 0b00100000
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);
if (command & 0x80) { //Si la comparación es 1 se pone GLCD_SDA a 1 lógico, Si es 0 GLCD_SDA se pone a 0.
output_high(GLCD_SI); // Pin de datos
} else {
output_low(GLCD_SI);
}
output_low(GLCD_SCK);
delay_us(100);
output_high(GLCD_SCK); // Reloj regresa a 1
delay_us(50);
command <<= 1;
}
// Unselect the chip
output_high(GLCD_CS);
}
El dato que está representado en el diagrama es el 0b10100011. Es el primero en la rutina de inicialización. No coincide porque cuando tomé la foto lo cambié. Lo importante es que se represente envíe correctamente en este caso.
Estoy pensando en utilizar las instrucciones de SPI de CCS C por software para hacer la comunicación y evitar estos tipos de errores. Que opinan?
Gracias.
Hola DominusDRR. Gracias por la ayuda.
Probé el código que me pasaste y el display no se inicializa. En el código de la función de inicialización que subiste, lo escribiste teniendo en cuenta los pasos sugeridos por el datasheet?
Muchas gracias por tu aporte. Yo te consultaba porque comparé las rutinas con el datasheet y hay algunas diferencias. De todas formas, el mismo datasheet dice que ellos recomiendan inicializarlo de esa forma, lo que entiendo que significa que puede haber otras.. :shock:
Con la configuración SPI por software y utilizando el scope, se puede ver que la frecuencia del spi es de 13 Khz. Me parece baja, y aunque no se cual es la mínima y/o máxima que soporta este display, voy a cambiarle el cristal para mejorar un poco la frecuencia.
Ya empiezo a descartar problemas en la comunicación; es configuración como bien decís DominusDRR. Este display me está volviendo loco, debería ser fácil :5] :5] :lol: :lol:
En la imagen se ve como se envía el código b10100011. Según el datasheet tiene que enviarse el bit mas significativo primero.
(https://i.ibb.co/Yfx0C3b/Whats-App-Image-2021-12-19-at-22-19-16.jpg) (https://ibb.co/ssZWf2t)
Compañeros... El display está funcionando. Obviamente tenía problemas en la inicialización, como siempre lo dudé. Pero quedó funcionando.
Solo, hay un problema que aún no puedo resolver. El punto (0,0) está corrido, es decír que las columnas están fuera de posición. Por lo tanto cuando escribo algo en esas coordenas no se vé. Según el datasheet hay dos registros para desplazar las columnas, pero ya los modifiqué y no cambia. :5]
Esta es la descripción de los registros para desplazar las columnas:
(https://i.ibb.co/dLQBTk1/Captura-de-pantalla-2021-12-26-195447.jpg) (https://ibb.co/3M013SG)
Y esta es la instrucción donde se utiliza, que ya está programada para que inicie en (0,0) pero no lo hace.Código: C
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); }
(https://i.ibb.co/xDjcB9V/20211225-172346.jpg) (https://ibb.co/805RfvF)
ver avatar online gratis en español completa (https://es.imgbb.com/)
Hola DominusDRR. Gracias por la respuesta.
Porque dices que LCDRAM[0][0] que debe ser igual a 0x80?
Feliz año nuevo!
Un abrazo
Hola DominusDRR. Gracias por la respuesta.
Porque dices que LCDRAM[0][0] que debe ser igual a 0x80?
Feliz año nuevo!
Un abrazo
Gracias DominusDRR! Ya puedo utilizar el display con normalidad!
((:-)) ((:-)) ((:-))