Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

LCD Display 128x64 e PIC Pierin

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] LCD Display 128x64 e PIC Pierin

Messaggioda Foto UtenteLuca1995 » 9 ott 2013, 22:17

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
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??
Avatar utente
Foto UtenteLuca1995
790 2 6 12
Frequentatore
Frequentatore
 
Messaggi: 200
Iscritto il: 6 gen 2013, 23:17

0
voti

[2] Re: LCD Display 128x64 e PIC Pierin

Messaggioda Foto UtenteMarcRider » 12 ott 2013, 10:07

così è un po difficile, cosa fa il display al termine delle operazioni?
Avatar utente
Foto UtenteMarcRider
5 1 4
New entry
New entry
 
Messaggi: 53
Iscritto il: 16 feb 2012, 17:37

0
voti

[3] Re: LCD Display 128x64 e PIC Pierin

Messaggioda Foto UtenteLuca1995 » 12 ott 2013, 11:34

Non ho capito la domanda........comunque adesso ho semplificato il codice perché stavo diventando pazzo.
Ho ricominciato da capo con funzioni semplici e di base per scrivere un byte alla volta.
Ecco
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"


/* Display connections */
#define Scrivi_Byte LATD
#define Leggi_Byte PORTD
#define Direzione_Bus TRISD
#define GLCD_CS1    LATBbits.LATB0
#define GLCD_CS2    LATBbits.LATB1
#define GLCD_RS     LATBbits.LATB2
#define GLCD_RW    LATBbits.LATB3
#define GLCD_RST    LATBbits.LATB5
#define GLCD_EN     LATBbits.LATB4




//------------------------------------------------------------------------------
// Variabili globali
//------------------------------------------------------------------------------
#pragma udata
volatile unsigned short timer_delay;    // Timer software


//------------------------------------------------------------------------------
// 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);


//------------------------------------------------------------------------------
// 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 time)
{
   timer_delay = time;
   for(;;){
      if(!timer_delay)break;
   }   
}   

void Enable(void)
{
   GLCD_EN = 1;
   ritardo(1);
   GLCD_EN = 0;
   
}
   
void Set_Chip(int chip)
{
   if(chip==1)
   {
      GLCD_CS1 = 1;
      GLCD_CS2 = 0;
   }
   else
   {
      GLCD_CS1 = 0;
      GLCD_CS2 = 1;
   }
}

void Set_Y (int y)
{
   GLCD_RS = 0;
   GLCD_RW =0;
   LATD = y;
   LATDbits.LATD7 = 0;
   LATDbits.LATD6 = 1;
   Enable();
}

void Set_Page (int page)
{
   GLCD_RS = 0;
   GLCD_RW =0;
   LATD = page;
   LATDbits.LATD7 = 1;
   LATDbits.LATD6 = 0;
   LATDbits.LATD5 = 1;
   LATDbits.LATD4 = 1;
   LATDbits.LATD3 = 1;
   Enable();
}

void Display_Line (int line)
{
   GLCD_RS = 0;
   GLCD_RW =0;
   LATD = line;
   LATDbits.LATD7 = 1;
   LATDbits.LATD6 = 1;
   
   Enable();
}

void Display_OFF (void)
{
   GLCD_RS = 0;
   GLCD_RW =0;
   LATD = 0x3E;
   Enable();
}

void Display_ON (void)
{
   GLCD_RS = 0;
   GLCD_RW =0;
   LATD = 0x3F;
   Enable();
}

void Status_Read (int busy, int on_off, int reset)
{
   GLCD_RS = 0;
   GLCD_RW =1;
   LATDbits.LATD7 = busy;
   LATDbits.LATD6 = 0;
   LATDbits.LATD5 = on_off;
   LATDbits.LATD4 = reset;
   LATDbits.LATD3 = 0;
   LATDbits.LATD2 = 0;
   LATDbits.LATD1 = 0;
   LATDbits.LATD0 = 0;
   Enable();
}

void WriteDisplayByte(int data, int chip)
{   
   GLCD_EN = 0;
   ritardo(1);   
   GLCD_RW =0;
   ritardo(1);
   GLCD_RS = 1;   
   Set_Chip(chip);
   LATD = data;
   GLCD_EN = 1;
   GLCD_EN = 0;
   GLCD_EN = 1;
}

int ReadDisplayByte(void)
{
   GLCD_RS = 1;
   GLCD_RW =1;
   Enable();
   return(PORTD);
}



// MAIN
void main(void)
{
  char c;  // utizzata per la durata dei lampeggi
 
  // 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 --------
 
  // Inizializza la PORTD
  // bit 4 input pulsante PL0
  //  "  5 input pulsante PL1
  //  "  6 output LED LED1
  //  "  7 output LED LED2
 
  // Mette a 0 tutte le uscite
 
 
 
  // 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 = 15;
  // 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
  c = 0;
 
  // -------------- Ciclo infinito di funzionamento -------------
  for(;;)
  {
   
Display_OFF();

Set_Y (7);
Set_Page(1);
Display_Line(1);
WriteDisplayByte(0x38,1);
Display_ON();
ritardo(10000);


   
  } // for(;;)
}

Ma anche adesso, come le funzioni che ho utilizzato nel for(;;) finale, non riesco a vedere neanche un pixel che cambia colore.....
Avatar utente
Foto UtenteLuca1995
790 2 6 12
Frequentatore
Frequentatore
 
Messaggi: 200
Iscritto il: 6 gen 2013, 23:17

0
voti

[4] Re: LCD Display 128x64 e PIC Pierin

Messaggioda Foto UtenteMarcRider » 12 ott 2013, 12:14

per iniziare, leggendo questo sul datasheet:

instruction from MPU. When RSTB becomes low, following procedure is occurred.
1. Display off
2. Display start line register become set by 0.(Z-address 0)
While RSTB is low, No instruction except status read can by accepted. Therefore, execute other
instructions after making sure that DB4= (clear RSTB) and DB7=0 (ready) by status read instruction.
The conditions of power supply at initial power up are shown in table 1.


Bisogna che fuori dal ciclo for, almeno la prima volta esegui il reset, e devi attendere almeno 1us. prima di iniziare questa procedura.
E poi non devi rifarla, ammeno che non prevedi un crash, una disalimentazione solo del display etc.

Poi il cambio colore, non ho capito cosa significa. se intendi il cursore che lampeggia o qualcosaltro...

poi scusa ma...
Codice: Seleziona tutto
void ritardo(int time)
{
   timer_delay = time;
   for(;;){
      if(!timer_delay)break;
   }   
}   

void Enable(void)
{
   GLCD_EN = 1;
   ritardo(1);
   GLCD_EN = 0;
   
}


non so che quarzo usa il pierin, io ho un 8Mhz e divide la frequenza per 4, e con un solo colpo di clock impiego 0.5us. Vedendo il PIC che monta, e quindi potrebbe anche non suddividere per 4, e con il codice "se è diverso da 1 blocca) e impostando il ritardo a 1... quanto tempo aspetteresti?
Avatar utente
Foto UtenteMarcRider
5 1 4
New entry
New entry
 
Messaggi: 53
Iscritto il: 16 feb 2012, 17:37

0
voti

[5] Re: LCD Display 128x64 e PIC Pierin

Messaggioda Foto UtenteTardoFreak » 12 ott 2013, 12:43

Sei sicuro di avere anche collegato e regolato bene il contrasto?
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,9k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[6] Re: LCD Display 128x64 e PIC Pierin

Messaggioda Foto UtenteLuca1995 » 12 ott 2013, 18:10

Allora, il PIC lavora con una frequenza di 48MHz che diviso 4 danno 12MHz. Per come ho impostato prescaler, contatore e postscaler ho un'interrupt ogni 100us.

In questo modo inserendo 1 nella funzione lui fa girare il ciclo for infinito fino a quando la variabile timer_delay, gestita da interrupt per un decremento di 1 ogni volta, non vale 0.

Il colore è inteso se si disegna nero su bianco o il rispettivo negativo di una immagine.
Comunque nel secondo programma, che è più semplice, per il momento il colore non c'è.

Poi non riesco a capire se lo "Status read" è un codice che devo inviare o ricevere dal display......
Il contrasto è regolato bene con un trimmer da 10k perché sullo schermo vedo chiaramente tutti i pixel color giallo-grigio-chiaro su sfondo blu (retroilluminazione).

Forse chiedo troppo ma sapreste scrivere a parole una piccola lista delle operazioni da fare perché, oltre a non capire bene tutto il datasheet, ci sono scritti dei piedini che non capisco, per esempio CS3 e CS1B....

perché li fanno così complicati........

Sarebbe più semplice se ogni 8 pixel fossero direttamente collegato ad una cella di memoria da un byte, la quale, insieme alle altre, sono indirizzate con un bus ad n linee e infine un semplice enable.
No loro per sti 4 puntini di uno schermo ci devono mettere 3 integrati........

Forse sono io che non capisco, non conoscendo il campo dell'elettronica che di occupa di display.
Grazie per gli aiuti che mi avete fornito :D
Avatar utente
Foto UtenteLuca1995
790 2 6 12
Frequentatore
Frequentatore
 
Messaggi: 200
Iscritto il: 6 gen 2013, 23:17

0
voti

[7] Re: LCD Display 128x64 e PIC Pierin

Messaggioda Foto UtenteMarcRider » 13 ott 2013, 0:35

status read o busy flag, è input lato MPU, cioè il display mette a 1 una uscita, finché non ha finito le operazioni.

Reads the internal status
BUSY
0: Ready
1: In operation
ON/OFF
0: Display ON
1: Display OFF
RESET
0: Normal
1: Reset


quindi quando interroghi il display, se ti restituisce 1, sta ancora lavorando se ti restituisce 0, allora è pronto a ricevere altri comandi. Per iniziare ti consiglio come stai facendo, di non usare il Busy flag.

Per l'inizializzazione, basta che esegui quelle due righe, il comando di displayoff, e return home, e devi stare attento ad aspettare il tempo di avvio, basta che sia effettivamente superiore a quello descritto.
http://www.mikroe.com/downloads/get/1908/s6b0108_spec.pdf
Questo dovrebbe essere il controller del tuo display. Non c'è scritto molto di più del datasheet del display, di solito però è più dettagliato. Ti rispiega la fase di reset, e ci sono i grafici dei tempi di attesa.
Il display presenta tutti i pixel neri?
Avatar utente
Foto UtenteMarcRider
5 1 4
New entry
New entry
 
Messaggi: 53
Iscritto il: 16 feb 2012, 17:37

0
voti

[8] Re: LCD Display 128x64 e PIC Pierin

Messaggioda Foto UtenteLuca1995 » 13 ott 2013, 18:24

Ho modificato tutto in questo modo ma ancora non funziona
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"


/* Display connections */
#define Scrivi_Byte LATD
#define Leggi_Byte PORTD
#define Direzione_Bus TRISD
#define GLCD_CS1    LATBbits.LATB0
#define GLCD_CS2    LATBbits.LATB1
#define GLCD_RS     LATBbits.LATB2
#define GLCD_RW    LATBbits.LATB3
#define GLCD_RST    LATBbits.LATB5
#define GLCD_EN     LATBbits.LATB4




//------------------------------------------------------------------------------
// Variabili globali
//------------------------------------------------------------------------------
#pragma udata
volatile unsigned short timer_delay;    // Timer software


//------------------------------------------------------------------------------
// 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);

//------------------------------------------------------------------------------
// 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 time)
{
   timer_delay = time;
   for(;;){
      if(!timer_delay)break;
   }   
}   

void Enable(void)
{
   GLCD_EN = 1;
   ritardo(1);
   GLCD_EN = 0;
   
}
   
void Set_Chip(int chip)
{
   if(chip==1)
   {
      GLCD_CS1 = 1;
      GLCD_CS2 = 0;
   }
   else
   {
      GLCD_CS1 = 0;
      GLCD_CS2 = 1;
   }
}

void Set_Y (int y)
{
   GLCD_RS = 0;
   GLCD_RW =0;
   LATD = y;
   LATDbits.LATD7 = 0;
   LATDbits.LATD6 = 1;
   Enable();
}

void Set_Page (int page)
{
   GLCD_RS = 0;
   GLCD_RW =0;
   LATD = page;
   LATDbits.LATD7 = 1;
   LATDbits.LATD6 = 0;
   LATDbits.LATD5 = 1;
   LATDbits.LATD4 = 1;
   LATDbits.LATD3 = 1;
   Enable();
}

void Display_Line (int line)
{
   GLCD_RS = 0;
   GLCD_RW =0;
   LATD = line;
   LATDbits.LATD7 = 1;
   LATDbits.LATD6 = 1;
   
   Enable();
}

void Display_OFF (void)
{
   GLCD_RS = 0;
   GLCD_RW =0;
   LATD = 0x3E;
   Enable();
}

void Display_ON (void)
{
   GLCD_RS = 0;
   GLCD_RW =0;
   LATD = 0x3F;
   Enable();
}

int Status_Read_Busy (void)
{   
   int a;
   GLCD_RS = 0;
   GLCD_RW =1;
   Enable();
   a = PORTDbits.RD7;
   return(a);
}

int Status_Read_ON_OFF(void)
{
   int a;
   GLCD_RS = 0;
   GLCD_RW =1;
   Enable();
   a = PORTDbits.RD5;
   return(a);
}

int Status_Read_Reset(void)
{
   int a;
   GLCD_RS = 0;
   GLCD_RW =1;
   Enable();
   a = PORTDbits.RD4;
   return(a);
}

void WriteDisplayByte(int data, int chip)
{   
   GLCD_EN = 0;
   ritardo(1);   
   GLCD_RW =0;
   ritardo(1);
   GLCD_RS = 1;   
   Set_Chip(chip);
   LATD = data;
   GLCD_EN = 1;
   GLCD_EN = 0;
   GLCD_EN = 1;
}

int ReadDisplayByte(void)
{
   GLCD_RS = 1;
   GLCD_RW =1;
   Enable();
   return(PORTD);
}




// MAIN
void main(void)
{
  // 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 --------
 
  // Inizializza la PORTD
  // bit 4 input pulsante PL0
  //  "  5 input pulsante PL1
  //  "  6 output LED LED1
  //  "  7 output LED LED2
 
  // Mette a 0 tutte le uscite
  GLCD_RST = 0;
 
 
  // 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 = 15;
  // 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
 
  ritardo(1);
  GLCD_RST = 1;
  // -------------- Ciclo infinito di funzionamento -------------
  for(;;)
  {
   
Display_OFF();

for(;;)
{
   if(!Status_Read_Busy)break;
}

Set_Y (7);
Set_Page(1);
Display_Line(1);
WriteDisplayByte(0x38,1);
Display_ON();
ritardo(10000);


   
  } // for(;;)
}
Avatar utente
Foto UtenteLuca1995
790 2 6 12
Frequentatore
Frequentatore
 
Messaggi: 200
Iscritto il: 6 gen 2013, 23:17

0
voti

[9] Re: LCD Display 128x64 e PIC Pierin

Messaggioda Foto UtenteMarcRider » 15 ott 2013, 16:03

perdonami, ma sul main continuo a vedere che generi un codice in loop, e non hai eseguito sto famoso reset. prima del ciclo for infinito, scrivi una funzione di reset.


Codice: Seleziona tutto
main....

// INIZIO RESET
if(Status_Read_Busy)
{
Nop();
}

Display_OFF();
Set_Y (0);
InviaComandoZalDisplay(RS=0,RW=0, DB7-DB0 = 11000000) // vedi DS reset register Z
// FINE reset

for(;;) ....

/*
RESET
The system can be initialized by setting RSTB terminal at low level when turning power on, receiving instruction
from MPU.
When RSTB becomes low, following procedure is occurred.
· Display off
· Display start line register become set by 0. (Z-address 0)
While RSTB is low, No instruction except status read can be accepted. Therefore, execute other instructions after
making sure that DB4 = 0 (clear RSTB) and DB7 = 0 (ready) by status read instruction.
*/


Prova così. miraccomando i ritardi nelle istruzioni. Fammi sapere se migliora.
Avatar utente
Foto UtenteMarcRider
5 1 4
New entry
New entry
 
Messaggi: 53
Iscritto il: 16 feb 2012, 17:37


Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 8 ospiti