' ********************************************************************** ' ** Program: k51terme.BAS - Version : 1.2 - 10 december 2004 ** ' ** Compilator: BASCOM 8051, (IDE and LIB V.2.0.11.0) ** ' ** Scheda : K51-AVR driven by GMB HR84 and GMM 932 ** ' ** 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, ' DS1621, through mini-BLOCK module GMB HR84 and grifo(r) mini module. ' DS1621 is a programmable digital thermometer, whose resolution is half ' Celsius degreese, all the operations of programming and temperature ' acquisition are performed through synchronous serial interface I2C BUS. ' This demo shows the temperature acquired on the 7 segments display of ' K51-AVR. ' ' ' 05.06.2000 by Adriano Pedrielli (for K51 only) ' ' 10.12.2004 by Graziano Gaiba ' ' '****************** Compiler directives ************************** ' NOTE: Copy 89LPC932.DAT file in BASCOM-8051 root directory and inside ' "Options | Compiler | Misc" window perform the following settings: ' Register File = 89LPC932.DAT ' Byte End(Hex) = A0 ' Size warning = 7167 $regfile "89lpc932.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 ' '********************* Constants declaration *************************** ' 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 ' ' ********************************************************************** ' Dim Ds1621 As Const &H4C ' Slave address DS1621 Dim Wds1621 As Const &H98 ' Slave address DS1621 in Write Dim Rds1621 As Const &H99 ' Slave address DS1621 in Read ' ***************** Commands list of DS1621 **************************** Dim Cfg As Const &HAC ' R/W Config register of DS1621 Dim Rtemp As Const &HAA ' read temperature 2 bytes Dim Strct As Const &HEE ' Start temperature conversion Dim Stpct As Const &H22 ' Stop temperature conversion '*********************** Variables declaration ************************* ' Dim S0 As Bit ' Bit of generic use Dim I As Byte Dim Hlpb As Byte , M As Byte ' Byte of generic use Dim T As Byte , S As Byte , V 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 Valore As Byte ' value to read or write for I2CBUS Dim Dig As Byte ' 7 segments format number Dim Th As Byte ' high byte of temperature Dim Tl As Byte ' low byte of temperature 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 ' '********************** Procedure declarations ************************* ' Declare Sub Init() ' Initialization of Mini Module Declare Sub Iniz() ' Initialization of peripherals Declare Sub Clrscr() ' Clears the screen Declare Sub Temperatura ' Reads the temperature Declare Sub Cifre(valore As Byte , Cifc As Byte , Cifd As Byte , Cifu As Byte) ' Converts TH in degreeses Declare Sub Digit(dig As Byte ) ' Converts a number from 0-9 in 7 segments Declare Sub Vis_temp(th As Byte , Tl As Byte) ' Show temperature 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: ' Ritardo Assestamento segnali 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 DS1621 with GMB HR84+GMM 932 at " ; Cclk ; " MHz and K51-AVR" Call Check ' Internal check Call Iniz ' initializations Print Print "Temperature is shown on K51-AVR." Do Call Temperatura ' read temperature Th = Getdati(1) ' get high byte Tl = Getdati(2) ' get low byte Call Vis_temp(th , Tl) ' visualize temperature Loop End ' '**************************** Program end ****************************** ' '*********************** 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 ' ' ' 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 ' ' '********************** 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 &HFF00 ' 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 ' ' '**************************** 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 0 ' set DY1 off Call Cmd_i2cwbyte 0 ' set DY2 off Call Cmd_i2cwbyte 0 ' set DY3 off Call Cmd_i2cwbyte 0 ' set DY4 off Call Cmd_i2cstop Call Cmd_i2csend Wds1621 , Cfg ' point to Configuration register Call Cmd_i2creceive Rds1621 , Valore ' read Configuration register Valore = Valore And 1 ' mask Bit 0 If Valore = 1 Then ' if temperature conversion not actived Call Cmd_i2cstart ' Start sequence for I2CBUS Call Cmd_i2cwbyte Wds1621 ' Communicate the Slave address Call Cmd_i2cwbyte Cfg ' point to Configuration register Call Cmd_i2cwbyte &B00001010 ' write Configuration register ' bit1= 1 polarity "1" ' bit0= 0 continuous conversion Call Cmd_i2cstop Waitms 50 ' delay End If Call Cmd_i2csend Wds1621 , Strct ' start temperature conversion End Sub ' ' ' *************************** read temperature *************************** ' This procedure reads the value of the temperature. ' Parameters: ' Input : nothing ' Output : Getdati(0), contains TH, high byte of temperature ' Getdati(1), contains TL, low byte of temperature ' ************************************************************************ ' Sub Temperatura ' read temperature Getdati(1) = Rtemp Call Cmd_n_i2creceive Wds1621 , Getdati(1) , 1 , 2 End Sub ' ' ' *********** Converts a figure in range from 0 to F in 7 segments ***** ' This procedure converts a figure in range from 0 to 9 in 7 segments format, if ' value is equal to or greater than 11 the display is off, if equal to 10 a ' negative sign is displayed. ' Parameters: ' Input : dig as byte, value from 0 to 9 ' Output : dig as byte, value in 7 segments format. ' ************************************************************************ ' Sub Digit(dig As Byte ) ' Converts a figure in range from 0 to F in 7 segments If Dig < 10 Then ' if number is lower thawn 16 Dig = Lookup(dig , Tab_7seg) ' read value from table Else If Dig > 10 Then ' if true trun off dispaly Dig = 0 Else ' if = 10 Dig = 64 ' show "-" End If End If End Sub ' ' ***************** Converte 1 byte in two "temperature" figures ************* ' This procedure converts 1 byte from 0 to 255 in a temperature, that is a ' value from 0 to 125 means positive centigrad degreeses (+0..+125), while a ' value from 255 to 201 means negative centigrad degreeses (-0..-55), bit 7 is ' the sign bit, negative degreeses are obtained complementing. ' E.g.: Not 255=0, Not 201=54 ' Parameters: ' Input : Valore as byte, value from 0 to 255 ' Uscita : Cifc As Byte , Cifd As Byte , Cifu As Byte, which contain hundreds, ' decines and unitsofthe temperature. ' ***************************************************************************** ' Sub Cifre(valore As Byte , Cifc As Byte , Cifd As Byte , Cifu As Byte) If Valore > 127 Then ' temperature results negative Cifc = 10 ' minus sign actived Valore = Not Valore ' complement the value Else If Valore > 99 Then ' if positive, over 99 Cifc = 1 ' activate figure "1" of hundreds Valore = Valore - 100 ' subtract 100 Else Cifc = 11 ' not over 99, turn off the figure ' of hundreds End If End If If Valore > 9 Then ' freater than 9 Cifd = Valore / 10 ' calculate figure of decines Cifu = Cifd * 10 ' calculate figure of units Valore = Valore - Cifu Cifu = Valore Else If Cifc = 11 Then ' lower than 9 and figure of hundreds off Cifd = 11 ' turn off figure of decines Else If Cifc = 10 Then ' lower than 9, and negative temperature Cifd = 11 ' turn off figure of decines Else Cifd = 0 ' lower than 9 and figure of hundreds on ' show a zero End If End If Cifu = Valore ' save value of units End If End Sub ' ' *********************** Temperature visualization *********************** ' This procedure allows to visualize the temperature stored in 2 bytes ' TH high byte and TL low byte ' TL indicates helf degree 0 or 128 (0 .. 0.5). ' TH indicates degreeses from 0 to 125 (+0..+125), and from 255 to 21 ( -0..-54). ' Parameters: ' Input : TH as byte, high byte value ' TL as byte, low byte value ' Output : nothing ' ************************************************************************ ' Sub Vis_temp(th As Byte , Tl As Byte) ' Temperature visualization Call Cmd_i2cstart ' Start sequence for I2CBUS Call Cmd_i2cwbyte Wsaa1064 ' Communicate the Slave address Call Cmd_i2cwbyte Dig1 ' point to display 1 (DY1) Call Cifre(th , Cifc , Cifd , Cifu) ' convert in 3 figures Call Digit(cifc) ' convert figure of hundreds ' in 7 segments Call Cmd_i2cwbyte Dig ' output to the first display Call Digit(cifd) ' convert figure of decines ' in 7 segments Call Cmd_i2cwbyte Dig Call Digit(cifu) ' convert figure of units ' in 7 segments Dig = Dig Or 128 ' turn on decimal point Call Cmd_i2cwbyte Dig ' output to third terzo display If Tl = &H80 Then ' visualize the half degree Call Digit(5) ' convert figure of units ' in 7 segments Else Call Digit(0) ' convert figure of units ' in 7 segments End If Call Cmd_i2cwbyte Dig ' output to fourth display Call Cmd_i2cstop ' Stop sequence for I2CBUS End Sub ' ' ***** Conversion table for 7 segments figure in the range from 0 to 15 ******* Tab_7seg: ' num. 0 1 2 3 4 5 6 7 8 9 Data &H3F , &H06 , &H5B , &H4F , &H66 , &H6D , &H7D , &H07 , &H7F , &H6F ' ****************************************************************************** '