' ********************************************************************** ' ** Program: k51ppoe.BAS - Version : 1.1 - 06 June 2005 ** ' ** Compiler: BASCOM 8051 DEMO, (IDE and LIB V.2.0.11.0) ** ' ** Board: K51-AVR driven by GMB HR84 and GMM 936 ** ' ** Firm: 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 drive an I2C BUS peripheral on board of K51-AVR, PCF8574, ' through mini-BLOCK module GMB HR84 and grifo(r) mini module. ' PCF 8574 is an I/O expander that allows to drive 8 TTL digital lines, both as ' input and as output, all the operations of read and write are performed ' through synchronous serial interface I2C BUS. ' This demo activates in sequence one line at a time, creating the classic bit ' shift to the right and to the left, and writes 'out' on the 7 segments ' display of K51-AVR, near the characters 'out'. ' ' ' 06.06.05 - Rel 1.1 By Graziano Gaiba ' ' '****************** Compiler directives ************************** ' NOTE: Copy 89LPC936.DAT file in BASCOM-8051 root directory and inside ' "Options | Compiler | Misc" window perform the following settings: ' Register File = 89LPC936.DAT ' Byte End(Hex) = A0 ' Size warning = 7167 $regfile "89lpc936.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 ' Dim Saa1064 As Const &H38 ' Slave address SAA1064 Dim Wsaa1064 As Const &H70 ' Slave address SAA1064 in Write Dim Rsaa1064 As Const &H71 ' Slave address SAA1064 in Read '****************** Addresses list for Saa1064 ************************* Dim Ctb As Const 0 ' Address Control byte Dim Dig1 As Const 1 ' Address Digit 1 Dim Dig2 As Const 2 ' Address Digit 2 Dim Dig3 As Const 3 ' Address Digit 3 Dim Dig4 As Const 4 ' Address Digit 4 '*********************************************************************** ' ********************************************************************** ' Comment the declaration of the component not used, uncomment the other ' declaration ' 'Dim Pcf8574 As Const &H3C ' Slave address PCF8574A 'Dim Wpcf8574 As Const &H78 ' Slave address PCF8574A in Write 'Dim Rpcf8574 As Const &H79 ' Slave address PCF8574A in Read Dim Pcf8574 As Const &H24 ' Slave address PCF8574P Dim Wpcf8574 As Const &H48 ' Slave address PCF8574P in Write Dim Rpcf8574 As Const &H49 ' Slave address PCF8574P in Read ' '*********************** Variables declaration ************************* ' Dim Pout As Byte ' value for output signals Dim X As Byte ' general purpose Dim Valore As Byte ' counter Dim I As Byte Dim Hlpb As Byte , M As Byte ' Byte of generic use Dim T As Byte ' Byte of generic use Dim Hlpw As Word , Ind As Word ' Word of generic use Dim Hlpl As Long ' Long of generic use ' Dim Dig As Byte ' 7 segments format number Dim Cifc As Byte ' figure of hundreds Dim Cifd As Byte ' figure of decines Dim Cifu As Byte ' figure of units ' Variables to manage communication, clock and delays Dim St As Byte Dim Br As Long ' Serail Buad Rate Dim Cclk As Long ' CPU clock frequency Dim R As Word , Del1ms As Word , Del As Word ' Delays ' Variables to manage Port I/O Dim M1 As Byte , M2 As Byte ' Variables to manage I2C Dim I2cc As Byte , I2cs As Byte Dim I2cdato As Byte Dim I2caddr As Word ' Used by I2C BUS hardware routines Dim I2c_slave As Byte , I2c_byte As Byte Dim Dummy As Byte , N_out As Byte , N_in As Byte Dim Getdati(2) As Byte ' vectore of 2 bytes ' '********************* Procedures declaration ************************** ' Declare Sub Init() ' Initialization of Mini Module Declare Sub Iniz() ' Initialization of peripherals Declare Sub Clrscr() ' Clears the screen Declare Sub Check() ' Internal check Declare Sub Ritardo(del As Word) ' Calibrated delay Declare Sub Iniser(br As Long , St As Byte) ' Initialization of serial port Declare Sub Cmd_i2c(i2cc As Byte) ' Send I2C command ' ' I2C BUS routines Declare Sub Cmd_i2cstart ' Send I2C start Declare Sub Cmd_i2cstop ' Send I2C stop ' Receive one byte in variable I2c_byte from specified slave address Declare Sub Cmd_i2creceive(i2c_slave As Byte , I2c_byte As Byte) ' Send one byte in variable I2c_byte to specified slave address Declare Sub Cmd_i2csend(i2c_slave As Byte , I2c_byte As Byte) ' Receive one byte Declare Sub Cmd_i2cwbyte(i2c_byte As Byte) ' Send n_out bytes from array Getdati to specified slave address and receive ' N_in bytes in array Getdati from the same slave address Declare Sub Cmd_n_i2creceive(i2c_slave As Byte , Dummy As Byte , N_out As Byte , N_in As Byte) ' '*************************** Main program ****************************** ' Main: Call Get_clk ' Acquires CPU clock frequency Call Iniser(19200 , 1) ' Initializes serial for console Call Init ' Initializes the module ' 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 ' ' ' Call Clrscr() Print "Demo for use of PCF 8574 with GMB HR84+GMM 936 at " ; Cclk ; " MHz and K51-AVR" Call Check ' Internal check Call Iniz ' initializations Print Print "Shift on signals of connector CN1." Do Valore = 1 ' starting value For X = 1 To 7 ' cycle initialization Pout = Not Valore ' complement the value Call Cmd_i2csend Wpcf8574 , Pout ' set the outputs Rotate Valore , Left ' left shift of bits Waitms 255 ' delay Next X For X = 1 To 7 ' cycle initialization Pout = Not Valore ' complement the value Call Cmd_i2csend Wpcf8574 , Pout ' set the outputs Rotate Valore , Right ' right shift of the bits Waitms 255 ' delay Next X Loop End ' '*************************** Programma end ****************************** ' ' ' '**************************** Demo specific Procedures ****************** ' ' ********************** Peripherals initialization ******************** ' This procedure performs all the system initializations. ' Parameters: ' Input : nothing ' Output : nothing ' ************************************************************************ ' Sub Iniz ' Peripherals initialization Do Call Cmd_i2creceive Rsaa1064 , Valore ' Read the status register Loop Until Valore = 0 ' Wait for SAA1064 to turn on Call Cmd_i2cstart ' Start sequence for I2CBUS Call Cmd_i2cwbyte Wsaa1064 ' Communicate the Slave address Call Cmd_i2cwbyte Ctb ' Point to control register Call Cmd_i2cwbyte &B00100111 ' 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 indifferent Call Cmd_i2cwbyte 92 ' set DY1 "o" Call Cmd_i2cwbyte 28 ' set DY2 "u" Call Cmd_i2cwbyte 120 ' set DY3 "t" Call Cmd_i2cwbyte 0 ' set DY4 off Call Cmd_i2cstop 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 ' ' '********************** 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 ' ' ' 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 ' ' ' 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 ' ' ' ' 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 ' ' Specific I2C Bus init P1m1 = P1m1 And &HF3 ' Configures P1.2 (SCL) and P1.3 P1m2 = P1m2 And &HF3 ' (SDA) in open drain mode P1 = P1 Or &H0C ' as input If Cclk = Rcint Then I2scll = 37 ' Bit rate is 2*(37+37) clock cycles I2sclh = 37 ' (7 MHz) equals to about 50 KHz Else I2scll = 55 ' Bit rate is 2*(55+55) clock cycles I2sclh = 55 ' (11 MHz) equals to about 50 KHz End If 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 ' ' ' Send start to I2C BUS using hardware peripheral Sub Cmd_i2cstart I2con = &H40 ' Enable SIO1 Call Cmd_i2c(&H60) ' Generate start End Sub ' ' ' Send stop to I2C BUS using hardware peripheral Sub Cmd_i2cstop I2con = &H50 ' Generate stop Hlpw = 0 ' 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 End Sub ' ' ' Send one byte to I2C BUS using hardware peripheral Sub Cmd_i2cwbyte(i2c_byte As Byte) I2dat = I2c_byte ' Write data Call Cmd_i2c(&H40) ' Reset flag interrupt End Sub ' ' ' Send one byte to I2C BUS to indicated slave address using hardware peripheral Sub Cmd_i2csend(i2c_slave As Byte , I2c_byte As Byte) Call Cmd_i2cstart ' Send start I2dat = I2c_slave ' Write slave address Call Cmd_i2c(&H40) ' Reset flag interrupt I2dat = I2c_byte ' Write data Call Cmd_i2c(&H40) ' Reset flag interrupt Call Cmd_i2cstop ' Send stop End Sub ' ' ' Read one byte from indicated slave address using hardware peripheral Sub Cmd_i2creceive(i2c_slave As Byte , I2c_byte As Byte) Call Cmd_i2cstart ' Send start I2dat = I2c_slave ' Write slave address Call Cmd_i2c(&H40) ' Reset flag interrupt I2dat = I2c_byte ' Write data Call Cmd_i2c(&H40) ' Reset flag interrupt Call Cmd_i2cstart ' Send second start I2dat = I2c_slave Or 1 ' Write slave address + R Call Cmd_i2c(&H40) ' Reset flag interrupt Call Cmd_i2c(&H44) ' Read one byte and send NACK I2c_byte = I2dat ' Data read stored in I2c_byte Call Cmd_i2cstop ' Send stop End Sub ' ' ' Send n_out bytes from array Getdati to specified slave address and receive ' N_in bytes in array Getdati from the same slave address Sub Cmd_n_i2creceive(i2c_slave As Byte , Dummy As Byte , N_out As Byte , N_in As Byte) Call Cmd_i2cstart ' Send start I2dat = I2c_slave ' Write slave address Call Cmd_i2c(&H40) ' Reset flag interrupt For Dummy = 1 To N_out I2dat = Getdati(dummy) ' Write data Call Cmd_i2c(&H40) ' Reset flag interrupt Next Dummy Call Cmd_i2cstart ' Second second start I2dat = I2c_slave Or 1 ' Write slave address + R Call Cmd_i2c(&H40) ' Reset flag interrupt For Dummy = 1 To N_in If Dummy = N_in Then ' If last byte to read Call Cmd_i2c(&H40) ' Read one byte and send NACK Else Call Cmd_i2c(&H44) ' Read one byte and send ACK End If Getdati(dummy) = I2dat ' Store data read into the array ' called Getdati() Next Dummy Call Cmd_i2cstop ' Send stop End Sub