; ; _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 VAR_COIL 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 coil0_bit=6 constant coil1_bit=7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 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 banksel PORTB ; bank 0 BSF PORTB, coil0_bit ; B6 on, coil 0 off BSF PORTB, coil1_bit ; B7 on, coil 1 off banksel TRISB ; bank 1 BCF TRISB, coil0_bit ; B6 operates as output BCF TRISB, coil1_bit ; B7 operates as output banksel VAR_COIL ; bank 0 START MOVLW H'02' ; wait .4 sec errorlevel -306 pagesel PAUSE CALL PAUSE pagesel START errorlevel +306 errorlevel -306 pagesel CHANGE_LED CALL CHANGE_LED ; change led pagesel START errorlevel +306 errorlevel -306 GET_COIL pagesel READ_SERIAL CALL READ_SERIAL ; W is the character read pagesel START errorlevel +306 errorlevel -306 pagesel WRITE_SERIAL CALL WRITE_SERIAL pagesel START errorlevel +306 banksel VAR_COIL ; bank 0 MOVWF VAR_COIL ; save the character read SUBLW H'49' ; compare to ascii 'I' BTFSC STATUS, Z CALL SET_COIL0 ; call "set_coil0" command procedure MOVF VAR_COIL, W SUBLW H'4F' ; compare to ascii 'O' BTFSC STATUS, Z CALL SET_COIL1 ; call "set_coil1" command procedure GOTO START SET_COIL0 BSF PORTB, coil0_bit ; coil 0 off BCF PORTB, coil1_bit ; coil 1 on RETURN SET_COIL1 BCF PORTB, coil0_bit ; coil 0 on BSF PORTB, coil1_bit ; coil 1 off 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