' ********************************************************************** ' ** Programma: DEMLCDAV.BAS - Versione : 1.1 - 19 Gennaio 2001 ** ' ** Compilatore : BASCOM AVR, (IDE V. 1.11.4.0, LIB V. 1.11.4.0) ** ' ** Scheda : K51-AVR ** ' ** Ditta: grifo(r) ITALIAN TECHNOLOGY ** ' ** Via Dell' Artigiano 8/6 40016 San Giorgio di Piano (BO) ** ' ** Tel.+39 051 892 052 Fax +39 051 893 661 ** ' ** http://www.grifo.com http://www.grifo.it ** ' ** sales@grifo.it tech@grifo.it grifo@grifo.it ** ' ** ** ' ** Realizzato da: Graziano GAIBA ** ' ********************************************************************** ' ' Questo programma e' un emulatore di terminale totalmente configuabile ' sia nei codici di emulazione sia nelle procedure che vengono eseguite in ' corrispondenza dei codici. ' La procedura che filtra i caratteri e decide se stamparli od eseguirli ' come comandi e' chamata elaboralcd. ' Esistono tre diversi tipi di comandi: ' ' 1) Caratteri di controllo ' 2) Comandi immeditati ' 3) Comandi con almeno un parametro ' ' I caratteri di controllo sono caratteri che non vengono visualizzati ma che, ' appena ricevuti, inducono l'esecuzione di un determinato pezzo di codice. Ad ' esempio il carattere ASCII detto BEL (codice 7) che normalmente produce un ' suono ma che non viene stampato sullo schermo. ' I comandi immeditai sono delle sequenze , ovvero un ' carattere prefisso che annuncia la richiesta di eseguire un comando (spesso si ' usa il carattere ASCII ESC (codice 27) e un codice che identifica il comando ' da eseguire. Non appena viene riconosciuto la porzione di ' istruzioni associata viene eseguita. ' Infine, i comandi con almeno un parametro sono sequenze di lunghezza variabile ' ' ... ' ' ogni comando e' preceduto dal prefisso e identificato da un codice, seguono ' uno o piu' caratteri che vengono memorizzati come parametri. Non appena ' l'ultimo parametro e' stato ricevuto vengono eseguite le istruzioni relative, ' ogni comando puo' avere un numero indipendente di parametri limitati solo ' dalla memoria disponibile. ' ' La funzione Conin e la procedura Conout costituiscono una ' comoda interfaccia verso la funzione elaboralcd che tiene conto di quale ' dispositivo (seriale o scheda K51) si sta usando come input o come output. ' La decisione di quale dispositivo debba agire da input e quale da output viene ' presa impostando opportunamente il valore delle variabili indev e outdev. ' Ad esempio, se si vuole leggere la seriale ed inviare i caratteri verso lo ' schermo LCD sfruttando la elaboralcd,la sequenza corretta e': ' ' Indev = Serport ' Outdev = K51 ' Kbhit = Constatus() ' If Kbhit <> 0 Then ' P = Conin() ' Call Conout(p) ' End If ' ' La funzione constatus determina se il dispositivo scelto con indev ha un ' carattere pronto per essere letto; se e' cosi' dopo averla chiamata la ' variabile kbhit avra' valore 1, altrimenti avra' valore 0. Per leggere il ' carattere pendente si deve chiamare la conin, la conin ritorna il valore 0 se ' viene chiamata quando nessun carattere e' in attesa, tuttavia potrebbe anche ' avere restituito il carattere 0, quindi prima di usarla bisogna SEMPRE ' chiamare la constatus ed esaminare il valore di ritorno. ' Per inviare un carattere al dispositivo di uscita selezionato con outdev e' ' sufficiente chiamare conout passando come parametro il carattere da stampare. ' ' ' NOTE ' Per poter bufferizzare i caratteri dalle fonti di input e' necessario che ' un interrupt ne controlli periodicamente lo stato, inoltre bisogna effettuare ' il debouncing dei tasti della K51. Tale interrupt viene generato ' dall'azzeramento del Timer 0, pertanto se si vuole usare la K51-AVR come input ' si deve rinunciare ad impiegare il Timer 0. ' ' Per poter utilizzare il display LCD e' indispensabile togliere l'integrato ' in IC12 ed aprire il jumper J4, perdendo la possibilita' di utilizzare il ' tasto T3, allo scopo di evitare che questi componenti creino conflitti con ' i segnali del display LCD. ' ' Sulla stessa linea del tasto T4 e' collegata l'uscita periodica del ' Real Time Clock PCF8583, che genera pressioni spurie. Per poter utilizzare il ' tasto 4 bisogna rimuovere l'RTC (IC7) o programmarlo in modo da bloccare ' il segnale periodico. ' '*********************************************************************** ' '****************** Direttive del compilatore ************************** ' $regfile = "8515def.DAT" ' elenco registri 90S8515 $romstart = &H0 ' indirizzo di partenza del codice $crystal = 5529600 ' frequenza di clock del micro $baud = 19200 ' Baud rate porta seriale Config Lcd = 20 * 2 ' Lcd avente 20 colonne e 2 righe Config Lcdmode = Port ' Report mostra impostazione ' dei pin per gestire LCD Config Lcdpin = Pin , Db4 = Portb.5 , Db5 = Portb.6 , Db6 = Portb.7 , Db7 = Portb.2 , E = Portb.4 , Rs = Portb.3 Config Pinb.0 = Input ' LSB (bit 0) port b in input Config Pinb.1 = Input ' bit 1 di port b in input 'Config Pinb.2 = Input ' bit 2 di port b in input 'Config Pind.2 = Input ' bit 2 di port d in input Config Pind.5 = Output ' bit 5 di port d in output ' Configura il timer 0 come timer ed il prescaler che divide il clock per 256 Config Timer0 = Timer , Prescale = 256 ' Carattere (R) di registrato, creato con LCD Designer nel menu Edit. Deflcdchar 0 , 32 , 14 , 10 , 12 , 10 , 32 , 32 , 32 ' Bit che indica quando il buffer di ingresso della seriale e' pieno Ri Alias Usr.7 ' Linea alla quale e' collegato il tasto T1 T1 Alias Pinb.0 ' Linea alla quale e' collegato il tasto T2 T2 Alias Pinb.1 ' Linea alla quale e' collegato il tasto T3 'T3 Alias Pinb.2 ' Linea alla quale e' collegato il tasto T4 'T4 Alias Pind.2 ' Linea alla quale e' collegato il buzzer auto-oscillante Buz Alias Portd.5 ' Imposta come routine di risposta all'interrupt del timer 0 la label Scan On Timer0 Scan ' '****************** Dichiarazione delle procedure ********************** ' Declare Sub Init ' Inizializza il display Declare Function Conin() As Byte ' Legge un byte da console Declare Sub Conout(ch As Byte) ' Elabora un carattere ' Determina se un carattere e' disponibile Declare Function Constatus() As Byte ' Riconosce ed esegue i comandi di terminale Declare Sub Elaboralcd(ch As Byte) ' Corregge i valori delle variabili riga e colonna Declare Sub Aggiustaxy ' Emette un bip di un decimo di secondo Declare Sub Bip ' Emette un suono di mezzo secondo Declare Sub Bell ' '******************* Dichiarazione delle costanti ********************** ' ' Valore con cui ricaricare Timer 0 per scandire i tasti della K51 ogni 20 msec Const Loadtimer = &H35 ' Iterazioni del debouncing prima che un tasto di consideri acqiuisito Const Debiter = 10 ' Massima dimensione del buffer di ricezione per caratteri dalla seriale Const Maxchar = 5 ' Massima dimensione del buffer di ricezione per i tasti della K51-AVR Const Maxtasti = 2 ' Massimo numero di parametri per un comando dell'emulazione terminale Const Maxpar = 3 ' Prefisso dei comandi di emulazione terminale Const Prefix = &H1B ' Carattere Esc ' Dirige input o output verso la porta seriale Const Serport = 1 ' Dirige input o output verso la k51 Const K51 = 2 ' '****************** Dichiarazione delle variabili ********************** ' Dim Indata As Byte ' Valore letto in input Dim Kbhit As Byte ' Vale 1 se tasto premuto Dim Comando As Byte ' Gestione comandi terminale Dim Codice As Byte ' Codice comando terminale Dim Indev As Byte ' Dispositivo di input Dim Outdev As Byte ' Dispositivo di output Dim Par(maxpar) As Byte ' Parametri comandi terminale Dim Riga As Byte , Colonna As Byte ' Coordinate cursore Dim Bufferk51(maxtasti) As Byte ' Buffer per i tasti K51 Dim Bufferser(maxchar) As Byte ' Buffer caratteri seriale Dim Idxser As Byte , Idxk51 As Byte ' Indice nei buffer Dim Idxcarser As Byte , Idxcark51 As Byte ' Indice prossimo ' carattere da leggere Dim Debcnt As Byte ' Contatore debouncing Dim Debcod As Byte ' Codice tasto premuto Dim Debchar As Byte ' Tasto sotto debouncing Dim Buzcnt As Byte ' Temporizza buzzer Dim P As Byte , Ch As Byte ' Variabili uso generico ' '************************* Programma main ****************************** ' Main: ' Inizializza il display LCD, il timer per la scansione delle fonti di input ' e le variabili del programma. Call Init Do Indev = Serport ' Seriale come input Outdev = K51 ' Display LCD come output Kbhit = Constatus() ' C'e' un carattere? If Kbhit <> 0 Then ' Se c'e' un carattere P = Conin() ' Legge il carattere e ' lo memorizza in p Call Conout(p) ' Invia al dispositivo End If ' di output Indev = K51 ' Tasti K51 come input Outdev = Serport ' Seriale come output Kbhit = Constatus() ' C'e' un carattere? If Kbhit <> 0 Then ' Se c'e' un carattere P = Conin() ' Legge il carattere ' lo memorizza in p Call Conout(p) ' Invia al dispositivo End If ' di output Loop End ' ' Procedura di risposta all'interrupt del Timer 0. ' Si occupa di temporizzare il suono del buzzer, aggiornare il buffer della ' seriale se ci sono caratteri ricevuti e aggiornare il buffer dei tasti K51 ' se un tasto e' premuto. ' Scan: ' Ogni volta che un interrupt temporizzato da un timer scatta, come prima cosa ' deve reinizializzare il timer per non perdere la cadenza. Stop Timer0 ' Ferma il timer Timer0 = Loadtimer ' Ripristina il timer Start Timer0 ' Riattiva il timer ' Temporizzazione del suono del buzzer. Se la variabile buzcnt e' 0 il buzzer ' viene zittito, altrimenti la variabile viene decrementata. If Buzcnt <> 0 Then ' Se buzcnt diversa da 0 Decr Buzcnt ' decrementala Else ' altrimenti Buz = 1 ' ferma il buzzer End If ' Lettura della porta seriale. Se il bit ri e' 1 c'e' un carattere in attesa. ' Viene memorizzato nell'array bufferser che viene gestito come un buffer ' circolare, ovvero una volta riempito si torna al suo inizio sovrascrivendo il ' contenuto. If Ri = 1 Then ' Se c'e' un carattere Bufferser(idxser) = Inkey() ' Leggilo e salvalo Incr Idxser ' Incrementa indice If Idxser > Maxchar Then ' Se indice oltre il massimo Idxser = 1 ' Riportalo all'inizio End If End If ' Acquisizione dei tasti della K51. Se il corrispondente pin del micro e' a 0 ' il tasto e' premuto Debcod = 0 ' Se tasto 1 e' premuto If T1 = 0 Then ' memorizza il codice Debcod = "1" End If If T2 = 0 Then ' Se tasto 2 e' premuto Debcod = "2" ' memorizza il codice End If ' I tasti 3 e 4 non vengono acquisiti. Vedi note in cima al sorgente. ' If T3 = 0 Then ' Debcod = "3" ' End If ' If T4 = 0 Then ' Debcod = "4" ' End If ' Debouncing. Il codice eventualmente letto diventa il nuovo tasto sotto ' debouncing a meno che non fosse gia' sotto debouncing, in tal caso viene ' incrementato il contatore di debouncing. Quando il contatore raggiunge il ' valore limite, il tasto si considera acquisito e viene messo nel buffer K51. If Debcod <> 0 Then ' Se c'e' un codice If Debcod = Debchar Then ' ed e' sotto debouncing Incr Debcnt ' incrementa contatore Else ' Altrimenti Debchar = Debcod ' nuovo tasto Debcnt = 0 ' azzera il contatore End If End If If Debcnt > Debiter Then ' Se il contatore eccede Debcnt = 0 ' azzera il contatore Bufferk51(idxk51) = Debchar ' memorizza il tasto Incr Idxk51 ' incrementa indice If Idxk51 > Maxtasti Then ' Se indice eccede Idxk51 = 1 ' riportalo all'inizio End If Call Bip 'Emette un bip End If Return ' '************************* Fine del programma main ***************************** ' ' ' Inizializzazione dei vari dispositivi di input e output e delle variabili. ' Sub Init ' Inizializzazione variabili usate globalmente Kbhit = 0 ' Nessun tasto premuto Comando = 0 ' Cancella eventuali comandi Codice = 0 ' del terminale in corso Idxser = 1 ' Valore iniziale degli Idxcarser = 1 ' indici dei buffer e Idxk51 = 1 ' di chi legge i buffer Idxcark51 = 1 Debcod = 0 ' Azzera codice tasto e Debchar = 0 ' tasto sotto debouncing Debcnt = 0 ' Azzera contatori di Buzcnt = 0 ' debouncing e buzzer Buz = 1 ' Spegne il buzzer Cls ' Inizializza e cancella ' il display Colonna = 1 : Riga = 1 ' Inizializza coordinate Cursor Blink ' Cursore lampeggiante Timer0 = Loadtimer ' Un int ogni 5 msec Enable Interrupts ' I tasti vengono letti Enable Timer0 ' da un int periodico Start Timer0 ' Abilita Timer 0 End Sub ' ' Legge un byte dal dispositivo di input selezionato ' ' Parametri in input ' Nessuno ' ' Valore in output ' conin byte letto ' Function Conin() As Byte Indata = 0 ' Se non c'e' nessun ' Carattere ritorna 0 Select Case Indev ' A seconda del dispositivo Case Serport: ' Porta seriale If Idxcarser <> Idxser Then ' Se c'e' un carattere ' Legge un carattere Indata = Bufferser(idxcarser) ' dal buffer di ricezione Incr Idxcarser ' Prossimo carattere If Idxcarser > Maxchar Then ' Se fuori dal buffer Idxcarser = 1 ' Torna a inizio buffer End If End If Case K51: ' Tasti della K51 If Idxcark51 <> Idxk51 Then ' Se c'e' un carattere ' Legge un carattere Indata = Bufferk51(idxcark51) ' dal buffer di ricezione Incr Idxcark51 ' Prossimo carattere If Idxcark51 > Maxtasti Then ' Se fuori dal buffer Idxcark51 = 1 ' Torna a inizio buffer End If End If End Select Conin = Indata End Function ' ' Scrive un byte dal dispositivo di output selezionato ' ' Parametri in input ' ch Dato da inviare al dispositivo di console ' ' Valore in output ' Nessuno ' Sub Conout(ch) Select Case Outdev ' A seconda del dispositivo Case Serport: ' Porta seriale Print Chr(ch); ' Invia il carattere Case K51: ' Display LCD Call Elaboralcd(ch) ' Elabora il carattere End Select End Sub ' ' Determina se sono presenti dei caratteri non letti nel buffer del dispositivo ' selezionato come input. ' ' Parametri in input ' Nessuno ' ' Valore in output ' constatus bit che vale 1 se c'e' almeno 1 carattere non letto, 0 altrimenti Function Constatus() As Byte Select Case Indev ' A seconda del dispositivo Case Serport: ' Porta seriale If Idxcarser = Idxser Then ' Se indici coincidono Constatus = 0 ' Nessun carattere Else ' Altrimenti Constatus = 1 ' Almeno un carattere End If Case K51: ' Display LCD If Idxcark51 = Idxk51 Then ' Se indici coincidono Constatus = 0 ' Nessun carattere Else ' Altrimenti Constatus = 1 ' Almeno un carattere End If End Select End Function ' ' Elabora il carattere da inviare all'LCD. ' Sub Elaboralcd(ch As Byte) If Ch = Prefix Then ' Se il tasto e' il prefisso If Comando = 0 Then ' e non viene eseguito alcun comando Comando = &H80 ' entra in modo comando End If ' Altimenti se non e' Else ' il prefisso Select Case Comando Case 0: ' non c'e' comando in corso ' COMANDI IMMEDIATI Select Case Ch ' Comandi immediati noti ' anche come caratteri ' di controllo Case &H07: ' Carattere BEL Call Bell ' Fa suonare il buzzer Case &H0A: ' Carattere LF line feed Incr Riga ' Riga successiva If Riga > 2 Then ' Ovvero la prima se si Riga = 1 ' va oltre l'ultima End If Locate Riga , Colonna ' Sposta il cursore Case Else: ' Caratteri stampabili Lcd Chr(ch) ' Scrivi il carattere su LCD Colonna = Colonna + 1 Call Aggiustaxy ' posiziona il cursore End Select Case &H80: ' Se deve acquisire un comando Select Case Ch ' Attiva il riconoscitore ' COMANDO CON ZERO PARAMETRI Case "1": ' Comando senza parametri Cls ' Esecuzione immediata Riga = 1 ' Aggiorna variabili di Colonna = 1 ' posizione cursore Comando = 0 ' Fine comando ' COMANDI CON PARAMETRI Case "2": ' Comando con un parametro Comando = 1 ' Dichiara n. parametri Codice = Ch ' Memorizza il codice Case "3": ' Comando con due parametri Comando = 2 ' Dichiara n. parametri Codice = Ch ' Memorizza il codice Case Else: ' Comando non riconosciuto Comando = 0 ' Esce da modo comandi Codice = 0 End Select ' Altrimenti acquisisce ' i parametri di un ' comando, il numero di ' parametro e' il valore ' stesso della variabile ' comando ' RACCOLTA PARAMETRI Case Is <= Maxpar: Par(comando) = Ch ' Memorizza parametro Comando = Comando - 1 ' Aggiorna n. parametri ' ESECUZIONE COMANDI CON PARAMETRI If Comando = 0 Then ' Ci sono tutti i parametri Select Case Codice ' Esegue il comando Case "2": ' Comando con un parametro If Par(1) = "n" Then ' Se il parametro e' "b" Cursor Noblink ' Il cursore lampeggia Else ' Altrimenti If Par(1) = "b" Then ' Se il parametro e' "n" Cursor Blink ' Il cursore non lampeggia End If End If Case "3": ' Comando con due parametri ' i parametri vengono ' memorizzati in ordine ' inverso If Par(2) = "1" Then ' Se il primo parametro e' "1" Lcd Chr(par(1)) ' Stampa il secondo Colonna = Colonna + 1 Else ' Altrimenti Lcd Hex(par(1)) ' Scrivi il valore esadecimale Colonna = Colonna + 2 End If ' del secondo parametro Call Aggiustaxy ' Aggiorna le coordinate End Select End If End Select End If End Sub ' ' Corregge il valore delle variabili riga e colonna per tenere conto della ' posizione del cursore nel display LCD internamente al programma. ' Sub Aggiustaxy If Colonna > 20 Then ' Colonna oltre ultima Colonna = 1 ' Prima colonna Riga = Riga + 1 ' Riga successiva If Riga > 2 Then ' Se riga oltre l'ultima Riga = 1 ' Prima riga End If Locate Riga , Colonna ' Sposta il cursore End If End Sub ' ' Attiva il buzzer ed imposta il contatore in interrupt per disabilitarlo ' dopo 25 cicli, ovvero mezzo secondo. ' Sub Bell Buzcnt = 25 ' Imposta 25 cicli Buz = 0 ' Attiva il buzzer End Sub ' ' Attiva il buzzer ed imposta il contatore in interrupt per disabilitarlo ' dopo 5 cicli, ovvero un decimo di secondo. ' Sub Bip Buzcnt = 5 ' Imposta 5 cicli Buz = 0 ' Attiva il buzzer End Sub