LCD Display 128x64 e PIC Pierin
Salve a tutti :)
Vi pongo il problema:
A scuola stiamo preparando un bel progetto che comprende microcontrollori, trasduttori, meccanica, display appunto e altre diavolerie.....io ho il compito di creare delle funzioni e codici in C col PIC Pierin per poter scrivere dei dati su questo piccolo schermo.
Il modello è LGM12864B-NSW-BBS.
Dopo vari tentativi, guide, ecc... mi devo arrendere e cercare l'aiuto di qualche buona anima perché non avendo mai avuto una minima esperienza in questo campo non so proprio come fare!!!
Il datasheet penso di saperlo a memoria (anche perché molto breve)....ecco il codice che ho scritto in MPLAB-IDE
Cosa non va??
Vi pongo il problema:
A scuola stiamo preparando un bel progetto che comprende microcontrollori, trasduttori, meccanica, display appunto e altre diavolerie.....io ho il compito di creare delle funzioni e codici in C col PIC Pierin per poter scrivere dei dati su questo piccolo schermo.
Il modello è LGM12864B-NSW-BBS.
Dopo vari tentativi, guide, ecc... mi devo arrendere e cercare l'aiuto di qualche buona anima perché non avendo mai avuto una minima esperienza in questo campo non so proprio come fare!!!
Il datasheet penso di saperlo a memoria (anche perché molto breve)....ecco il codice che ho scritto in MPLAB-IDE
- Codice: Seleziona tutto
// File di definizione dei registri del micro.
#include "p18f47j53.h"
// File di configurazione dei fuses
#include "configurazione.h"
// Mappatura delle interrupt
#include "mappa_int.h"
// Header del main
#include "main.h"
//Dichiaro del funzioni dase per LCD Display
//////////////////////////////////////////////////////////////////////////////////////// SCRITTURA/LETTURA
//scrittura
#define GLCD_CS1(n) LATBbits.LATB0 = (n)
#define GLCD_CS2(n) LATBbits.LATB1 = (n)
#define GLCD_RS(n) LATBbits.LATB2 = (n)
#define GLCD_RST(n) LATBbits.LATB5 = (n)
#define GLCD_RW(n) LATBbits.LATB3 = (n)
#define GLCD_E(n) LATBbits.LATB4 = (n)
#define GLCD_D0(n) LATDbits.LATD0 = (n)
#define GLCD_D1(n) LATDbits.LATD1 = (n)
#define GLCD_D2(n) LATDbits.LATD2 = (n)
#define GLCD_D3(n) LATDbits.LATD3 = (n)
#define GLCD_D4(n) LATDbits.LATD4 = (n)
#define GLCD_D5(n) LATDbits.LATD5 = (n)
#define GLCD_D6(n) LATDbits.LATD6 = (n)
#define GLCD_D7(n) LATDbits.LATD7 = (n)
//lettura
#define GLCD_D0_Read PORTDbits.RD0
#define GLCD_D1_Read PORTDbits.RD1
#define GLCD_D2_Read PORTDbits.RD2
#define GLCD_D3_Read PORTDbits.RD3
#define GLCD_D4_Read PORTDbits.RD4
#define GLCD_D5_Read PORTDbits.RD5
#define GLCD_D6_Read PORTDbits.RD6
#define GLCD_D7_Read PORTDbits.RD7
/////////////////////////////////////////////////////////////////////////////////////////////// DEFINIZIONE TRIS SOLO OUT
#define GLCD_TRIS_CS1 TRISBbits.TRISB0 = 1
#define GLCD_TRIS_CS2 TRISBbits.TRISB1 = 1
#define GLCD_TRIS_RS TRISBbits.TRISB2 = 1
#define GLCD_TRIS_RST TRISBbits.TRISB5 = 1
#define GLCD_TRIS_RW TRISBbits.TRISB3 = 1
#define GLCD_TRIS_E TRISBbits.TRISB4 = 1
/////////////////////////////////////////////////////////////////////////////////////////////// DEFINIZIONE TRIS IN/OUT
#define GLCD_TRIS_D0_IN TRISDbits.TRISD0 = 1
#define GLCD_TRIS_D1_IN TRISDbits.TRISD1 = 1
#define GLCD_TRIS_D2_IN TRISDbits.TRISD2 = 1
#define GLCD_TRIS_D3_IN TRISDbits.TRISD3 = 1
#define GLCD_TRIS_D4_IN TRISDbits.TRISD4 = 1
#define GLCD_TRIS_D5_IN TRISDbits.TRISD5 = 1
#define GLCD_TRIS_D6_IN TRISDbits.TRISD6 = 1
#define GLCD_TRIS_D7_IN TRISDbits.TRISD7 = 1
#define GLCD_TRIS_D0_OUT TRISDbits.TRISD0 = 0
#define GLCD_TRIS_D1_OUT TRISDbits.TRISD1 = 0
#define GLCD_TRIS_D2_OUT TRISDbits.TRISD2 = 0
#define GLCD_TRIS_D3_OUT TRISDbits.TRISD3 = 0
#define GLCD_TRIS_D4_OUT TRISDbits.TRISD4 = 0
#define GLCD_TRIS_D5_OUT TRISDbits.TRISD5 = 0
#define GLCD_TRIS_D6_OUT TRISDbits.TRISD6 = 0
#define GLCD_TRIS_D7_OUT TRISDbits.TRISD7 = 0
////////////////////////////////////////////////////////////////////////////////////////////////////
#define PAUSA_E ritardo(1)
#define PAUSA_INIT ritardo(100)
//------------------------------------------------------------------------------
// Variabili globali
//------------------------------------------------------------------------------
#pragma udata
volatile unsigned short timer_delay; // Timer software
unsigned char TRIS_BUS;
// ------------------------------------------------------
// GLCD Picture name: Immagine.bmp
// GLCD Model: KS0108 128x64
// ------------------------------------------------------
//------------------------------------------------------------------------------
// Funzione di servizio delle interrupt ad ALTA priorità
//------------------------------------------------------------------------------
#pragma code
#pragma interrupt highPriorityInterrupt
void highPriorityInterrupt()
{
// Verifica quale flag ha causato l' interrupt
// Esegui la parte di codice di servizio dell' interrupt
// Azzera il flag che ha causato l' interrupt
// ...
}
//------------------------------------------------------------------------------
// Funzione di servizio delle interrupt a BASSA priorità
//------------------------------------------------------------------------------
#pragma interruptlow lowPriorityInterrupt
void lowPriorityInterrupt()
{
// Verifica quale flag ha causato l' interrupt
// Esegui la parte di codice di servizio dell' interrupt
// Azzera il flag che ha causato l' interrupt
// ...
// Gestione dell' interrupt del timer 2
if(PIR1bits.TMR2IF)
{
// gestione del timer software. Il timer software deve decrementarsi
// fino ad arrivare a 0. Una volta arrivato a 0 resta fermo a 0.
if (timer_delay) timer_delay--;
// Resetta il flag che ha generato l' interrupt
PIR1bits.TMR2IF = 0;
}
}
//------------------------------------------------------------------------------
// Prototipi delle funzioni
//------------------------------------------------------------------------------
#pragma code
void timer2_deInit(void);
void ritardo(int x);
void impulso(int x);
//------------------------------------------------------------------------------
// Funzioni
//------------------------------------------------------------------------------
#pragma code
//------------------------------------------------------------------------------
// De-inizializza il timer 2 e lo porta nello stato in cui si trovava
// subito dopo il RESET
void timer2_deInit(void)
{
T2CON = 0; // Resetta il timer 2 control register
TMR2 = 0; // Azzera il contatore interno
PR2 = 0; // Azzera il registro comparatore
PIE1bits.TMR2IE = 0; // Disabilita l' interrupt
IPR1bits.TMR2IP = 0; // Resetta il bit di priorità dell' interrupt
PIR1bits.TMR2IF = 0; // Azzera il flag di interrupt
}
void ritardo(int x)
{
timer_delay = x;
for(;;){
if(!timer_delay){
break;}
} }
//FUNZIONI DEL DISPLAY
//Questa funzione la useremo al momento di leggere o scrivere qualcosa dal bus dati del display
void Enable_Strobe(void){
GLCD_E(1);
PAUSA_E;
GLCD_E(0);
PAUSA_E;
}
//Effettua il reset del display !!Attenzione non è LCD_Clear dopo il reset il display va reinizializzato!!!
void GLCD_RESETcmd(void){
//Reset LCD
GLCD_RST(1);
PAUSA_INIT;
GLCD_RST(0);
PAUSA_INIT;
GLCD_RST(1);
PAUSA_INIT;
}
//IMPOSTO LE PORTE D COME OUTPUT O INPUT (0 output, 1 input)
void GLCD_Set_Port(unsigned char ch)
{
if(ch == 1){
TRIS_BUS = 1;
GLCD_TRIS_D0_IN;
GLCD_TRIS_D1_IN;
GLCD_TRIS_D2_IN;
GLCD_TRIS_D3_IN;
GLCD_TRIS_D4_IN;
GLCD_TRIS_D5_IN;
GLCD_TRIS_D6_IN;
GLCD_TRIS_D7_IN;
}
else{
TRIS_BUS = 0;
GLCD_TRIS_D0_OUT;
GLCD_TRIS_D1_OUT;
GLCD_TRIS_D2_OUT;
GLCD_TRIS_D3_OUT;
GLCD_TRIS_D4_OUT;
GLCD_TRIS_D5_OUT;
GLCD_TRIS_D6_OUT;
GLCD_TRIS_D7_OUT;
}
PAUSA_E;
}
////////////////////////////////////////////////////////////////////////////////CONTROLLA LE PORTE DATI
//scrive un dato nel bus
void GLCD_Ctrl_Port(unsigned char ch){
if(TRIS_BUS == 1){GLCD_Set_Port(0);}//Se il bus dati è configurato come input lo riconfigura come output
if(ch & 1){GLCD_D0(1);}else{GLCD_D0(0);}
if(ch & 2){GLCD_D1(1);}else{GLCD_D1(0);}
if(ch & 4){GLCD_D2(1);}else{GLCD_D2(0);}
if(ch & 8){GLCD_D3(1);}else{GLCD_D3(0);}
if(ch & 16){GLCD_D4(1);}else{GLCD_D4(0);}
if(ch & 32){GLCD_D5(1);}else{GLCD_D5(0);}
if(ch & 64){GLCD_D6(1);}else{GLCD_D6(0);}
if(ch & 128){GLCD_D7(1);}else{GLCD_D7(0);}
}
////////////////////////////////////////////////////////////////////////////////LEGGE LE PORTE DATI
unsigned char GLCD_Ctrl_Port_Read(void){
unsigned char ch = 0;
if(TRIS_BUS == 0){GLCD_Set_Port(1);} //Se il bus dati è configurato come output lo riconfigura come input
if(GLCD_D7_Read == 1){ch=ch | 128;}
if(GLCD_D6_Read == 1){ch=ch | 64;}
if(GLCD_D5_Read == 1){ch=ch | 32;}
if(GLCD_D4_Read == 1){ch=ch | 16;}
if(GLCD_D3_Read == 1){ch=ch | 8;}
if(GLCD_D2_Read == 1){ch=ch | 4;}
if(GLCD_D1_Read == 1){ch=ch | 2;}
if(GLCD_D0_Read == 1){ch=ch | 1;}
return ch;
}
////////////////////////////////////////////////////////////////////////////////INVIA UN DATO all'LCD GRAFICO
//invio un dato al controller del display selezionandolo tramite la varabile chip & chop
//Ch è il valore da inviare
//colore invece se == 2 inverte i byte (negativo)
void Write_Data(unsigned char ch, unsigned char chip, unsigned char colore)
{
if(chip == 1){GLCD_CS1(1);GLCD_CS2(0);} //seleziono il chip 1
else{GLCD_CS1(0);GLCD_CS2(1);} // seleziono il chip 2
GLCD_RW(0); //scrivo
GLCD_RS(1); //invio un dato
if(colore==2){GLCD_Ctrl_Port(~ch);}
else{GLCD_Ctrl_Port(ch);}
Enable_Strobe();
}
////////////////////////////////////////////////////////////////////////////////INVIA UN COMANDO all'LCD GRAFICO
//Invia un comando al display
void Write_Cmd(unsigned char ch,unsigned char chip){
if(chip == 1){GLCD_CS1(1);GLCD_CS2(0);} //seleziono il chip 1
else{GLCD_CS1(0);GLCD_CS2(1);} //seleziono il chip 2
GLCD_RW(0); //scrivo
GLCD_RS(0); //invio un comando
GLCD_Ctrl_Port(ch);
Enable_Strobe();
}
////////////////////////////////////////////////////////////////////////////////LEGGE UN DATO dall'LCD GRAFICO
//legge un dato dal display selezionato tramite comando
unsigned char Read_Data(unsigned char chip){
unsigned char ch;
if(chip == 1){GLCD_CS1(1);GLCD_CS2(0);} //seleziono il chip 1
else{GLCD_CS1(0);GLCD_CS2(1);} //seleziono il chip 2
GLCD_RW(1); //leggo
GLCD_RS(1); //leggo un dato
GLCD_E(1);
PAUSA_E;
ch=GLCD_Ctrl_Port_Read();
GLCD_E(0);
PAUSA_E;
return ch;
}
////////////////////////////////////////////////////////////////////////////////SET Y START ADD
void GLCD_SetY_StartAdd(unsigned char ch,unsigned char chip){
if(ch <= 63){
Write_Cmd((ch | 0b11000000),chip);
}
}
////////////////////////////////////////////////////////////////////////////////SET Y ADD
void GLCD_SetY_Add(unsigned char ch,unsigned char chip){
if(ch <= 63){
Write_Cmd((ch | 0b01000000),chip);
}
}
////////////////////////////////////////////////////////////////////////////////SET PAGE ADD
void GLCD_SetPage_Add(unsigned char ch,unsigned char chip){
if(ch <= 7){
Write_Cmd((ch | 0b10111000),chip);
}
}
////////////////////////////////////////////////////////////////////////////////DISPLAY LDC ON/OFF
void GLCD_ON(unsigned char ch,unsigned char chip){
if(ch <= 1){
Write_Cmd((ch | 0b00111110),chip);
}
}
////////////////////////////////////////////////////////////////////////////////scrive lo stesso byte su tutta la pagina
void GLCD_Clear_Page(unsigned char ch,unsigned char chip,unsigned char page){
unsigned char i;
GLCD_SetPage_Add(page,chip);
GLCD_SetY_Add(0,chip);
for(i=0;i<64;i++){
Write_Data(ch,chip,0);
}
}
////////////////////////////////////////////////////////////////////////////////CHIP CLEAR
void GLCD_Clear_Chip(unsigned char ch,unsigned char chip){
unsigned char i;
for(i=0;i<8;i++){
GLCD_Clear_Page(ch,chip,i);}
}
////////////////////////////////////////////////////////////////////////////////GLCD CLEAR
void GLCD_ClearAll(void){
GLCD_Clear_Chip(0,1);
GLCD_Clear_Chip(0,2);
}
////////////////////////////////////////////////////////////////////////////////LEGGI un BYTE dall'LCD
unsigned char GLCD_ReadByte(unsigned char page,unsigned char y,unsigned char chip){
unsigned char ch;
GLCD_SetPage_Add(page,chip);
GLCD_SetY_Add(y,chip);
ch=Read_Data(chip);
return ch;
}
////////////////////////////////////////////////////////////////////////////////Scrive un BYTE sull'LCD
void GLCD_WriteByte(unsigned char ch,unsigned char color,unsigned char page,unsigned char y,unsigned char chip){
GLCD_SetPage_Add(page,chip);
GLCD_SetY_Add(y,chip);
Write_Data(ch,chip,color);
}
////////////////////////////////////////////////////////////////////////////////INIZIALIZZA l'LCD GRAFICO
void GLCD_My_init(void){
unsigned char ch=0;
///////////////////Inizializzo le porte del processore
GLCD_Set_Port(0);
GLCD_TRIS_CS1;
GLCD_TRIS_CS2;
GLCD_TRIS_RS;
GLCD_TRIS_RST;
GLCD_TRIS_RW;
GLCD_TRIS_E;
GLCD_Ctrl_Port(0);
GLCD_CS1(0);
GLCD_CS2(0);
GLCD_RW(0);
GLCD_RS(0);
GLCD_E(0);
PAUSA_INIT;
GLCD_RESETcmd();//Reset GLCD
//Protocollo di inizializzazione Vedi Datasheet
//Imposto lo zero nell'asse Y
GLCD_SetY_StartAdd(0,1);PAUSA_INIT;
GLCD_SetY_StartAdd(0,2);PAUSA_INIT;
//Posiziono il puntatore dell'asse Y sul punto 0
GLCD_SetY_Add(0,1);PAUSA_INIT;
GLCD_SetY_Add(0,2);PAUSA_INIT;
//Posiziono il cursore nella pagina 0
GLCD_SetPage_Add(0,1);PAUSA_INIT;
GLCD_SetPage_Add(0,2);PAUSA_INIT;
//invio il cmd di accensione!!
GLCD_ON(1,1);PAUSA_INIT;
GLCD_ON(1,2);PAUSA_INIT;
//Ed infine lo "LAVO"
GLCD_ClearAll();PAUSA_INIT;
}
void GLCD_XY_byte(unsigned char x,unsigned char y, unsigned char *Yp,unsigned char *page,unsigned char *chip){
if(y>55){*page=7; goto out;}
if(y>47){*page=6; goto out;}
if(y>39){*page=5; goto out;}
if(y>31){*page=4; goto out;}
if(y>23){*page=3; goto out;}
if(y>15){*page=2; goto out;}
if(y>7) {*page=1; goto out;}
else{ *page=0; }
out:
if(x > 63){*chip=1;*Yp=x-64;}else{*chip=2;*Yp=x;}
}
void GLCD_Goto_XY(unsigned char x,unsigned char y){
unsigned char Yp,page,chip;
GLCD_XY_byte(x,y,&Yp,&page,&chip);
GLCD_SetPage_Add(page,chip);
GLCD_SetY_Add(Yp,chip);
}
////////////////////////////////////////////////////////////////////////////////Scrivo un byte con coordinate X,Y
void GLCD_WriteByte_XY(unsigned char ch,unsigned char color,unsigned char x,unsigned char y){
unsigned char Yp,page,chip;
GLCD_XY_byte(x,y,&Yp,&page,&chip);
GLCD_WriteByte(ch,color,page,Yp,chip);
}
////////////////////////////////////////////////////////////////////////////////Leggo un byte con coordinate X,Y
unsigned char GLCD_ReadByte_XY(unsigned char x,unsigned char y){
unsigned char Yp,page,chip,ch;
GLCD_XY_byte(x,y,&Yp,&page,&chip);
ch=GLCD_ReadByte(page,Yp,chip);
return ch;
}
///////////////////////////////////////////////////////////////////////////////Scrivo vera e propria immagine
void GLCD_WriteForImm(unsigned char const immagine[],unsigned char color,unsigned char l,unsigned char h,unsigned char x,unsigned char y){
unsigned char xImm,yImm;
unsigned int xArr=0;
for(yImm=0;yImm<h;){
for(xImm=0;xImm<l;xImm++){
GLCD_WriteByte_XY(immagine[xArr],color,(x+xImm),(y+yImm));
xArr=xArr+1;
}
yImm=yImm+8;}
}
//------------------------------------------------------------------------------
// MAIN
void main(void)
{
char Immagine[16] = {1,2,3,4,5,4,2,3,4,2,3,5,6,2,2,3};
// Fa partire il PLL.
// Anche se viene selezionato tramite i bit di configurazione
// il suo funzionamento non è automatico. Ha bisogno di un comando.
OSCTUNEbits.PLLEN = 1;
// Attende abbastanza tempo per far stabilizzare il PLL
Delay1KTCYx(100);
// Da ora in poi abbiamo il PLL funzionante ed il micro con il turbo.
// -------- Inizializzazione delle periferiche --------
// De-inizializza il timer2. Non sarebbe necessario perché il micro esce
// allo stato di RESET ma è comunque buona pratica de-inizializzare sempre
// le periferiche per non tralasciare nessun bit.
timer2_deInit();
// Inizializza il timer 2 per interrupt ogni millisecondo.
// prescaler divide per 16
T2CONbits.T2CKPS = 2;
// Postscaler divide per 5
T2CONbits.T2OUTPS = 4;
// Imposta il valore comparatore a 150
PR2 = 150;
// Imposta l' interrupt del Timer 2 a priorita' bassa
IPR1bits.TMR2IP = 0;
// abilita interrupt del timer
PIE1bits.TMR2IE = 1;
// -------- Selezione ed abilitazione delle interrupt --------
// Ora che si sono inizializzate tutte le periferiche si possono abilitare
// Oppurtunamente le interrupt
// abilita le interrupt a bassa priorita'
RCONbits.IPEN = 1;
// abilta tutte le interrupt a priorità bassa
INTCONbits.GIEL = 1;
// Abilita tutte le interrupt in generale
INTCONbits.GIEH = 1;
// -------- Attivazione delle periferiche --------
// Con le interrupt abilitate possiamo ora far partire il timer 2
// Accende il timer
T2CONbits.TMR2ON = 1;
// Inizializza la variabile che funge da timer software
timer_delay = 0;
// Inizializza la variabile di conteggio
GLCD_My_init();
// -------------- Ciclo infinito di funzionamento -------------
for(;;)
{
GLCD_WriteForImm(Immagine[],0,32,8,0,0);
} // for(;;)
}
Cosa non va??