*/
Got something to write about? Check out our Article Builder.
*/

View \USER.SRC

Code from app note AN425 using the 8584

Submitted By: WEBMASTER
Rating: (Not rated) (Rate It)


$TITLE (Demo program for PCD8584 I2C-routines)
$PAGELENGTH(40)
;Program displays on the LCD display  the time (with PCF8583).
;Dots on LCD display blink every second.
;On the LED display the values of the successive analog
;input channels are shown.
;Program reads analog channels of PCF8591P.
;Channel number and channel value are displayed successively.
;Values are displayed on LCD and LED display on I2C demo board.
;
        PUBLIC   SLAVE_ADR,I2C_CLOCK,PCD8584
        EXTRN    CODE(I2C_INIT,INT0_SRV,START)
        EXTRN    BIT(I2C_END,DIR)
        EXTRN    DATA(BASE,NR_BYTES,IIC_CNT,SLAVE)
;
;
;Define used segments
USER    SEGMENT  CODE   ;Segment for user program
RAMTAB  SEGMENT  DATA   ;Segment for table in internal RAM
RAMVAR  SEGMENT  DATA   ;Segment for variables
;
        RSEG RAMVAR
STACK:  DS 20           ;Stack area (20 bytes)
PREVIOUS: DS 1          ;Store for previous seconds
CHANNEL:DS 1            ;Channel number to be sampled
AN_VAL: DS 1            ;Analog value sampled channel
CONVAL: DS 3            ;Converted BCD value sampled channel
;
        CSEG AT 00H
        LJMP MAIN       ;Reset vector
;
        CSEG AT 03H     ;INT0/
        LJMP INT0_SRV   ;Vector I2C-interrupt
;
;
        RSEG USER
;Define I2C clock, own slave address and address for main processor
SLAVE_ADR EQU 55H       ;Own slaveaddress is 55h
I2C_CLOCK EQU 00011100B ;12.00MHz/90kHz
PCD8584   EQU 0000H     ;Address of PCD8584. This must be an EVEN number!!
;Define addresses of I2C peripherals
PCF8583R  EQU 10100011B ;Address PCF8583 with Read active
PCF8583W  EQU 10100010B ;Address PCF8583 with Write active
PCF8591R  EQU 10011111B ;Address PCF8591 with Read active
PCF8591W  EQU 10011110B ;Address PCF8591 with Write active
PCF8577W  EQU 01110100B ;Address PCF8577 with Write active
SAA1064W  EQU 01110110B ;Address SAA1064 with Write active
;
MAIN:   MOV SP,#STACK-1 ;Define stack pointer
;Initialise 80C31 interruptregisters for I2C interrupt (INT0/)
        SETB EX0        ;Enable interrupt INT0/
        SETB EA         ;Set global enable
        SETB PX0        ;Priority level is '1'
        SETB IT0        ;INT0/ on falling edge
;Initialise PCD8584
        CALL I2C_INIT
;
        MOV CHANNEL,#00 ;Set AD-channel
;
;Time must be read from PCD8583.
;First write word address and control register of PCD8583.
        SETB DIR        ;DIR='transmission'
        MOV BASE,#TABLE ;Start address I2C data
        MOV NR_BYTES,#02H ;Send 2 bytes
        MOV SLAVE,#PCF8583W
        CLR A
        MOV TABLE,A     ;Data to be sent (word address).
        MOV TABLE+1,A   ;      "         (control byte)
        CALL START      ;Start transmission.
FIN_1:  JNB I2C_END,FIN_1 ;Wait till transmission finished
;Send word address before reading time
REPEAT: SETB DIR        ;'transmission
        MOV BASE,#TABLE ;I2C data
        MOV SLAVE,#PCF8583W
        MOV A,#01
        MOV NR_BYTES,A  ;Send 1 byte
        MOV TABLE,A     ;Data to be sent is '1'
        CALL START      ;Start I2C transmission
FIN_2:  JNB I2C_END,FIN_2 ;Wait till transmission finished
;
;Time can now be read from PCD8583. Data read is
;hundredths of sec's, sec's, min's and hr's
        CLR DIR         ;DIR='receive'
        MOV BASE,#TABLE ;I2C table
        MOV NR_BYTES,#04; 4 bytes to receive
        MOV SLAVE,#PCF8583R
        CALL START      ;Start I2C reception
FIN_3:  JNB I2C_END,FIN_3 ;Wait till finished
;
;Transfer data to R2...R5
        MOV R0,#TABLE   ;Set pointers
        MOV R1,#02H     ;Pointer R2
TRANSFER:MOV A,@R0
        MOV @R1,A
        INC R0
        INC R1
        DJNZ NR_BYTES,TRANSFER
        MOV A,R5        ;Mask of hour counter
        ANL A,#3FH
        MOV R5,A
;
;Data must now be displayed on LCD display.
;First minutes and hours (in R4 and R5) must be
;converted from BCD to LCD segment data.The segment data
;will be transferred to TABLE. R0 is pointer to table
        MOV R0,#TABLE
        MOV @R0,#00H    ;Control word for PCF8577
        INC R0
        CALL CONV
;
;Switch on dp between hours and minutes
        ORL TABLE+3,#01H
;If lsb of seconds is '0' then switch on dp.
        MOV A,R3        ;Get seconds
        RRC A           ;lsb in carry
        JC PROCEED
        ORL TABLE+1,#01H;switch on dp
;
;Now the time (hours,minutes) can be displayed on the LCD
PROCEED:
        SETB DIR        ;Direction 'transmit'
        MOV BASE,#TABLE
        MOV NR_BYTES,#05H
        MOV SLAVE,#PCF8577W
        CALL START      ;Start transmission
;
FIN_4:  JNB I2C_END,FIN_4
        JMP ADCON       ;Proceed with AD-conversion part
;
;*****************************************************************
;Routines used by clock part of demo
;
;CONV converts hour and minute data to LCD data and stores
;it in TABLE.
CONV:   MOV DPTR,#LCD_TAB ;Base for LCD segment table
        MOV A,R5        ;Hours to accu
        SWAP A          ;Swap nibbles
        CALL LCD_DATA   ;Convert 10's hours to LCD data in table
        MOV A,R5        ;Get hours
        CALL LCD_DATA
        MOV A,R4        ;Get minutes
        SWAP A
        CALL LCD_DATA   ;Convert 10's minutes
        MOV A,R4
        CALL LCD_DATA   ;Convert minutes
        RET
;
;LCD_DATA gets data from segment table and stores it in TABLE
LCD_DATA:ANL A,#0FH     ;Mask off LS-nibble
        MOVC A,@A+DPTR  ;Get LCD segment data
        MOV @R0,A       ;Save data in table
        INC R0
        RET
;
;LCD_TAB is conversion table for LCD
LCD_TAB:       
        DB 0FCH,60H,0DAH; '0','1','2'
        DB 0F2H,66H,0B6H; '3','4','5'
        DB 3EH,0E0H,0FEH; '6','7','8'
        DB 0E6H         ; '9'
;
;*******************************************************************
;
;
;These part of the program reads an analog input-channel.
;Displaying is done on the LED-display
;On odd-seconds the channel number will be displayed.
;On even-seconds the analog value of this channel is displayed
;Then the next channel is displayed.
;
ADCON:  MOV A,R3        ;Get seconds
        RRC A           ;lsb to carry
        JNC NEW_MEAS    ;Even seconds; do a measurement on the current channel
;
;Display and/or update channel
        RLC A           ;Restore accu
        CJNE A,PREVIOUS,NEW_CH ;If new seconds, update channel number
        JMP DISP_CH
NEW_CH: INC CHANNEL
        MOV A,CHANNEL   ;If channel=4 then channel:=0
        CJNE A,#04,DISP_CH
        MOV CHANNEL,#00
DISP_CH:MOV PREVIOUS,R3 ;Update previous seconds
        MOV A,CHANNEL   ;Get segment value of channel
        MOV DPTR,#LED_TAB
        MOVC A,@A+DPTR
;
        MOV R0,#TABLE   ;Fill table with I2C data
        MOV @R0,#00     ;SAA1064 instruction byte
        INC R0
        MOV @R0,#77H    ;SAA1064 control byte
        INC R0
        MOV @R0,A       ;Channel number
        CLR A
        INC R0
        MOV @R0,A       ;Second digit
        INC R0
        MOV @R0,A       ;Third digit
        INC R0
        MOV @R0,A       ;Fourth byte
;
        SETB DIR        ;I2C transmission of channel number
        MOV BASE,#TABLE
        MOV NR_BYTES,#06H
        MOV SLAVE,#SAA1064W
        CALL START
;
FIN_5:  JNB I2C_END,FIN_5
        JMP REPEAT      ; Repeat clock and AD cycle again
;
;
;Measure and display the value of an AD-channel
NEW_MEAS: CALL AD_VAL   ;Do measurement
;Wait till values are available
FIN_6:  JNB I2C_END,FIN_6
;Relevant byte in TABLE+1. Transfer to AN_VAL
        MOV R0,#TABLE+1
        MOV AN_VAL,@R0
        MOV A,AN_VAL    ;Channel value in accu for conversion
;AN_VAL is converted to BCD value of the measured voltage.
;Input value for CONVERT in accu
;Address for MSByte in R1
        MOV R1,#CONVAL
        CALL CONVERT
;Convert 3 bytes of CONVAL to LED-segments
        MOV DPTR,#LED_TAB ;Base of segment table
        MOV R0,#CONVAL
        CALL SEG_LOOP
;Display value of channel to LED display
        CALL LED_DISP
FIN_8:  JNB I2C_END,FIN_8 ;Wait till I2C transmission is
        JMP REPEAT      ;Repeat clock and AD cycle
;
;****************************************************************
;Routines used for AD converter.
;
;AIN reads an analog values from channel denoted by CHANNEL.
;Send controlbyte:
AD_VAL: SETB DIR        ;I2C transmission
        MOV R0,#TABLE   ;Define control word
        MOV @R0,CHANNEL
        MOV BASE,#TABLE ;Set base at table
        MOV NR_BYTES,#01H ;Number of bytes to be send
        MOV SLAVE,#PCF8591W ;Slave address PCF8591
        CALL START      ;Start transmission of controlword
FIN_7:  JNB I2C_END,FIN_7 ;Wait until tranmission is finished
;Read 2 data bytes from AD-converter
;First data byte is from previous conversion and not
;relevant
        CLR DIR         ;I2C reception
        MOV BASE,#TABLE ;Bytes must be stored in TABLE
        MOV NR_BYTES,#02H; Receive 3 bytes
        MOV SLAVE,#PCF8591R ;Slave address PCF8591
        CALL START
        RET
;
;LED_DISP displays the data of 3 bytes from address CONVAL
LED_DISP:
        ORL CONVAL,#80H ;Set decimal point
        MOV R0,#TABLE
        MOV R1,#CONVAL
        MOV @R0,#00     ;SAA1064 instruction byte
        INC R0
        MOV @R0,#01110111B ;SAA1064 control byte
        INC R0
        MOV @R0,#00     ;First LED digit
        INC R0
        CALL GETBY      ;Second digit
        CALL GETBY      ;Third digit
        CALL GETBY      ;Fourth digit
        SETB DIR        ;I2C transmission
        MOV BASE,#TABLE
        MOV NR_BYTES,#06
        MOV SLAVE,#01110110B
        CALL START      ;Start I2C transmission
        RET
;
;CONVERT calculates the voltage of the analog value.
;Analog value must be in accu
;BCD result (3 bytes) is stored from address stored in R1
;Calculation: AN_VAL*(5/256)
CONVERT:MOV B,#05
        MUL AB
;b2..b0 of reg. B : 2E+2..2E0
;b7..b0 of accu   : 2E-1..2E-8               
        MOV @R1,B       ;Store MSB (10E0-units)
        INC R1
        MOV @R1,#00     ;Calculate 10E-1 units (10E-1 is 19h)
TEN_CH: CJNE A,#19H+03H,V1  ;Check if accu <= 0.11
        JMP TENS        ;accu=0.11; update tens
V1:     JC NX_CON       ;accu<0.11; update hundreds
TENS:   CLR C           ;Calculate new value
        SUBB A,#19H
        INC @R1         ;Update BCD byte
        JMP TEN_CH
;Correction may be neccessary. With 8 bits '0.1' is in fact 0.0976.
;A digit of '0A' may appear. Correct this by decrementing the digit.
;The intermediate result result must be corrected with 10*(0.1-0.0976)
;This is 06H
NX_CON: CJNE @R1,#0AH,PROC_CON ; If digit is '0A' then correct
        DEC @R1
        ADD A,#19H
PROC_CON:INC R1         
        MOV @R1,#00     ;Calculate 10E-2 units
HUND:   CJNE A,#03H,V2  ;Check if accu <= 10E-2
        JMP HUNS        ;accu=10E-2; update hundreds
V2:     JC FINISH       ;accu<10E-2; conversion finished
HUNS:   CLR C           ;Calculate new value
        SUBB A,#03H
        INC @R1         ;Update BCD byte
        JMP HUND
FINISH: CJNE @R1,#0AH,FIN ;Check if result is '0A'. Then correct.
        DEC @R1
FIN:    RET
;
;CALLBY tranfers byte from @R1 to @R0
GETBY:  MOV A,@R1
        MOV @R0,A
        INC R0
        INC R1
        RET
;
;SEG_LOOP converts 3 values to segment values.
;R0 contains address of source and destination
;DPTR contains base of table
SEG_LOOP: MOV R1,#03    ;Loop counter
INLOOP: MOV A,@R0     ;Get value to be displayed
        MOVC A,@A+DPTR  ;Get segment value from table
        MOV @R0,A       ;Store segment data
        INC R0
        DJNZ R1,INLOOP
        RET
;
;
;LED_TAB is conversion table for BCD to LED segments
LED_TAB:
        DB 7DH,48H,3EH  ; '0','1','2'
        DB 6EH,4BH,67H  ; '3','4','5'
        DB 73H,4CH,7FH  ; '6','7','8'
        DB 4FH          ; '9'
;
;************************************************************
;
        RSEG RAMTAB
TABLE:  DS 10
;
        END

corner
© 1996-2008 CommunityHeaven LLC. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
North American business development: Nicolai Wadstrom. Publisher: Lars Hagelin.