' ********************************************************************** ' * File gmbi2c.bas - Rel. 1.1 con Bascom 8051 DEMO IDE e LIB 2.0.11.0 * ' * Scheda: GMM 935 + GMB HR84 * ' * GRIFO(R) via Dell'Artigiano 8/6 40016 S. Giorgio di Piano (BO) * ' * Tel. +39 051 892052 Fax. +39 051 893661 * ' * http://www.grifo.com http://www.grifo.it * ' * by Graziano Gaiba del 16.11.04 * ' ********************************************************************** ' ' Questo demo permette di comunicare con disposivi I2C BUS collegati a CN3. ' E' possibile leggere e scrivere byte ad un qualsiasi slave address ed ' address inseriti da console. ' In particolare, in lettura il byte ricevuto viene visualizzato, mentre in ' caso di scrittura il dato inserito viene spedito. ' ' ' '****************** Direttive del compilatore ************************** ' 'N.B. Nella finestra Options | Compiler | Misc effettuare i seguenti ' settaggi: Register File = 89LPC935.DAT ' Byte End (Hex) = A0 ' Size warining = 7167 $regfile "89lpc935.dat" $romstart = &H0 ' Ind. inizio codice in FLASH $ramstart = &H0 ' Ind. inizio area dati in XRAM $ramsize = &H200 ' Dimensioni area dati in XRAM $crystal = 11059200 ' Massima Fclock della scheda $baud = 19200 ' Velocità comunicazione seriale $large ' Dimensione codice > 2K $map ' Genera info per debug ' '****************** Dichiarazione delle costanti *********************** ' Const Cret = 13 ' Codice di ritorno di carrello Const Nl = 10 ' Codice nuova linea Const Clrscr = 12 ' codice di clear screen Const Bell = 7 ' codice di Bell Const Rcint = 7372800 ' Frequenza clock da RC interno Const Qz11m = 11059200 ' Frequenza clock da quarzo esterno ' ' ' '****************** Dichiarazione delle variabili ********************** ' ' Variabili ad uso generico Dim S0 As Bit ' Bit di uso generico Dim I As Byte , Scelta As Byte Dim Hlpb As Byte , M As Byte ' Byte ad uso generico Dim T As Byte , S As Byte , V As Byte ' Byte di uso generico Dim Hlpw As Word , Ind As Word ' Word ad uso generico Dim Hlpl As Long ' Long ad uso generico ' Variabili per gestione comunicazione seriale, clock e ritardi Dim St As Byte Dim Br As Long ' Buad Rate seriale Dim Cclk As Long ' Frequenza clock della CPU Dim R As Word , Rit1ms As Word , Rit As Word ' Gestione ritardi ' Variabili per gestione Port di I/O digitale Dim M1 As Byte , M2 As Byte ' Variabili per gestione I2C Dim I2cc As Byte , I2cs As Byte Dim I2cdato As Byte Dim I2caddr As Word ' '****************** Dichiarazione delle procedure ********************** ' Declare Sub Init() ' Inizializzazione Declare Sub Ritardo(rit As Word) ' Effettua ritardo calibrato Declare Sub Iniser(br As Long , St As Byte) ' Inizializzazione seriale Declare Sub Tastoxuscire ' Indica pressione tasto Declare Sub Att_tasto ' Attende pressione tasto Declare Sub Check ' Verifica periferiche Declare Sub Cmd_i2c(i2cc As Byte) ' Manda comando ad I2C ' '************************* Programma main ****************************** ' Main: Disable Interrupts P1m1 = 0 ' Necessario per la seriale RS232 Call Get_clk ' Preleva frequenza della CPU Call Iniser(19200 , 1) ' Inizializza seriale x console ' ' ' Effettua un ritardo di circa 2 secondi in modo da assicurare la ' partenza del programma di emulazione terminale per console (es. ' HYPERTERMINAL) e contemporaneamente fa` lampeggiare il LED di ' attivita` DL1 della scheda. ' Usa la variabile generale i P0m1 = P0m1 Or &H40 ' Setta P0.6 in modo 3=OpenDrain P0m2 = P0m2 Or &H40 For I = 1 To 16 ' 16 cicli da 125 msec = 2 sec P0.6 = Not P0.6 ' Complementa LED attivita` Call Ritardo(125) ' Ritardo di circa 125 msec Next I ' ' ' Print Print "Demo 1.1 per GMM935 ds300803+GMBHR84 ds220503" Call Check ' Controllo interno ' ' ' Demo gestione interfaccia I2C hardware nelle modalita` Master ' transmit e Master receive ad un bit rate fisso. Consente di leggere ' e scrivere un generico dispositivo I2C, grazie alla possibilita` ' di inserire da console lo Slave addres, l'address ed il dato. ' Usa le variabili generali scelta,hlpw ' ' P1m1 = P1m1 And &HF3 ' Configura P1.2 (SCL) e P1.3 P1m2 = P1m2 And &HF3 ' (SDA) in modo open drain P1 = P1 Or &H0C ' in ingresso If Cclk = Rcint Then I2scll = 37 ' Bit rate a 2*(37+37) cicli clock I2sclh = 37 ' (7 MHz) pari a circa 50 KHz Else I2scll = 55 ' Bit rate a 2*(55+55) cicli clock I2sclh = 55 ' (11 MHz) pari a circa 50 KHz End If Print Print "I2C BUS" Do Print Print "L) Legge" Print "S) Scrive" Print Print "Scelta: "; Do ' Ciclo attesa scelta valida Scelta = Waitkey() Scelta = Scelta - &H20 Loop Until Scelta = "L" Or Scelta = "S" Print Chr(scelta) Print Select Case Scelta Case "S": Inputhex "Inserire indirizzo esadecimale a quattro cifre: " , I2caddr Inputhex "Inserire valore esadecimale da scrivere a due cifre: " , I2cdato I2con = &H40 ' Abilita la SIO1 Call Cmd_i2c(&H60) ' Invia lo start If I2cs <> &H08 Then Printhex "Errore su Start (codice " ; I2cs ; "H)" Else I2dat = High(i2caddr) ' Scrive SLA+W Call Cmd_i2c(&H40) ' Resetta flag interrupt If I2cs <> &H18 Then Printhex "Errore su SLA+W (codice " ; I2cs ; "H)" Else I2dat = Low(i2caddr) ' Parte bassa indirizzo Call Cmd_i2c(&H40) ' Resetta flag interrupt If I2cs <> &H28 Then Printhex "Errore su Indirizzo (codice " ; I2cs ; "H)" Else I2dat = I2cdato ' Scrive il dato Call Cmd_i2c(&H40) ' Resetta flag interrupt If I2cs <> &H28 Then Printhex "Errore su Dato (codice " ; I2cs ; "H)" End If End If End If I2con = &H50 ' Genera lo stop Hlpw = 0 ' Contatore per timeout Do Incr Hlpw ' Incrementa contatore Call Ritardo(1) ' Pausa 1 msec Loop Until I2con.4 = 0 Or Hlpw > 20 ' Esce x stop finito o timeout I2con = &H00 ' Disattiva controllore I2C Call Att_tasto ' Consente lettura risultati Case "L": Inputhex "Inserire indirizzo esadecimale a quattro cifre: " , I2caddr I2con = &H40 ' Abilita la SIO Call Cmd_i2c(&H60) ' Invia lo start If I2cs <> 8 Then Printhex "Errore su Start (codice " ; I2cs ; "H)" Else I2dat = High(i2caddr) ' Scrive SLA+W Call Cmd_i2c(&H40) ' Resetta flag interrupt If I2cs <> &H18 Then Printhex "Errore su SLA+W (codice " ; I2cs ; "H)" Else I2dat = Low(i2caddr) ' Scrive Slave Address Call Cmd_i2c(&H40) ' Resetta flag interrupt If I2cs <> &H28 Then Printhex "Errore su Indirizzo (codice " ; I2cs ; "H)" Else Call Cmd_i2c(&H60) ' Invia il secondo start If I2cs <> &H10 Then Printhex "Errore su Secondo Start (codice " ; I2cs ; "H)" Else I2dat = High(i2caddr) Or &H01 ' Scrive SLA+R Call Cmd_i2c(&H40) ' Resetta flag interrupt If I2cs <> &H40 Then Printhex "Errore su SLA+R (codice " ; I2cs ; "H)" Else ' Usare I2CON=&H42 per effettuare piu' letture consecutive ' Intercettare il codice &H58 se la lettura effettuata non ' e' l'ultima della sequenza, altrimenti usare il codice ' qui sotto. Call Cmd_i2c(&H44) ' Resetta flag interrupt If I2cs <> &H50 Then ' Intercettare &H58 se ' la lettura non e' ' l'ultima di una ' sequenza Printhex "Errore su Lettura dato (codice " ; I2cs ; "H)" Else Printhex "Dato letto: " ; I2dat End If End If End If End If End If End If I2con = &H50 ' Genera lo stop Hlpw = 0 ' Contatore per timeout Do Incr Hlpw ' Incrementa contatore Call Ritardo(1) ' Pausa 1 msec Loop Until I2con.4 = 0 Or Hlpw > 20 ' Esce x stop finito o timeout I2con = &H00 ' Disattiva controllore I2C Call Att_tasto ' Consente lettura risultati End Select Loop End ' '************************ Fine del programma *************************** ' ' ' '************************ Procedure di uso generale **************************** ' Legge il byte di configurazione UCFG1 in FLASH grazie alle procedure IAP del ' Boot Rom del P89LPC932. Restituisce la variabile globale cclk settata con la ' frequenza di clock della CPU, senza controllare gli eventuali errori. Sub Get_clk mov A,#&H03 ' Usa comando Misc. Read mov R7,#&H00 ' Legge registro UCFG1 lcall &HFF03 ' Chiama proc. IAP ad ind. PGM_MTP mov A,R7 ' Salva risultato anl A,#&H07 ' Mantiene bit con clock CPU Select Case Acc Case &H00 : Cclk = Qz11m ' Frequenza clock da quarzo esterno Case &H03 : Cclk = Rcint ' Frequenza clock da RC interno End Select End Sub ' ' ' Effettua un ritardo del numero di millisecondi passato nel parametro rit, ' tenendo conto della frequenza di clock salvata nella variabile cclk senza ' usare le istruzioni BASCOM che usano un valore predefinito e costante di ' clock. Sub Ritardo(rit As Word) If Cclk = Rcint Then Rit1ms = 73 ' Valore sperimentale per 1 msec a 7 MHz Else Rit1ms = 110 ' Valore sperimentale per 1 msec a 11 MHz End If Do For R = 0 To Rit1ms ' Ciclo per ritardo di 1 msec Next R Rit = Rit - 1 Loop Until Rit = 0 End Sub ' ' '************************* Procedure gestione seriale ************************** ' Inizializza la linea seriale con: ' Bit x chr = 8 ' Stop bit = 1 o 2 a seconda del parametro ST ' Parity = None ' Baud rate = valore nel parametro BR ' usando l'apposito baud rate generator del micro e la frequenza di clock salvata ' nella variabile globale cclk. ' Usa le variabili generali hlpw,hlpl Sub Iniser(br As Long , St As Byte) Pcon = Pcon And &HBF ' Azzera bit SMOD0 x settare modo If St = 1 Then Scon = &H52 ' Modo 1 (1 stop),No multiproc,Attiva rx Else Scon = &HDA ' Modo 3 (2 stop),No multiproc,Attiva rx End If Brgcon = &H02 ' Imposta baud rate passato Hlpl = Br * 16 ' Calcola divisore per baud Hlpl = Cclk - Hlpl Hlpl = Hlpl / Br Hlpw = Loww(hlpl) Brgr0 = Low(hlpw) Brgr1 = High(hlpw) Brgcon = &H03 End Sub '*********************** Procedure gestione I2C BUS **************************** ' Scrive il comando passato nel parametro i2c nel registro di conrollo I2C ed ' attende il completamento dell'operazione impostata per poi leggere lo stato ' dello stesso controllore e restituirlo nella variabile globale i2cs ' Usa la variabile generale hlpw Sub Cmd_i2c(i2cc As Byte) I2con = I2cc ' Fornisce comando passato Hlpw = 0 ' Contatore timeout Do Incr Hlpw ' Incrementa contatore Call Ritardo(1) ' Pausa 1 msec Loop Until I2con.3 = 1 Or Hlpw > 50 ' Esce x flag interrupt o timeout I2cs = I2stat ' Legge stato attuale I2cs = I2cs And &HF8 ' Mantiene bit significativi End Sub ' ' ' Stampa messaggio di pressione tasto per uscita (per ridurre codice ' del programma che lo visulaizza in numerosi punti). Sub Tastoxuscire Print "Premere un tasto per uscire." End Sub ' ' ' Stampa il messaggio informativo ed attende la pressione di un tasto ' Usa la variabile generale st Sub Att_tasto Call Tastoxuscire Do St = Inkey ' Verifica tasto (NON sospensiva) Loop Until St <> 0 ' Ripete se nessun tasto End Sub ' ' ' Controllo correttezza periferiche interne con eventuali ritentativi ' Usa le variabili generali st,t,m,ind,hlpw Sub Check Deecon = &H01 T = Peek(&Hff) Deeadr = &HFF T = 1 Ind = &HF7 Do M = Peek(&H07) If M.7 = 1 Then M = M And &H03 Ind = M + &HF8 T = Peek(ind) Else T = 0 End If St = Deecon And &H80 Loop Until St <> 0 St = Deedat Do S = Peek(ind) Incr Ind If Ind = &HFF Then Ind = &HF9 Do M = S If St = 0 Then Incr T End If Loop Until St.0 = 0 Or T > M Loop Until St = 0 End Sub