PIC32+GRAPHIC LCD 128*64 KS0107/8

Stampa
( 4 Votes ) 
Valutazione attuale:  / 4
ScarsoOttimo 
Categoria principale: Elettronica Categoria: Microcontrollori
Data pubblicazione
Scritto da teppei68 Visite: 2706

INTRODUZIONE:

Vedremo in questo articolo la solita millefori con il PIC32 che pilota un display grafico 128*64 con controller KS0107/8, come prefazione sul 32 e LCD

conviene andare a visitare le pubblicazioni precedenti perchè chiaramente non ripeterò concetti già esposti smiley!

vediamo alcune foto del progetto:

Possiamo notare questo circuitino, alla sinistra della millefori, con tre fili  che serve per creare la tensione negativa rispetto a massa di -5V necessaria per la regolazione del contrasto, per questo si è utilizzato un un lm2954(SMD) recuperato da una scheda e montato a sua volta con pochi componenti su di un millefori, allego datasheet files/teppei68/lm2594.pdf.

la figura n. 25 è il circuito realizzato, per questo scopo, si possono utilizzare altri integrati tra cui l'ne555 o l'icl7660.

A differenza dei display alfanumerici i grafici non hanno nessun tipo di carattere memorizzato in qualche area di memoria quindi se con l'alfanumerico per visualizzare una "a" bastava fornire il suo corrispettivo codice ascii 65, nel display grafico questo non accade; il disegno della prima foto è stato creato con un programma PINTA (ubuntu) ma che trova il suo ononimo PAINT nel winzoz si impostano gli attributi dei pixel 128*64 si crea un disegnino e poi con un altro programma  GRAPHIC LCD EDITOR si "traduce" il disegno in una const char BMP[1024], fatto questo si inserisce la variabile nel sorgente e da lì si può visualizzare nel display... poi vedremo come, tutto questo con quasi 128K di memoria disponibile del 32 si può fare ma chiaramente occupare spazio con una matrice di 8192 bytes (128*64=8192)  non ha molto senso, la soluzione è una sola utilizzare una EEPROM esterna che sia abbastanza veloce negli accessi (meglio se una flash) ma tanto per capirci vanno bene anche le 24c16/64/256/512 ect, quindi le matrici con le immagini i caratteri maschere ect saranno stoccati in una memoria esterna ed il PIC andrà a "pescare" quello che dovrà  poi dovrà elaborare e visualizzare.

Questo per le immagini per i caratteri il percorso è ancora un pò più tortuoso: prima di tutto bisogna decidere il FONT da utilizzare,  poi si passa alla creazione dei caratteri maiscoli, minuscoli e tutte le punteggiature fatto questo bisogna assegnare ad ogni carattere un'area di memoria nell'EEPROM e ricordarsi l'allocazione del carattere. Esempio se ho deciso il font 7x5 ogni carattere occuperà 5 bytes quindi la memoria EEPROM per contenere un carattere avrà bisogno di 5 allocazioni di memoria libere per carattere e per visualizzare la solita "a" il PIC leggerà  l'indirizzo da dove comincia il carattere "a" fino dove finisce; se comincia dall'indirizzo 0x00 finirà all'indirizzo 0x04 all'indirizzo successivo e cioè il 0x05 comincerà il carattere "b" e finirà a  n-indirizzo+5.

Vediamo ora più da vicino le caratteristiche dell'LCD grafico:

La piedinatura ricorda molto quella dei display alfanumerici (visti in precedenza HD44780) nel nostro caso la versione dell'LCD grafico ha 18 pin in cambio dei 20 previsti dal datasheet effettivamente quello che manca in questa versione utilizzata sono i piedini 17 e 18 rispettivamente RESET e la tensione negativa per il contrasto, il fatto che un LCD costi meno di un altro dipende proprio da queste "sfumature" infatti come riportavo prima ho dovuto realizzare un circuitino a parte per i -5 Volt mentre per il RESET non avendo il pin disponibile c'è la possibilità di implementarlo però con un "comando" via software. Un'altra cosa che si differenzia dagli alfanumerici sono i pin 15 e 16 rispettivamente CS1 e CS2 a cosa servono? Ho letto tempo fa su di un forum il perchè dei display grafici tipo il 256*128 venisse in realtà gestito come un 128*128, Il display grafico infatti ha due driver ogniuno pilota una matrice, nel caso nostro 64*64 quindi quando si abilta il driver CS1 si scriverà nella prima matrice di 64*64 pixel ed abilitando CS2 si scriverà nella seconda gemella matrice,  affiancando le due matrici otteniamo appunto un'unica matrice di 128*64 pixel.  Bisogna porre molta attenzione in fase di implementazione del sorgente in quanto NON  possono essere settati contemporaneamente CS1 e CS2 ma devono sempre ed esclusivamente essere alternati: quando CS1=1 CS2=0 e viceversa.

Anche qui ci sono molte analogie con i display alfanumerici sui cilci scrittura/lettura e sui tempi dei cicli stessi. Allego per comodità il datasheet: files/teppei68/grafico/truly12864.pdf

Una volta lette tutte le indicazioni del datasheet siamo in grado di inizializzare l'LCD quindi si eseguiranno una serie di comandi ed istruzioni:

   R/W=0,RS=0, CS1=1, CS2=0, E=1;

   DATA=0x3E                                                 // CS1 display off

    DelayMs(1);                                              // min. 450nS
    E   = 0;
    DelayMs(1);                                            

questo è il primo ciclo che andrà ripetuto per le altre istruzioni che seguono, la variabile DATA fa chiaramente riferimento a ciò che sarà caricato nella porta rispettiva del PIC es. nel nostro caso PORTE=DATA che interessa la linea dati D0/D7 dell'LCD:
   DATA=0x3F         // CS1 display on
   DATA=0x40         // CS1 set Y address in the address counter  
   DATA=0xB8         // CS1 set x address at the x address reg  
   DATA=0xC0         // CS1 indicates the display data RAM displayed at the top of the screen 

Per quanto riguarda il CS2 andrà eseguita la stessa procedura per inizializzare anche il secondo driver invertendo CS1=0 e ponendo CS2=1. Per la lettura necessaria ad esempio per verificare il BUSY FLAG => D7 basta porre R/W=1  predisporre la porta DATA del PIC come ingresso e leggere il valore presente al BIT corrispondente al D7.

Personalmente non ho implementato (per ora ) questa opzione ma ho optato, come per i display alfanumerici,  con un ritardo "ragionevole" per aspettare che il display compia le sue routine interne, bisogna dire però che in questo caso,  questo ritardo non sfugge all'occhio difatti si vede l'immagine, che interessa l'intero display, viene caricata in poco più di 2 Sec è chiaro che per le esigenze del progetto è del tutto ininfluente, importante è sapere che c'è il BUSY FLAG . Il tempo di 2sec, come ho fatto a calcolarlo? Semplice: il display carica 8 bytes per volta quindi scrive su di una ipotetica riga lunga 128*8 quindi avremmo su di un 128*64 8 righe lunghe 128 bytes la routine prevede ad ogni ciclo scrittura un tempo complessivo di 2 mSec quindi  2mSec* 128bytes*8righe = 2048 mSec. Una volta inizializzato si è pronti a visualizzare un primo punto o linea: 

R/W=0, RS=1, CS1=1, CS2=0, E=1

DATA=0xFF                                                 // CS1 display at  Y address =0 and X address=0  " | "

DelayMs(1);                                              // min. 450nS
E   = 0;
DelayMs(1);

A questo punto sarà visualizzato nell'angolo in alto a sinistra la linea verticale infatti il valore 0xFF riempie tutti gli otto pixel all'indirizzo indicato, per visualizzare la stessa linea nella  seconda matrice dell'LCD basterà invertire i valori CS1/CS2 e la linea verticale questa volta sarà visualizzata in alto al 65° pixel partendo dal 1° a sx corrispondente all'indirizzo Y address=0  e X address=0 del CS2.      N.B. E' consigliato subito dopo l'inizializzazione pulire il display quindi basterà eseguire la scrittura appena vista lasciando il campo vuoto: DATA=0x00 ponendo attenzione all'incremento ed all'autoincremento degli indirizzi.

Vediamo ora come è connesso l'LCD al pic:
  

 

Lo schema elettrico per quanto riguarda il PIC32 fa riferimento quello dell'articolo precedente con l'LCD 16x2 in più qui si ha l'utilizzo dell'intera PORTE per la line dati e la RD6 per il CHIP SELECT 1 e RD5 per il CHIP SELECT 2, vedremo nel filmato seguente la visualizzazione dei caratteri " | " nei due punti  come indicavo prima ed un logo:

 

 

Qui di seguito parte del sorgente:

 

 

/* ********************************************************************

* Program: GLCD 128*64, internal clock *

* and minimal configuration pin (see datasheet). *

* MCU: PIC32MX440F128H 64 Pin QFN

* Compiler: C32 V2.02

* Development software: MPLAB IDE 8.83 + PICKIT2 *

* Author : Mirko Musto 20/09/2012 *

* ********************************************************************/

 

#include <p32xxxx.h>

#include <plib.h> // Adds support for PIC32 Peripheral Library functions and macros

#include <delayLCD.h> // delay support only ms

 

#pragma config FNOSC = FRCPLL // Oscillator Selection internal clock 8mhz

#pragma config FPLLIDIV = DIV_2 // PLL Input Divider

#pragma config FPLLMUL = MUL_24 // PLL Multiplier

#pragma config FPLLODIV = DIV_8 // PLL Output Divider

#pragma config FPBDIV = DIV_1 // Peripheral Clock divisor

#pragma config FWDTEN = OFF // Watchdog Timer

#pragma config WDTPS = PS1 // Watchdog Timer Postscale

#pragma config FCKSM = CSDCMD // Clock Switching & Fail Safe Clock Monitor

#pragma config OSCIOFNC = OFF // CLKO Enable

#pragma config POSCMOD = OFF // Primary Oscillator

#pragma config IESO = OFF // Internal/External Switch-over

#pragma config FSOSCEN = OFF // Secondary Oscillator

#pragma config CP = OFF // Code Protect

#pragma config BWP = OFF // Boot Flash Write Protect

#pragma config PWP = OFF // Program Flash Write Protect

//#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select

#pragma config DEBUG = OFF // Debugger

 

#define red PORTCbits.RC13

#define yellow PORTCbits.RC14

#define green PORTDbits.RD0

#define puls PORTDbits.RD1

#define RW PORTDbits.RD7 // R/W bus LCD

#define RS PORTFbits.RF0 // RS bus LCD

#define E PORTFbits.RF1 // EN bus LCD

#define CS1 PORTDbits.RD6 // CS1

#define CS2 PORTDbits.RD5 // CS2

 

// global var

unsigned int errorValue = 0x00;

unsigned char m = 0, n = 0;

char data[1024];

char *buffer=data;

 

 

// ------------------------------------------------------

// GLCD Picture name: BMP.bmp

// GLCD Model: KS0108 128x64

// ------------------------------------------------------

const char BMP[1024]={

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0,128, 64, 32, 16, 16, 8, 8, 8, 8, 8,

8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,

8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,

8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,

8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,

8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,

8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,

8, 8, 8, 8, 16, 16, 32, 64,128, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0,254, 1, 0, 0, 0, 0, 0, 0,224,224,224,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,224,

224, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,

192,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,224,

224,224, 0, 0, 0, 0, 0, 0, 0, 0, 96, 96, 96, 0, 0,192,

192,192, 0, 0, 0, 0, 0, 0, 1,254, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,

0, 0,254,254,254, 14, 6, 6, 14,252,252,240, 0, 6,255,255,

255, 6, 0,240,252,252, 14, 6, 6, 14,252,252,240, 0, 0,254,

254,254, 14, 6, 6, 14,252,252,240, 0, 0,240,252,252, 14, 6,

6, 14,252,252,240, 0, 0,254,254,254, 14, 6, 6, 0, 6,255,

255,255, 6, 0,136,204,206,110,102, 46,254,252,248, 0, 0,255,

255,255, 0, 0, 0, 0, 0, 0, 0, 0,254,254,254, 0, 6,255,

255,255, 6, 0, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7,

0, 0, 7, 7, 7, 0, 0, 0, 0, 7, 7, 7, 0, 0, 7, 7,

7, 0, 0, 0, 3, 3, 7, 6, 6, 7, 3, 3, 0, 0, 0,127,

127,127, 7, 6, 6, 7, 3, 3, 0, 0, 0, 0, 3, 3, 7, 6,

6, 7, 3, 3, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0, 3,

7, 7, 6, 0, 3, 7, 7, 6, 6, 7, 3, 7, 7, 6, 0, 7,

7, 7, 0, 0, 0, 6, 6, 6, 0, 0, 7, 7, 7, 0, 0, 3,

7, 7, 6, 0, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 3, 12, 16, 32, 64, 64,128,128,128,128,128,

128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,

128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,

128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,

128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,

128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,

128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,

128,128,128,128, 64, 64, 32, 16, 12, 3, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

};

 

 

 

 

 

 

// Function

void clean(char *var);

void wd(char e, char f, char g, char h); // write a data/instruction

void wc(char f, char g, int h); // write a char, CS1, CS2, char from font5x7

char rd(char e, char f, char g); // read a data/busy check

void Initglcd(void); // init GLCD

void ClearDisplay(void);

void paint(void);

void paint1(void);

 

int main(void){

// local var

char a=0x00, b=0x00, c=0x00, cerca=0;

 

mPORTCClearBits (BIT_13 | BIT_14 ); // LED setup - Turn off leds before configuring the IO pin as output

mPORTDClearBits (BIT_1 | BIT_3 | BIT_5 | BIT_6 | BIT_7); // clear RD3 output TX UART1

mPORTEClearBits (BIT_0 | BIT_1 | BIT_2 | BIT_3 | BIT_4 | BIT_5 | BIT_6 | BIT_7 );

mPORTFClearBits (BIT_0 | BIT_1 ); // Turn off before configuring the IO pin as output

 

mPORTCSetPinsDigitalOut (BIT_13 | BIT_14 ); // Set RC13 and RC14 as outputs

mPORTDSetPinsDigitalIn (BIT_1 | BIT_2 ); // Set RD1 as input RD2 as input RX UART1

mPORTDSetPinsDigitalOut (BIT_0 | BIT_3 | BIT_5 | BIT_6 | BIT_7 ); // Set RD3 as output TX UART1

mPORTESetPinsDigitalOut (BIT_0 | BIT_1 | BIT_2 | BIT_3 | BIT_4 | BIT_5 | BIT_6 | BIT_7 ); // Set PORTE as output

mPORTFSetPinsDigitalOut (BIT_0 | BIT_1 ); // Set RF0 and RF1 as outputs

 

OpenTimer1(T1_ON | T1_SOURCE_INT | T1_PS_1_256, 0xFFF); // configure the core timer roll-over rate (100msec)

ConfigIntTimer1(T1_INT_ON | T1_INT_PRIOR_2); // set up the core timer interrupt priority 2 and 0 sub-priority

 

INTEnableSystemMultiVectoredInt();

 

 

 

DelayMs(500);

Initglcd();

ClearDisplay();

 

while(1){ // endless loop

if(puls==0)

{

green=!green;

}

if(green==1)

{

ClearDisplay();

paint1();

DelayMs(6000);

 

}

else

{

ClearDisplay();

paint();

DelayMs(2000);

}

green=!green;

 

} // END endless loop

return 0;

} // END main

 

 

void clean(char *var)

{

int z = 0;

while(var[z] != '\0')

{

var[z] = '\0';

z++;

}

}

 

 

void __ISR(_TIMER_1_VECTOR, ipl2) _Timer1Handler(void)

{

//yellow=!yellow;

red=!red; // flicker Led rosso

mT1ClearIntFlag(); // clear the interrupt flag

}

 

void paint1(void)

{

wd( 0, 1, 0,0x40); // Set Y address in the address counter

wd( 0, 1, 0,0xB8); // Set x address at the x address reg

wd( 0, 1, 0,0xC0); // Indicates the display data RAM displayed at the top of the screen

wd( 1, 1, 0,0xFF); // Write data

 

wd( 0, 0, 1,0x40); // Set Y address in the address counter

wd( 0, 0, 1,0xB8); // Set x address at the x address reg

wd( 0, 0, 1,0xC0); // Indicates the display data RAM displayed at the top of the screen

wd( 1, 0, 1,0xFF); // Write data

}

Mancano tutte le funzioni libreria ma partendo dalla PAINT1 ogniuno può costruire le proprie in rete a tal proposito non c'è molto materiale e se c'è è coperto da diritti, si può notare inoltre la const char, contenente il logo infoportal, ed il notevole spazio che occupa all'interno del sorgente stesso.

Bene e con questo è tutto alla prossima. 

Joomla 1.7 Templates designed by College Jacke