;
; _A.Fenyo 2003 - 2004
;
include p16f876.inc
list P=PIC16F876
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; local variables used by functions
cblock H'20'
VARPAUSEBCL0, VARPAUSEBCL1, VARPAUSEBCL2
VAR_READ_SERIAL, VAR_WRITE_INTRO
VAR_TURN_LED_W, VAR_TURN_LED_VAL
VAR_CMD
endc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; module address
org 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; avoid assembler warning message "Register in operand not in bank 0"
errorlevel -302
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; define constants
constant led_bit=4
constant cts_bit=5
constant L293D_control_A=7
constant L293D_control_B=6
constant L293D_enable=5
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; initial values for variables used by functions
banksel VAR_TURN_LED_VAL
CLRF VAR_TURN_LED_VAL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; initialize PCLATH for GOTO and CALL instructions
errorlevel -306
INITPCLATH pagesel FIRSTLIB
CALL FIRSTLIB
pagesel INITPCLATH
errorlevel +306
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; start of program
; C0-2 as output
banksel TRISB
BCF TRISB, L293D_control_A
BCF TRISB, L293D_control_B
BCF TRISB, L293D_enable
; clear C0-2
banksel PORTB
BCF PORTB, L293D_control_A
BCF PORTB, L293D_control_B
BCF PORTB, L293D_enable ; disable stepper
myCmdLOOP
; read serial to W
errorlevel -306
pagesel READ_SERIAL
CALL READ_SERIAL
CALL WRITE_SERIAL
CALL CHANGE_LED
pagesel INITPCLATH
errorlevel +306
banksel VAR_CMD
MOVWF VAR_CMD ; save the character read
SUBLW H'41' ; compare to ascii 'A'
BTFSC STATUS, Z
CALL CMD_A ; call "A" command procedure
banksel VAR_CMD
MOVF VAR_CMD, W
SUBLW H'42' ; compare to ascii 'B'
BTFSC STATUS, Z
CALL CMD_B ; call "B" command procedure
banksel VAR_CMD
MOVF VAR_CMD, W
SUBLW H'43' ; compare to ascii 'C'
BTFSC STATUS, Z
CALL CMD_C ; call "C" command procedure
banksel VAR_CMD
MOVF VAR_CMD, W
SUBLW H'44' ; compare to ascii 'D'
BTFSC STATUS, Z
CALL CMD_D ; call "D" command procedure
banksel VAR_CMD
MOVF VAR_CMD, W
SUBLW H'45' ; compare to ascii 'E'
BTFSC STATUS, Z
CALL CMD_E ; call "E" command procedure
GOTO myCmdLOOP
CMD_A banksel PORTB
BCF PORTB, L293D_control_A
BCF PORTB, L293D_control_B
BSF PORTB, L293D_enable ; enable stepper
RETURN
CMD_B banksel PORTB
BCF PORTB, L293D_control_A
BSF PORTB, L293D_control_B
BSF PORTB, L293D_enable ; enable stepper
RETURN
CMD_C banksel PORTB
BSF PORTB, L293D_control_A
BCF PORTB, L293D_control_B
BSF PORTB, L293D_enable ; enable stepper
RETURN
CMD_D banksel PORTB
BSF PORTB, L293D_control_A
BSF PORTB, L293D_control_B
BSF PORTB, L293D_enable ; enable stepper
RETURN
CMD_E banksel PORTB
BSF PORTB, L293D_control_A
BSF PORTB, L293D_control_B
BCF PORTB, L293D_enable ; disable stepper
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; end of program
THEEND GOTO 0 ; reset
; Starting from here: Alexandre Fenyo's BIOS for Microchip PICs
: This BIOS is able to drive the RS-232-C interface in order to erase and flash
; the EEPROM memory. No need to use an EEPROM programer to debug your code !
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; start of 1st LIBRARY in program page 3
FIRSTLIB org H'1800'
;FIRSTLIB org H'1000'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; initialize I/O ports
banksel TRISC ; bank 1
BCF TRISC, led_bit ; C4 (red led) operates as output
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; initialize UART
MOVLW H'02' ; wait .4 sec
CALL PAUSE
BSF TRISC, 6 ; C6-7 must be set to use UART
BSF TRISC, 7
BCF TRISC, cts_bit ; C5 (CTS) signal operates as output
; high speed UART
; set communications speed (with 3.6864 MHz ext. oscillator)
BCF TXSTA, BRGH
; MOVLW H'BF' ; 300 b/s
MOVLW H'00' ; 57600 b/s
MOVWF SPBRG
banksel RCSTA ; bank 0
BSF RCSTA, SPEN ; use UART
banksel TXSTA ; bank 1
BCF TXSTA, SYNC ; async UART
BSF TXSTA, TXEN ; enable transmit
banksel RCSTA ; bank 0
BSF RCSTA, CREN ; enable receive
BCF PORTC, cts_bit ; clear C5 (set CTS)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; initial sequence (test peripherals)
; ToDo: call change_led instead of this
INIT BSF PORTC, led_bit ; red led on
MOVLW H'02' ; wait .4 sec
CALL PAUSE
; ToDo: call change_led instead of this
BCF PORTC, led_bit ; red led off
MOVLW H'02' ; wait .4 sec
CALL PAUSE
BSF PORTC, led_bit ; red led on
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; write introduction text to rs232c
CALL WRITE_INTRO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; "read" command
CMD_READ MOVLW H'3C' ; write ascii '<' to ask for address
CALL WRITE_SERIAL
CALL READ_SERIAL ; read memory address low byte
banksel EEADR
MOVWF EEADR ; save byte
CALL READ_SERIAL ; read memory address high byte
banksel EEADRH
MOVWF EEADRH ; save byte
banksel EECON1
BSF EECON1, EEPGD ; want to read flash
BSF EECON1, RD ; read flash
NOP ; requires two cycles wait
NOP
banksel EEDATA
MOVF EEDATA, W ; read char from flash
CALL WRITE_SERIAL ; write 8 lowest bits of flash to serial
banksel EEDATH
MOVF EEDATH, W ; read char from flash
CALL WRITE_SERIAL ; write 6 highest bits of flash to serial
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; "write" command
CMD_WRITE MOVLW H'3E' ; write ascii '>' to ask for address
CALL WRITE_SERIAL
; this bit clear seems to stop the pic
; banksel EECON1 ; bank 3
; BCF EECON1, WRERR ; clear write error bit
CALL READ_SERIAL ; read memory address low byte
banksel EEADR
MOVWF EEADR ; save byte
CALL READ_SERIAL ; read memory address high byte
banksel EEADRH
MOVWF EEADRH ; save byte
MOVLW H'26' ; write ascii '&' to ask for data
CALL WRITE_SERIAL
CALL READ_SERIAL ; read low byte of data
banksel EEDATA
MOVWF EEDATA ; save byte
CALL READ_SERIAL ; read high byte of data
banksel EEDATH
MOVWF EEDATH ; save byte
banksel EECON1 ; bank 3
BSF EECON1, EEPGD ; want to write flash
BSF EECON1, WREN ; enable write on flash memory
MOVLW 0x55 ; magic op code
MOVWF EECON2 ; magic op code
MOVLW 0xAA ; magic op code
MOVWF EECON2 ; magic op code
BSF EECON1, WR ; start write operation
NOP ; requires two cycles wait
NOP
CMD_WRITE_WAIT BTFSC EECON1, WR ; wait until write cycle completion
GOTO CMD_WRITE_WAIT
BCF EECON1, WREN ; disable write on flash memory
MOVLW H'21' ; write ascii '!' to inform about end of flash operation
CALL WRITE_SERIAL
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; turn led on/off
CHANGE_LED banksel RCSTA ; default bank 0
MOVWF VAR_TURN_LED_W ; save W
MOVLW H'01' ; invert bit 0 in VAR_TURN_LED_VAL
XORWF VAR_TURN_LED_VAL, F
BCF PORTC, led_bit ; red led off
BTFSS STATUS, Z ; check parity of VAR_TURN_LED_VAL
BSF PORTC, led_bit ; red led on
MOVF VAR_TURN_LED_W, W ; restore W
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; write a char to rs232c
; input : W
; output : W not altered
WRITE_SERIAL CALL CHANGE_LED
banksel RCSTA ; default bank 0
BTFSS PIR1, TXIF
GOTO WRITE_SERIAL
MOVWF TXREG
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; read a char from rs232c
; output : W
READ_SERIAL banksel RCSTA ; default bank 0
READ_SERIAL_2 BTFSS PIR1, RCIF ; test buffer
GOTO READ_SERIAL_2 ; nothing to read
; a byte can be read
MOVF RCSTA, W ; check error bits
MOVWF VAR_READ_SERIAL
BTFSC VAR_READ_SERIAL, OERR ; test overrun
GOTO RS_RESET ; reset USART receiver
BTFSS VAR_READ_SERIAL, FERR ; test framing error
GOTO RS_END ; go to read byte
RS_RESET MOVF RCREG, W ; must read register
BCF RCSTA, CREN ; reset USART receiver
BSF RCSTA, CREN
GOTO READ_SERIAL
RS_END MOVF RCREG, W ; read byte
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; short PAUSE function
; number of cycles :
; 3 + ((((255 * 3 + 2) + 3) * 255 + (255 * 3 + 2) + 2) + 3) * W
; + (((255 * 3 + 2) + 3) * 255 + (255 * 3 + 2) + 2) + 2 + 2
; = 197122 * W + 197123
; nearly equal to 197123 * W = 0.214 * W sec (with 3.6864MHz ext. oscillator)
PAUSE banksel VARPAUSEBCL0
MOVWF VARPAUSEBCL0
CLRF VARPAUSEBCL1
CLRF VARPAUSEBCL2
PAUSE_1 DECFSZ VARPAUSEBCL2, F
GOTO PAUSE_1
DECFSZ VARPAUSEBCL1, F
GOTO PAUSE_1
DECFSZ VARPAUSEBCL0, F
GOTO PAUSE_1
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; write introduction text to rs232c
; since index counter is a 8 bit register, string length must be 256 characters max
WRITE_INTRO banksel VAR_WRITE_INTRO
CLRF VAR_WRITE_INTRO ; clear index counter
CLRW
WRITE_INTR_LOOP CALL GET_INTRO ; get one char
BTFSC STATUS, Z ; last char is null ?
RETURN ; return
CALL WRITE_SERIAL ; write char
INCF VAR_WRITE_INTRO, F ; increment index counter
MOVF VAR_WRITE_INTRO, W
GOTO WRITE_INTR_LOOP ; loop : get next char
GET_INTRO banksel EEADR
ADDLW LOW(STR_INTRO) ; compute address of text string
MOVWF EEADR ; select address
MOVLW HIGH(STR_INTRO)
BTFSC STATUS, C
ADDLW 1
MOVWF EEADRH
banksel EECON1
BSF EECON1, EEPGD ; want to read flash
BSF EECON1, RD ; read flash
NOP ; requires two cycles wait
NOP
banksel EEDATA
MOVF EEDATA, W ; read char
banksel RCSTA ; default bank 0
RETURN ; return char
STR_INTRO
DA h'000D'
DA h'000A'
DA " M i c r o c h i p P I C 1 6 F 8 7 x B I O S"
DA h'000D'
DA h'000A'
DA " c o n t a c t : a l e x @ f e n y o . n e t"
DA h'000D'
DA h'000A'
DA " 3 . 6 8 6 4 M H z e x t e r n a l o s c i l l a t o r"
DA h'000D'
DA h'000A'
DA " 1 a s y n c s e r i a l p o r t"
DA h'000D'
DA h'000A'
DA " 1 h i g h p o w e r l a t c h i n g r e l a y [ 6 0 A 2 5 0 V A C ]"
DA h'000D'
DA h'000A'
DA h'0000'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org H'2007'
DATA _HS_OSC & _WDT_OFF & _PWRTE_ON & _BODEN_OFF & _LVP_OFF & _CPD_OFF & _WRT_ENABLE_ON & _DEBUG_OFF & _CP_OFF
END