'****************************************************************** '* Nome : k51dah.bas * '* Autore : Graziano GAIBA * '* Data : 25/06/04 * '* Versione : 1.1 * '* Scheda : GMM 876 * '* Linguaggio: PIC BASIC Standard Ver. 1.45 * '* Azienda : Copyright (c) 2004 grifo(r) ITALIAN Technology * '* : All Rights Reserved * '* : Tel.: +39 051 892052 Fax: +39 051 893661 * '* : http://www.grifo.com http://www.grifo.it * '* : E-Mail: grifo@grifo.it * '****************************************************************** ' ' Questo demo permette di pilotare una periferica I2C BUS a bordo della K51-AVR, ' PCF8591, attraverso il modulo mini-BLOCK GMB HR84 ed un mini modulo grifo(r). ' Il PCF8591 e' dotato di una uscita analogica D/A con risoluzione ad 8 bit, ' tutte le operazioni di attivazione avvengono tramite l'interfaccia seriale ' sincrona I2C BUS. ' Il demo permette di impostare quale livello di tensione avere in uscita ' tramite la tastiera del PC, e scrive 'da' sui display a 7 segmenti della ' K51-AVR per indicare il funzionamento del demo. ' ' Per la comunicazione, viene usata la seriale hardware implementata ' nel demo Usart.bas del PIC Basic standard opportunamente ' modificata. ' ' ' ********************************************************************* ' * Definizioni e Costanti * ' ********************************************************************* ' ' Registri del PIC symbol INDF = 0 symbol FSR = $04 ' Port di I/O symbol PORTA = $05 symbol TRISA = $85 ' banco 1 symbol PORTB = $06 symbol TRISB = $86 ' banco 1 symbol PORTC = $07 symbol TRISC = $87 ' banco 1 ' I2C BUS symbol SSPCON2= $91 ' banco 1 symbol SSPBUF = $13 symbol SSPADD = $93 ' banco 1 symbol SSPCON1= $14 symbol SSPSTAT= $94 ' banco 1 ' symbol OPTION_REG = $81 ' banco 1 ' ' Simboli usati dalla seriale hardware implementata ' nel demo Usart.bas del PIC Basic standard ' Definizione registri USART Symbol PIR1 = $0C ' Registro Peripheral Interrupt Flag Symbol RCSTA = $18 ' Registro di stato e controllo ricezione Symbol TXREG = $19 ' Dato da trasmettere Symbol RCREG = $1A ' Dato ricevuto Symbol TXSTA = $98 ' Registro di stato e controllo trasmissione Symbol SPBRG = $99 ' Registro del Baud Rate Generator ' ' ' Slave address e altre costanti ' Symbol Saa1064 = $38 ' Slave address SAA1064 Symbol Wsaa1064 = $70 ' Slave address SAA1064 in Write Symbol Rsaa1064 = $71 ' Slave address SAA1064 in Read ' ***************** Elenco indirizzi per Saa1064 *********************** Symbol Ctb = $0 ' Ind. Control byte Symbol Dig1 = $1 ' Ind. Digit 1 Symbol Dig2 = $2 ' Ind. Digit 2 Symbol Dig3 = $3 ' Ind. Digit 3 Symbol Dig4 = $4 ' Ind. Digit 4 ' ' ********************************************************************** ' Symbol Pcf8591 = $48 ' Slave address PCF8591 Symbol Wpcf8591 = $90 ' Slave address PCF8591 in Write Symbol Rpcf8591 = $91 ' Slave address PCF8591 in Read ' ' ' ********************************************************************* ' * Variabili usate dal programma * ' ********************************************************************* ' ' ' Usate dall'USART SYMBOL UsartST = B0 ' Stato dell'USART SYMBOL UsartOut = B1 ' Carattere da inviare symbol UsartIn = B2 ' Carattere ricevuto ' Valore da stampare come stringa symbol Valore = B3 ' Uso Generico SYMBOL i = B4 SYMBOL c = B5 symbol z = B6 ' Indirizzo e dati in esadecimale per I2C BUS symbol Slave_Address = B7 symbol Indirizzo = B8 symbol DatoIn = B9 symbol DatoOut = B10 symbol Dato = B11 ' Usato dall'input di un valore esadecimale symbol ValoreHex = B12 ' Usate per la visualizzazione su display a 7 segmenti symbol Nibble_h = B13 symbol Nibble_l = B14 ' ' ' ********************************************************************* ' * Programma main * ' ********************************************************************* ' Main: gosub Module_init ' Inizializzazione generale for i=0 to 135 lookup i,("Visualizza sui display a 7 segmenti l'indice dell'uscita PWM.",13,10,"Premere + per incrementare l'uscita, Premere - per decrementare l'uscita."),usartout gosub charout next i gosub k51_init ' Inizializzazione K51-AVR dato = 0 Loop: ' Imposta il livello di uscita desiderato specificato in Dato. ' Il livello di uscita varia da 0 a 5 V, il PWM ha risoluzione di 8 bit ' quindi l'uscita viene mappata nei valori da 0 a 255 per la variabile ' Dato. gosub set_out ' Visualizza in esadecimale sul display a 7 segmenti il valore ' contenuto nella variabile Dato gosub vis_num ' Aggiorna il livello dell'uscita in base all'input ' fornito dall'utente: premendo il tasto + sulla tastiera del PC ' il livello aumenta, premendo il tasto - diminuisce gosub set_livello ' Ripete Loop per sempre goto loop end ' ' ' ********************************************************************* ' * Fine del programma * ' ********************************************************************* ' ' ' Inizializzazione della GMM 876 Module_init: ' ' Inizializza USART per 19200 Baud Poke SPBRG,64 ' Imposta baud rate a 19200 Poke RCSTA,%10010000 ' Abilita porta seriale e ricezione continua Poke TXSTA,%00100100 ' Abilita tramsissione, modalita' asincrona e ' baud rate elevati ' ' Inizializzazione per I2C BUS ' Configura RC3 ed RC4 come ingressi peek trisc, B0 bit3 = 1 bit4 = 1 poke trisc, B0 ' Attiva il modulo SSP in modalita' master I2C BUS, clock 50 kHz poke sspstat, 0 poke sspadd, $63 poke sspcon1, $28 ' Rimettere la pagina 0 prima di uscire dall'asm 'ASM 'ENDASM pause 500 return ' ' ' Inizializzazione periferiche della K51-AVR K51_init: ' ' Configurazione del controllore dei display a 7 segmenti SAA 1064 ' ' Invia lo start gosub i2cbusstart 'Attende che venga completato gosub i2cbussynch ' ' Invia lo slave address del SAA 1064 datoout = rsaa1064 gosub i2cbussend ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' ' Legge lo stato del SAA 1064 gosub i2cbusget ' Invia l'acknowledge negato... peek sspcon2, B0 bit5 = 1 bit4 = 1 poke sspcon2, B0 '...e attende che venga completato gosub i2cbussynch ' ' Invia lo stop gosub i2cbusstop 'Attende che venga completato gosub i2cbussynch ' if datoin <> 0 then k51_init ' Invia lo start gosub i2cbusstart 'Attende che venga completato gosub i2cbussynch ' datoout = Wsaa1064 ' comunico lo Slave address gosub i2cbussend ' ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' datoout = Ctb ' Punto al registro di controllo gosub i2cbussend ' ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' datoout = %00100111 ' bit0 =1 dynamic mode ' bit1 =1 digit 1+3 not blanked ' bit2 =1 digit 2+4 not blanked ' bit3 =0 no test segment ' bit4 =0 no 3mA segment current ' bit5 =1 6mA segment current ' bit6 =0 no 12mA segment current ' bit7 =0 indifferente gosub i2cbussend ' ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' datoout = 94 gosub i2cbussend ' scrive 'd' ' ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' datoout = 119 gosub i2cbussend ' scrive 'a' ' ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' datoout = 0 gosub i2cbussend ' scrive DY3 off ' ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' datoout = 0 gosub i2cbussend ' scrive DY4 off ' ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' ' Invia lo stop gosub i2cbusstop 'Attende che venga completato gosub i2cbussynch return ' ' ' Imposta il livello di uscita desiderato specificato in Dato. ' Il livello di uscita varia da 0 a 5 V, il PWM ha risoluzione di 8 bit ' quindi l'uscita viene mappata nei valori da 0 a 255 per la variabile ' Dato. Set_out: slave_address = wpcf8591 ' Comando attivazione PWM indirizzo = $40 ' Livello dell'uscita datoout = dato gosub i2cbuswrite return ' ' ' Aggiorna il livello dell'uscita in base all'input ' fornito dall'utente: premendo il tasto + sulla tastiera del PC ' il livello aumenta, premendo il tasto - diminuisce Set_livello: gosub charin if usartin = "+" then incr_out if usartin = "-" then decr_out goto set_livello_esci Incr_out: dato = dato + 1 goto set_livello_esci Decr_out: dato = dato -1 Set_livello_esci: return ' ' ' Visualizza un byte sui display a 7 segmenti Vis_num: ' Separa il valore conenuto nella variabile Dato in due parti: ' Nibble_h (nibble alto) e Nibble_l (nibble basso) gosub cifre ' Converte il valore decimale in codifica a 7 segmenti B1 = nibble_h gosub dec_to_7seg nibble_h = B1 ' Converte il valore decimale in codifica a 7 segmenti B1 = nibble_l gosub dec_to_7seg nibble_l = B1 ' Invia il valore di temperatura converitito in codifica a 7 ' segmenti al driver dei display a 7 segmenti ' Genera I2CBUS Start... gosub i2cbusstart 'Attende che venga completato gosub i2cbussynch ' Invia lo Slave Address datoout = Wsaa1064 gosub i2cbussend ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' Punta al primo display datoout = dig3 gosub i2cbussend ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' Scrive il nibble alto datoout = nibble_h gosub i2cbussend ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' Scrive il nibble basso datoout = nibble_l gosub i2cbussend ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' Invia lo stop gosub i2cbusstop 'Attende che venga completato gosub i2cbussynch return Dec_to_7Seg: lookup B1, ($3F, $06, $5B, $4F, $66, $6D, $7D, $07, $7F, $6F, $77, $7C, $39, $5E, $79, $71), B1 return ' ' ' Separa il valore conenuto nella variabile Dato in due parti: ' Nibble_h (nibble alto) e Nibble_l (nibble basso) Cifre: nibble_h = dato / 16 nibble_l = dato & $0F return ' ' ' Scrive un byte all'indirizzo specificato I2CBUSWrite: ' Genera I2CBUS Start... gosub i2cbusstart 'Attende che venga completato gosub i2cbussynch ' Invia lo Slave Address datoout = slave_address gosub i2cbussend ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' Invia l'indirizzo a cui scrivere il dato datoout = indirizzo gosub i2cbussend ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' Invia il dato da scrivere datoout = dato gosub i2cbussend ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' Invia lo stop gosub i2cbusstop 'Attende che venga completato gosub i2cbussynch ' Esce return ' ' ' Legge un byte dall'indirizzo specificato I2CBUSRead: ' Genera I2CBUS Start... gosub i2cbusstart 'Attende che venga completato gosub i2cbussynch ' Invia lo Slave Address datoout = slave_address gosub i2cbussend ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' Invia l'indirizzo da cui leggere il dato datoout = indirizzo gosub i2cbussend ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' Genera il secondo I2CBUS Start... gosub i2cbusrepstart 'Attende che venga completato gosub i2cbussynch ' Invia lo Slave Address per la lettura datoout = slave_address | $01 gosub i2cbussend ' Se non viene ricevuto l'acknowledge, segnala l'errore peek sspcon2, B0 if bit6 = 1 then notack ' Legge il dato nella variabile DatoIn gosub i2cbusget ' Pone il byte letto nella variabile Dato dato = datoin ' Invia l'acknowledge negato... peek sspcon2, B0 bit5 = 1 bit4 = 1 poke sspcon2, B0 '...e attende che venga completato gosub i2cbussynch ' Invia lo stop gosub i2cbusstop 'Attende che venga completato gosub i2cbussynch ' Esce I2CBUSEsci: return ' ' ' Indica che l'acknowledge non e' stato ricevuto NotACK: for i = 0 to 23 lookup i,("Acknowledge non ricevuto"), usartout gosub charout next i return ' ' ' Genera uno start I2C BUS I2CBUSStart: peek sspcon2, B0 bit0 = 1 poke sspcon2, B0 return ' ' ' Genera uno start I2C BUS ripetuto I2CBUSRepStart: peek sspcon2, B0 bit1 = 1 poke sspcon2, B0 return ' ' ' Genera uno stop I2C BUS I2CBUSStop: peek sspcon2, B0 bit2 = 1 poke sspcon2, B0 return ' ' ' Invia il valore contenuto in DatoOut su I2C BUS I2CBUSSend: poke sspbuf, datoout gosub i2cbussynch return ' ' ' Legge un dato da I2C BUS e lo restituisce in DataIn I2CBUSGet: ' Abilita il ricevitore peek sspcon2, B0 bit3=1 poke sspcon2, B0 I2CBusGetLoop: peek sspcon2, B0 if bit3 = 1 then I2CBusGetLoop peek sspbuf, datoin return ' ' ' Attende il completamento dell'ultima operazione dell'interfaccia I2C I2CBUSSynch: peek pir1, B0 if bit3 = 0 then I2CBUSSynch bit3 = 0 poke pir1, B0 return ' ' ' Trasforma il valore esadecimle nella variabile Valore in caratteri ' ASCII e li invia alla porta seriale. ' Valore deve essere compreso tra 0 e 0FFh. StampaHex: usartout = valore / 16 gosub hexdecode gosub charout StampaNibbleHex: usartout = valore & $0F gosub hexdecode gosub charout return ' HexDecode: Lookup usartout,("0123456789ABCDEF"),usartout return ' HexEncode: lookDown usartin,("0123456789abcdef"),usartin return ' ' ' Manda a capo su una riga sotto NLCR: usartout = 10 ' New Line gosub charout CR: usartout = 13 ' Carriage Return gosub charout return ' ' ' Stampa due spazi DueSpazi: usartout = " " ' Spazio gosub charout gosub charout return ' ' ' Va a capo, stampa il messaggio "Premere un tasto..." e va a capo TastoPerUscire: gosub nlcr for z = 0 to 18 lookup z, ("Premere un tasto..."),usartout gosub charout next z gosub nlcr return ' ' ' Chiede un valore in esadecimale e lo restituisce in dato InputDato: for z = 0 to 11 lookup z,("Dato (Hex): "), usartout gosub charout next z gosub inputhex dato = valorehex return ' ' ' Chiede indirizzo in esadecimale e lo restituisce in indirizzo InputSlaveAddress: for z = 0 to 20 lookup z,("Slave Address (Hex): "), usartout gosub charout next z gosub inputhex slave_address = valorehex return ' ' ' Chiede indirizzo in esadecimale e lo restituisce in indirizzo InputIndirizzo: for z = 0 to 16 lookup z,("Indirizzo (Hex): "), usartout gosub charout next z gosub inputhex indirizzo = valorehex return ' ' ' Input di un valore esadecimale da 00 a FF poi va a capo InputHex: gosub charin if usartin = 0 then InputHex usartout = usartin gosub charout usartin = usartin | $20 gosub hexencode valorehex = usartin * 16 InputHex2: gosub charin if usartin = 0 then InputHex2 usartout = usartin gosub charout usartin = usartin | $20 gosub hexencode valorehex = valorehex + usartin gosub nlcr return ' ' ' Subroutine che invia un carattere al trasmettitore USART ' (sospensiva) CharOut: Peek pir1,UsartST ' Leggi il Flag in UsartST = B0 If Bit4 = 0 Then charout ' Attendi che si svuoti il registro di ' trasmissione Poke TXREG,Usartout ' Metti il carattere nel registro di ' trasmissine Return ' Ritorno al chiamante ' ' ' Subroutine che preleva un carattere dal ricevitore dell'USART ' (non sospensiva) CharIn: UsartIn = 0 ' Preset a nessun carattere ricevuto Peek PIR1,Usartst ' Leggi il Flag in UsartST = B0 If Bit5 = 0 Then ciret ' Se il flag di ricezione e' 0, esci Peek RCREG,UsartIn ' Altrimenti metti il carattere ricevuto ' in UsartIn = B1 ciret: Return ' Ritorno al chiamante