' ********************************************************************** ' ** Program : gmbi2ce.bas - Version : 1.2 - 18 November 2004 ** ' ** Compiler : BASCOM 8051 DEMO, (IDE and LIB V.2.0.11.0) ** ' ** Board : GMB HR84 with GMM 935 ** ' ** Corporate: 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 ** ' ** Written by: Graziano Gaiba ** ' ********************************************************************** ' ' This demo allows to communicate to I2C BUS devices connected to CN3. ' It is possible to read or write bytes at any slave address and location ' address input by console. In detail, when reading the byte read is ' visualized and when writing the byte input is sent. ' ' 24.06.03 - Rel 1.1 By Graziano Gaiba ' ' 18.11.04 - Rel 1.2 By Graziano Gaiba ' Modified to run on a GMM 935 ' ' '************************ Compiler directives ********************************** ' NOTE: Copy 89LPC935.DAT file in BASCOM-8051 root directory and inside ' "Options | Compiler | Misc" window perform the following settings: ' Register File = 89LPC935.DAT ' Byte End(Hex) = A0 ' Size warning = 8191 $regfile "89lpc935.dat" $romstart = &H0 ' Start add. of code in FLASH $ramstart = &H0 ' Start add. of data in XRAM $ramsize = &H200 ' Size of data area in XRAM $crystal = 11059200 ' Maximum Fclock of the card $baud = 19200 ' Serial communication speed $large ' Code size > 2K $map ' Generates debug info '************************* Constants declaration ******************************* Const Cret = 13 ' Used ASCII codes Const Lf = 10 Const Bell = 7 Const Rcint = 7372800 ' Internal RC clock frequency Const Qz11m = 11059200 ' External crystal clock frequency '************************* Variables declaration ******************************* ' General purpose variables Dim I As Byte Dim Hlpb As Byte , T As Byte , M As Byte ' General purpose Byte Dim Hlpw As Word , Ind As Word ' General purpose Word Dim Hlpl As Long ' General purpose Long Dim Choice As String * 1 ' One char string ' Variables for serial communication Dim St As Byte ' Stop bit number Dim Br As Long ' Serial Buad Rate ' Variables for clock and delays management Dim Cclk As Long ' CPU clock requency Dim R As Word , Del1ms As Word , Del As Word ' Delays management ' Variables for digital I/O ports management Dim M1 As Byte , M2 As Byte ' Variables for I2C management Dim I2cc As Byte , I2cs As Byte Dim I2cdata As Byte Dim I2caddr As Word '************************* Subroutines declaration ***************************** Declare Sub Get_clk ' Acquires clock frequency Declare Sub Init ' General initialization Declare Sub Ritardo(del As Word) ' Calibrated delay Declare Sub Iniser(br As Long , St As Byte) ' Serial initialization Declare Sub Clrscr ' Clears console monitor Declare Sub Keytoexit ' Requires key pressed Declare Sub Key_wait ' Waits key pressed Declare Sub Check ' Verifies peripherals Declare Sub Show_run ' Shows start execution of program Declare Sub Cmd_i2c(i2cc As Byte) ' Sends command to I2C Declare Sub I2c ' Demo for I2C BUS management '******************************* Main program ********************************** Main: Call Init ' Initializes the module Call Get_clk ' Acquires CPU clock frequency Call Iniser(19200 , 1) ' Initializes serial for console ' Performs a delay of about 2 seconds to allows the presence of emulation ' terminal program for console (i.e. HYPERTERMINAL) and contemporaneosly blinks ' the activity LED DL1 of the card. ' Uses general purpose variable i P0m1 = P0m1 Or &H40 ' Sets P0.6 in mode 3=OpenDrain P0m2 = P0m2 Or &H40 For I = 1 To 16 ' 16 cycles of 125 msec=2 sec P0.6 = Not P0.6 ' Complements activity LED Call Ritardo(125) ' Delays about 125 msec Next I Do Call Clrscr ' Clears console Print "I2C BUS demo Ver. 1.2 for GMB HR84 ds 220503 + GMM 932 ds 300803 at " ; Cclk ; " MHz" Print Print "1) I2C BUS Master" Print Print "Choice:"; Choice = Waitkey() ' Waits key from console Choice = Ucase(choice) ' Converts in upper case Select Case Choice Case "1" : Call I2c Case Else : Print Chr(bell) End Select Loop End '**************************** End of main program ****************************** '********************* Card sections demo subroutines ************************** ' Demo subroutine for I2C hardware interface in Master transmit and Master ' receive mode with a fixed bit rate. It allows to read and write a generic ' I2C device, thanks to the possibility to insert the Slave addres, the address ' and the data, from console. ' Uses the general purpose variables choice,hlpw Sub I2c P1m1 = P1m1 And &HF3 ' Configures P1.2(SCL), P1.3 P1m2 = P1m2 And &HF3 ' (SDA) in quasi bidirectional P1 = P1 Or &HC0 ' mode in input If Cclk = Rcint Then I2scll = 37 ' Bit rate=2*(37+37) clock cycles I2sclh = 37 ' (7 MHz) equal to about 50 KHz Else I2scll = 55 ' Bit rate=2*(55+55) clock cycles I2sclh = 55 ' (11 MHz) equal to about 50 KHz End If Do Call Clrscr ' Clears the console Print " I2C BUS management demo" Print Print "Interface management in Master mode: allows to comunicate with each slave" Print "peripheral (EEPROM, RTC, A/D, D/A, etc.) through the pin 6=SCL and 7=SDA" Print "of the CN1 socket, with a 50 KHz fixed bit rate." Print Print "R) Read" Print "W) Write" Print "E) Exit" Print Print "Choice: "; Do ' Cycle that waits valid choice Choice = Waitkey() Choice = Ucase(choice) Loop Until Choice = "R" Or Choice = "W" Or Choice = "E" Print Choice Print Select Case Choice Case "W": Inputhex "Insert the 4 digits hexadecimal address: " , I2caddr Inputhex "Insert the 2 digits hexadecimal value to write: " , I2cdata I2con = &H40 ' Enables I2C controller Call Cmd_i2c(&H60) ' Sends Start If I2cs <> &H08 Then Printhex "Error on Start (code " ; I2cs ; "H)" Else I2dat = High(i2caddr) ' Sends SLA+W Call Cmd_i2c(&H40) ' Resets interrupt flag If I2cs <> &H18 Then Printhex "Error on SLA+W (code " ; I2cs ; "H)" Else I2dat = Low(i2caddr) ' Sends Address Call Cmd_i2c(&H40) ' Resets interrupt flag If I2cs <> &H28 Then Printhex "Error on Address (code " ; I2cs ; "H)" Else I2dat = I2cdata ' Sends data Call Cmd_i2c(&H40) ' Resets interrupt flag If I2cs <> &H28 Then Printhex "Error on Data (code " ; I2cs ; "H)" End If End If End If I2con = &H50 ' Sends Stop Hlpw = 0 ' Resets timeout counter Do Incr Hlpw ' Increments counter Call Ritardo(1) ' 1 msec delay Loop Until I2con.4 = 0 Or Hlpw > 20 ' Exit if Stop complete or timeout I2con = &H00 ' Disables I2C controller Call Key_wait ' Allows results reading Case "R": Inputhex "Insert the 4 digits hexadecimal address: " , I2caddr I2con = &H40 ' Enables I2C controller Call Cmd_i2c(&H60) ' Sends Start If I2cs <> 8 Then Printhex "Error on Start (code " ; I2cs ; "H)" Else I2dat = High(i2caddr) ' Sends SLA+W Call Cmd_i2c(&H40) ' Resets interrupt flag If I2cs <> &H18 Then Printhex "Error on SLA+W (code " ; I2cs ; "H)" Else I2dat = Low(i2caddr) ' Sends Address Call Cmd_i2c(&H40) ' Resets interrupt flag If I2cs <> &H28 Then Printhex "Error on Address (code " ; I2cs ; "H)" Else Call Cmd_i2c(&H60) ' Sends second Start If I2cs <> &H10 Then Printhex "Error on second Start (code " ; I2cs ; "H)" Else I2dat = High(i2caddr) Or &H01 ' Sends SLA+R Call Cmd_i2c(&H40) ' Resets interrupt flag If I2cs <> &H40 Then Printhex "Error on SLA+R (code " ; I2cs ; "H)" Else ' Use I2CON=&H42 to perform more consecutive readings ' Intercept code &H58 if the executed reading is not the last ' of the sequence, otherwise use the following code. Call Cmd_i2c(&H44) ' Resets interrupt flag If I2cs <> &H50 Then ' Intercept &H58 if the ' reading is not the last ' of a sequence Printhex "Error on data Reading (code " ; I2cs ; "H)" Else Printhex "Data read: " ; I2dat End If End If End If End If End If End If I2con = &H50 ' Sends Stop Hlpw = 0 ' Resets timeout counter Do Incr Hlpw ' Increments counter Call Ritardo(1) ' 1 msec delay Loop Until I2con.4 = 0 Or Hlpw > 20 ' Exits if Stop complete or timeout I2con = &H00 ' Disables I2C controller Call Key_wait ' Allows results reading End Select Loop Until Choice = "E" End Sub ' Initializes resources, variables and peripheral device to allow right ' execution of all demo program. Sub Init Disable Interrupts ' Disables interrupts P1m1 = 0 ' Initializes necessary lines Call Check ' Internal check End Sub ' Performs a calibrated delay long as many milliseconds as specified in the ' passed parameter del, according with the clock frequency saved in cclk ' variable, with no use of BASCOM instructions that use a fixed and preset ' value of clock. Sub Ritardo(del As Word) If Cclk = Rcint Then Del1ms = 73 ' Value for 1 msec at 7 MHz Else Del1ms = 110 ' Value for 1 msec at 11 MHz End If Do For R = 0 To Del1ms ' Cycle for 1 msec delay Next R Del = Del - 1 Loop Until Del = 0 End Sub ' Performs the clear screen functions for a generic console device. ' Uses general purpose variable i Sub Clrscr Printbin Cret For I = 0 To 25 Printbin Lf ' Transmits 25 Line Feeds Next I End Sub ' Prints message that requires a key pressed to exit (developed to reduce the ' code size of the program that shows it in many points). Sub Keytoexit Print "Press a key to exit." End Sub ' Prints information message that ask for a key and wait the key pressure. ' Uses general purpose variable st Sub Key_wait Call Keytoexit Do St = Inkey ' Verifies key (NOT suspend) Loop Until St <> 0 ' Repeats if no key End Sub ' Checks right functionality of internal devices with possible remakes. ' Uses general purpose variable 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 St = St And &H80 Loop Until St <> 0 T = St St = Deedat Do M = Peek(ind) Incr Ind If Ind = &HFF Then Ind = &HF9 Hlpw = 0 Do Incr Hlpw M = Peek(ind) Loop Until St.0 = 0 Or Hlpw >= 1000 T = T + M Hlpw = Ind + T M = Peek(t) If St = 0 Then Incr T Else Call Ritardo(1) ' 1 msec pause End If Loop Until St = 0 End Sub '*********************** Serial management subroutines ************************* ' Initializes the serial line with: ' Bit x chr = 8 ' Stop bit = 1 or 2 according with ST parameter ' Parity = None ' Baud rate = value of BR parameter ' by using the proper baud rate generator of microcontroller and his clock ' frequency saved on global variable cclk. ' Uses general purpose variables hlpw,hlpl Sub Iniser(br As Long , St As Byte) Pcon = Pcon And &HBF ' Resets bit SMOD0 to set mode If St = 1 Then Scon = &H52 ' Mode 1 (1 stop),No multiproc,Rx enable Else Scon = &HDA ' Mode 3 (2 stop),No multiproc,Rx enable End If Brgcon = &H02 ' Sets passed baud rate Hlpl = Br * 16 ' Calculates divisor for baud Hlpl = Cclk - Hlpl Hlpl = Hlpl / Br Hlpw = Loww(hlpl) Brgr0 = Low(hlpw) Brgr1 = High(hlpw) Brgcon = &H03 End Sub '********************** I2C BUS management subroutine ************************** ' Writes the command passed in i2c parameter in the control register I2C, waits ' the complete execution of the selected operation and then reads the same ' controller status that is returned in global variable i2cs. ' Uses general purpose varaiable hlpw Sub Cmd_i2c(i2cc As Byte) I2con = I2cc ' Writes passed command Hlpw = 0 ' Resets timeout counter Do Incr Hlpw ' Increments counter Call Ritardo(1) ' 1 msec delay Loop Until I2con.3 = 1 Or Hlpw > 50 ' Exit if interrupt flag or timeout I2cs = I2stat ' Reads current status I2cs = I2cs And &HF8 ' Masks significant bits End Sub ' ' ' ' '********************** General purpose subroutines **************************** ' Reads the configuration byte UCFG1 on FLASH thanks to IAP procedures of ' P89LPC932 Boot Rom. Returns the global variable cclk set with the CPU clock ' frequency, with no control of the possible errors. Sub Get_clk mov A,#&H03 ' Uses command Misc. Read mov R7,#&H00 ' Reads register UCFG1 lcall &HFF03 ' Calls IAP proc. at PGM_MTP addr. mov A,R7 ' Saves result anl A,#&H07 ' Masks bits with CPU clock Select Case Acc Case &H00 : Cclk = Qz11m ' Ext. crystal clock frequency Case &H03 : Cclk = Rcint ' Internal RC clock frequency End Select End Sub