;**********************************************************

 

; PIC assembler software routines for reading from and writing to the EEPROM memory of

; a PIC16F84 (or PIC16C84).

 

; When programming your PIC, activate the power up timer and disable the watchdog timer (unless

; you add to this code to handle the watchdog timer).

 

; Written by Glenn Pure (Glenn.Pure@pcug.org.au). Please mail any significant improvements you

; may make to this code (and the accompanying C software) as I might be able to use them myself!

 

;**********************************************************

 

; Processor is PIC16C84

            #DEFINE PIC16C84

 

; Include file for PIC16C84

            INCLUDE       <P16C84.INC>

 

 

;--------------------------------------------

; Setup configurations fuses for processor; must first declare processor

 

            __CONFIG     B'00000000011001'   ; XT oscillator, power up time active

;--------------------------------------------

 

; Assembler constants

 

BIT_CNT        EQU    0x0f                 ; bit counter register address (number of bits)

BYT_CNT      EQU    0x10                ; byte counter register address (number of bytes)

BITS    EQU    8                      ; number of bits to read or write

BYTES            EQU    64                    ; number of bytes to read or write

 

AA      EQU    0x0c                ; General purpose register AA

BB       EQU    0x0d                ; General purpose register BB

CC      EQU    0x0e                ; General purpose register CC

 

 

;--------------------------------------------

 

 

;Jump past interrupt handler

 

            ORG    0x00

 

BEGIN            GOTO BOOTUP

 

;Interupt handler: Note, when interupt is actioned by processor, it automatically pushes the

;program counter onto the stack and resets INTCON:GIE.

 

            ORG    0x04                ; Start location for interupt handler

 

 

            BTFSC            INTCON,INTF          ; Is this a request to read/write EEPROM memory?

            GOTO PC_DATA                  ; If interupt pin (RB0/INT) interupt received, jump to

                                               ; service routine for this. This routine responsible for

                                               ; popping program counter from stack (with RETFIE) if needed

           

 

 

;***********************************************************************************************

;Bootup code: set interupt status and correct status for I/O ports

 

BOOTUP        MOVLW        B'10010000'    ; initialise interupt status

            MOVWF        INTCON                    ; GIE enabled, RB0/INT pin interupt enabled,

                                               ; all others off & all flags cleared

            BSF     STATUS,RP0 ; Select register page 1

            MOVLW        B'11100000'

            MOVWF        TRISA             ; set RA0 to RA4 as outputs

            MOVLW        B'11111011'

            MOVWF        TRISB             ; set PORT B, pin RB2 to output, all the rest are inputs

            MOVLW        B'00010110'    ; set up TMR0 to on, use internal clock, prescaler 128

                                               ; INT pin interupt is falling edge, weak pull-ups on port B

            MOVWF        OPTION_REG           ; (note: timer not used here)

            BCF    STATUS,RP0 ; reset register addressing to page 00

 

;Waste time

DO_NIL         NOP

            NOP

            NOP

            NOP

            NOP

            NOP

            GOTO DO_NIL

 

 

 

;***********************************************************************************************

; Routine for read/write of data from PC parallel port.

 

; The following lines are used for I/O (these may be changed except for RB0/INT which is used

; to receive the initial interupt that signal entry to this block of code. That is, you may

; use any I/O port pin on the PIC to replace pin assignments below - obviously, the code

; will need to be modified accordingly):

 

; Note: Port B is set with internal pull-up resistors active. Default state of all Port B input

; pins is therefore high.

 

; RB0/INT The interupt to enter the routines below is on falling edge of RB0/INT. On PC side,

;           connected to [note output pin of printer port here].

 

; RB1 on the PIC is for serial data in to PIC. On the PC side, it is connected to [note output

;           pin of printer port here].

;           During initiation of I/O, this line is also used to signal when data from PC is ready.

 

; RB2 on the PIC is for serial data out. On the PC side, it is connected to [note input pin

;           of printer port here]

;           Bits are output most significant bit first. RB2 is also used to signal whether PIC is

;           ready or not to receive data from PC (high = ready)

;           RB2 is also used during the initial handshake to establish I/O.

 

; RB3 on the PIC is clock input for data read and write operations. On the PC side,

;           it is connected to [note output pin of printer port here].

 

; RB6 on the PIC is read/write input signal. low = write to PIC; high = read PIC. On the PC side,

;           it is connected to [note output pin of printer port here].

 

; RA0 on the PIC is an output signal to the PC used to signal when EERAM write is completed

;           during the reprogramming of EERAM by the computer. A high signals the write is complete.

;           On the PC side, it is connected to [note input pin of printer port here].

 

; The following constants are used:

; BIT_CNT (RAM address): counter for number of bits read from PIC or received for writing.

;           (also used as a time out counter to abort main routine if PC doesn't respond in time)

; BYT_CNT (RAM address): counter for number of bytes to read from PIC or received for writing.

; EEDATA (PIC register): contains current byte of data being sent to PC or received for writing.

; BITS (constant): number of bits per byte.

; BYTE (constant): number of bytes to read from PIC or received for writing.

 

; A fresh RB0/INT interupt is needed to enter either read or write routines. Each routine

; exits completely from this block of code when done. To get into read or write routines, the

; 'handshake' code is first executed.

 

PC_DATA      BCF    STATUS,RP0 ; ensure register addressing at page 0

            BSF     PORTB,2                    ; initialise RB2 output (to high)

 

                                               ; Note: code from here on relies on polling the inputs

                                               ; Interupts are not used and GIE was disabled by interupt

                                               ; handling routine before control was passed to here.

 

;***********************************

;Handshake section

 

            MOVLW        BYTES                       ; load counter with number of bytes to read or write

            MOVWF        BYT_CNT

            MOVLW        D'50'               ; Load loop counter via W: RB1 must cycle low-high 50 times

            MOVWF        AA

B1_LOOP       CLRF  BB                   ; Reset 'time-out' counter

PORTOK        BTFSC            PORTB,1                    ; Now check for low-high-low sequence on RB1 to be sure

                                               ; PC port handshake is OK: first check for high on RB1

            GOTO RB1_OK1                  ; RB1 is high: check for next low on RB1

            DECFSZ         BB,1

            GOTO PORTOK                   ; Otherwise, keep checking RB1

            GOTO IOQUIT                      ; If 'timed out', abort I/O mode

RB1_OK1       CLRF  BB                   ; RB1 went high: now reset time-out timer

            BCF    PORTB,2                    ; then signal PC by reseting RB2 output from controller

            NOP                           ; (separate port write from port read with NOP)

RB1_OK2       BTFSS            PORTB,1                    ; Now check for low on RB1

            GOTO NXT_B1                     ; RB1 low: check for next high on RB1 (or if loop done, exit)

            DECFSZ         BB,1

            GOTO RB1_OK2                  ; Otherwise, keep checking RB1

            GOTO IOQUIT                      ; If timed out, abort I/O mode

NXT_B1         BSF     PORTB,2                    ; Set RB2 output high to complete current cycle

            DECFSZ         AA,1               ; Check if main handshake loop completed

            GOTO B1_LOOP                  ; Keep looping if not; otherwise skip to complete the handshake

 

            MOVLW        0x4F                ; Acknowledge PC connection: output "OK"

            MOVWF        EEDATA                    ; First load and output "O"

            CALL  BYT_OUT

            MOVLW        0x4B               ; Then load "K"

            MOVWF        EEDATA

            CALL  BYT_OUT                  ; and output it

            BCF    PORTB,2                    ; make sure RB2 is low in case write routine is entered

 

            BTFSC            PORTB,6                    ; Now check for read or write: RB6 low = write; high = read

 

            GOTO PIC_RD                      ; If high, go to the PIC read routine (ie output to PC)

                                               ; Otherwise, start full write to all EERAM (next instruction)

 

;*****************************************

; Routine to write fresh data from PC to controller

 

PIC_WR         CALL  BYT_IN                      ; Fetch start address for writing from PC

            SUBLW          0x0F                ; Check for error condition from BYT_IN before continuing

            BTFSC            STATUS,Z                  ; Zero flag will be clear if no error

            GOTO IOQUIT                      ; Exit if error

            MOVF            EEDATA,0                 ; Place the start address in EEADR (via W)

            MOVWF        EEADR

            SUBWF          BYT_CNT,1   ; Now set counter for correct number of bytes to write

WR_NXT       BCF    PORTA,0                    ; Clear the output that signals that last byte written OK

            CALL  BYT_IN                      ; Fetch byte to write from PC

            SUBLW          0x0F                ; Check for error condition from BYT_IN before writing byte

            BTFSC            STATUS,Z                  ; Zero flag will be clear if no error

            GOTO IOQUIT                      ; Exit if error

            CALL  EE_WR                       ; Otherwise continue: write to current EERAM location

            BSF     PORTA,0                    ; Send RA0 high to signal byte successfully written

 

; Wait for ack from computer before fetching and writing the next byte

            CLRF  CC                  ; Set time-out counters

            CLRF  BB

WR_ACK       BTFSC            PORTB,1                    ; Wait until RB1 input is high: this is ack from PC

            GOTO ACK_OK                   ; If high, write the next byte

            DECFSZ         BB,1                ; If still low, check if time-out occur

            GOTO WR_ACK                   ; If not timed-out, re-check for high on RB1

            DECFSZ         CC,1               ; Otherwise, decement outer loop counter

            GOTO WR_ACK                   ; Continue reading if counter not zero

            GOTO IOQUIT                      ; Otherwise abort

 

; prepare to receive and write next byte

ACK_OK       INCF   EEADR,1                    ; Point to next EERAM address

            DECFSZ         BYT_CNT,1   ; Then check if bytes written = BYTES, if so: finish

            GOTO WR_NXT                   ; If not done, then get next byte to write

 

            BCF    PORTA,0                    ; Set RA0 output low before finishing (not essential)

 

IOQUIT          BSF     PORTB,2                    ;

            GOTO BOOTUP                    ; All done

 

 

; Function to input a byte to PIC on RB1, starting with least significant bit

 

BYT_IN          MOVLW        BITS               ; First, reload bit counter

            MOVWF        BIT_CNT

NXT_IN         BSF     PORTB,2                    ; Set RB2 high to signal PIC is ready for data

            CLRF  BB                   ; Set time-out counter

B3_LO            BTFSC            PORTB,3                    ; Main loop to monitor clock input (RB3) and keep count

                                               ; of the number of bits received.

            GOTO B3_HI             ; If B3 is high, fetch bit on RB1 and process

            NOP                           ; Lengthen time allowed for RB3 to change

            DECFSZ         BB,1                ; Check if 'time-out' occurred: if so, quit

            GOTO B3_LO                        ; Otherwise, keep checking RB3

            RETLW           0x0F                ; If 'timed out', set error status and return

                                               ; (write value hex 0F to W to signal error condition)

B3_HI MOVLW        D'5'                 ; Make sure RB3 stays high: debounce the input

            MOVWF        CC                  ; Set debounce counter

DEBNC1        BTFSS            PORTB,3                    ; Check RB3 is still high

            GOTO B3_LO                        ; If not, go back and continue checking til high

            DECFSZ         CC,1               ; Otherwise, keep cycling through debounce

            GOTO DEBNC1

            BCF    PORTB,2                    ; RB3 input debounced: now set RB2 low to signal not ready for data

            BCF    STATUS,C                 ; Clear carry bit in preparation for reading of RB1

            BTFSC            PORTB,1                    ; Read received bit (on RB1)

            BSF     STATUS,C                 ; Set carry bit if RB1 is high; otherwise, bit stays clear

            RRF     EEDATA,1                 ; Either way, shift the read bit right through EEDATA

            CLRF  BB                   ; Set time-out counter

H_L1   BTFSS            PORTB,3                    ; Wait until RB3 input is low

            GOTO DEC_BIT                    ; If low, decrement bit counter and continue

            DECFSZ         BB,1                ; If still high, check if time-out occur

            GOTO H_L1               ; If not timed-out, re-check for low on RB3

            RETLW           0x0F                ; Otherwise flag error and abort

DEC_BIT        MOVLW        D'5'                 ; First, debounce the input

            MOVWF        CC                  ; Set debounce counter

DEBNC2        BTFSC            PORTB,3                    ; Check RB3 is still low

            GOTO H_L1               ; If not, go back and continue checking til low

            DECFSZ         CC,1               ; Otherwise, keep cycling through debounce

            GOTO DEBNC2

            DECFSZ         BIT_CNT,1     ; RB3 input debounced: Check if 8 bits received

            GOTO NXT_IN                     ; If not, fetch next bit

            RETLW           0                      ; Otherwise return with W cleared

 

;***********************************************************************************************       

; Routine to read contents of PIC to PC

PIC_RD          CLRF  EEADR                       ; Set start address for read

            CLRF  CC                  ; Clear general register used for checksum

RD_NXT        CALL  EE_RD                        ; Read current EERAM address: result placed in EEDATA

            MOVF            EEDATA,0                 ; Calculate checksum in CC via W

            ADDWF         CC,1

            CALL  BYT_OUT                  ; Output the byte

            SUBLW          0x5A               ; Check for error condition from BYT_OUT before outputing next byte

            BTFSC            STATUS,Z                  ; Zero flag will be clear if no error

            GOTO IOQUIT                      ; If error: exit now

            INCF   EEADR,1                    ; Point to next EERAM address

            DECFSZ         BYT_CNT,1   ; Then check if bytes read = BYTES, if so: finish

            GOTO RD_NXT                    ; If not done, then get next byte

            MOVF            CC,0               ; If done, output checksum

            MOVWF        EEDATA

            CALL  BYT_OUT                  ; (PC to check for output of 0xF0 to confirm success)

            GOTO IOQUIT                      ; All done: exit

 

; Function to output a byte on RB2, starting with most significant bit

; Note, PC should wait a few microseconds after sending RB3 high before reading bit to ensure

; new bit has been placed on RB2. Data to be output must be put in EEDATA by calling routine

 

BYT_OUT      MOVLW        BITS               ; First, reload bit counter

            MOVWF        BIT_CNT

RLF_BIT         RLF     EEDATA,1                 ; Prepare first/next bit for output: via Carry bit

            BCF    PORTB,2                    ; Set RB2 low as default output

            BTFSC            STATUS,C                 ; Output 1 or 0 mirroring value in 'Carry'

            BSF     PORTB,2                    ; Set bit output of RB2 if Carry bit was high

            CLRF  BB                   ; Set 'time out' counter 

CHK_RB3      BTFSC            PORTB,3                    ; Wait until RB3 input is high: means PC now reading last bit

            GOTO NXT_OUT                 ; RB3 high: complete cycle & prepare next bit for output

            DECFSZ         BB,1

            GOTO CHK_RB3                  ; Otherwise, keep checking RB3

            RETLW           0x5A               ; If 'timed out', set error status and return

NXT_OUT      CLRF  BB                   ; Set 'time out' counter

H_L2   BTFSS            PORTB,3                    ; Now check for next falling edge on RB3 (signals previous

                                               ; bit of data has been read.)

            GOTO CHK_BIT                   ; If low, get ready to output next bit (or exit)

            DECFSZ         BB,1

            GOTO H_L2               ; Otherwise, keep checking RB3

            RETLW           0x5A               ; If 'timed out', set error status and return

CHK_BIT       DECFSZ         BIT_CNT,1     ; Now check if 8 bits have been output

            GOTO RLF_BIT                    ; Output next bit

            RETLW           0                      ; Otherwise return with 0 in W

 

 

 

           

;***********************************************************************************************       

; Functions to read and write EERAM

 

; Read function: requires user to place EERAM address in EEADR prior to call. Results of read

; are put in EEDATA

EE_RD            BSF     STATUS,RP0 ; Go to RAM page 1

            BSF     EECON1,RD  ; Instruction to read current EERAM address

            BCF    STATUS,RP0 ; Go to RAM page 0; data is now in EEDATA register in page 0

            RETURN                                ; [return is a two cycle instruction]

 

; Write function: requires user to place EERAM address to write in EEADR prior to call. User also

; responsible for disabling interupts prior to calling this function. Data to be written is to

; be placed in EEDATA before calling this function.

 

EE_WR           BSF     STATUS,RP0 ; first go to RAM page 1

            BSF     EECON1,WREN        ; Enable EERAM write

            MOVLW        0x55                ; Write cycle for EERAM

            MOVWF        EECON2

            MOVLW        0xAA

            MOVWF        EECON2

            BSF     EECON1,WR

WR_ON         BTFSS            EECON1,EEIF           ; Poll until write is completed

            GOTO WR_ON                     ; Keep looping until EEIF goes high

            BCF    EECON1,WREN        ; Once write has started, can disable EERAM write

            BCF    EECON1,EEIF           ; When done, clear EE write interupt flag

            BCF    STATUS,RP0 ; Return to RAM page 0

            RETURN                                ; Done!

 

 

;***********************************************************************************************

            END                           ; end of code

 

 

 

 

 

Перейти: /Главная/ CBuild/ JavaScript 1.2-5.6/ Delifi6/ I2C контроллеры/ AVR контроллеры/ ПЛИС/ AHDL/ VHDL/
LPT EPP/ LPT ECP/ PCI/ COM port/ I2C/ RS-232/
Рейтинг@Mail.ru Rambler's Top100 Rambler's Top100 Rambler's Top100    
Используются технологии uCoz