At 09:28 PM 2002/01/26 +0000, you wrote:
Yes please. I haven't got round to using any of my '628s yet, but had heard a
few vibes that things were not as they seem
Andy 'JNT
>I will send any and all who ask a copy of this ASM file, which I happen to
>call PIC8_4B.ASM, configured to run on a 4 MHz crystal or 4 MHz internal
>oscillator by just compiling it with MPASM.
It is a great pleasure to be able to send you something Andy....
Larry
VA3LK
;******************************************************************************
;[email protected]
LIST p=16F628 ;PICF628 is the target processor
;
#include "P16F628.INC" ;Include header file
;
ErrorLevel 0 ;0 for Messages, Warnings, Errors
ErrorLevel -302 ;1 for Warnings, Errors
;2 for Errors
;-302 to suppress Page Message
;
;enable _hs_osc, _pwrte_on, when programming the device
;******************************************************************************
cblock h'20' ;bank 0 h'20' to h'7f'. 96 locations
savew1 ;SAVEW1 *MUST* be at location h'20'!
savestatus
savepclath
savefsr
rx_data ;the received byte from the serial UART
tx_data ;byte to be transmitted via UART
endc
;******************************************************************************
cblock h'A0' ;bank 1
savew2 ;SAVEW2 *MUST* be at location h'A0'.
endc
;
org h'0000' ;set code origin to beginning of rom start
goto initialize ;we must get past interrupt vector at 0004
;
;INTERRUPT ROUTINE
org h'0004' ;interrupt vector location
inthandler
movwf savew1 ;save w register! (at h'20', h'A0', etc.)
movf status,w ;w now has copy of status
clrf status ;ensure we are in bank 0 now!
movwf savestatus ;save status
movf pclath,w ;save pclath
movwf savepclath
clrf pclath ;explicitly select Page 0
;
movf fsr,w
movwf savefsr ;save fsr (just in case)
;
vector_to_interrupt
;
btfsc intcon,t0if ;test to see which interrupt
goto service_t0if ;needs servicing...
;
btfsc intcon,intf ;there can be many different sources
goto service_intf ;of interrupt...
;add as many checks here as you
;have possible interrupt sources....
;
service_t0if
nop ;!!! or do something useful here...
;
t0if_done
bcf intcon,t0if ;clear interrupt flag that
caused interrupt.
goto intclean ;restore and return from
interrupt!
;
service_intf
nop ;!!! or do something useful here...
;
intf_done bcf intcon,intf ;clear flag that caused interrupt.
goto intclean ;restore and return from interrupt!
;
intclean
movf savefsr,w
movwf fsr ;restore fsr
;
movf savepclath,w
movwf pclath ;restore pclath. (Page=original)
;
movf savestatus,w
movwf status ;restore status! (bank=original)
;
swapf savew1,f ;restore w from *original* bank!
swapf savew1,w ;swapf does not affect any flags!
;
retfie ;return from interrupt!
;gie is auto-re-enabled.
;
initialize ;initialize ports and registers
bcf status,rp0 ;first do page 0 stuff. yep, page 0
gie01 bcf intcon,gie ;turn gie off
btfsc intcon,gie ;MicroChip recommends this check!
goto gie01 ;without this check
;you are not sure gie is cleared!
clrf pir1 ;clear peripheral flags
;
clrf porta ;clear all i/o registers...
clrf portb
;
bsf status,rp0 ;allow access to page 1 stuff!
;
clrf pie1 ;disable peripheral interrupts
;
movlw b'00000110'
movwf trisb ;0=output 1=input
; BUT for UART use RB1 and RB2 MUST be
programmed as an INPUT!
;
bsf option_reg, not_rbpu ;!rbpu! rb_pullup 0=enabled
; 1=disabled. enabling is based on individual
;port-latch values. currently pullups are
;disabled.
bsf option_reg, intedg ;intedg 0=inc on falling 1=inc on
; rising edge. <<note: intedg and t0se use
; opposite definitions!>>
;currently set for rising edge detection.
bcf option_reg, t0cs ;t0cs timer0clocksource 0=internal
clkout
;1=ra4/int. currently set for internal clkout
bcf option_reg, t0se ;t0se timer0signaledge 0=inc on rising
1=inc
; on falling edge.
; <<note: intedg and t0se use opposite
; definition!>>
bcf option_reg, psa ;psa prescaler assignment 0=tmr0 1=wdt
;ps2-ps0 determine prescaler rate, which is
;dependent also on whether tmr0 or wdt is
;selected:
;wdt from 0-7 is div by 1 2 4 8 16 32 64 128
;tmr0 from 0-7 is div by 2 4 8 16 32 64 128 256
;if wdt is assigned prescaler, then tmr0 is div by 1
; here we will set prescaler to divide by 16 for tmr0
; !!! set this any way you want.
; This is just an example that works.
bcf option_reg,ps2 ;ps2
bsf option_reg,ps1 ;ps1
bsf option_reg,ps0 ;ps0
;intcon register: bit assignments
;
;enables... 1=enable 0=disable
;<7>=gie=global_int_enable
;<6>=peie=peripheral_int_enable
;<5>=t0ie=t0_int_enable (enables <2> t0if)
;<4>=inte=int_enable (rb0/int) (enables <1> intf)
;<3>=rbie=rb_int_enable (enables <0> rbif)
;
;intcon flags. software reset. 0=reset 1=flagged
;<2>=t0if=t0_int_flag
;<1>=intf=int_flag (rb0/int)
;<0>=rbif=rb_int_flag (rb7-rb4)
clrf intcon ;in this example we have no interrupts used.
;
;pie1 peripheral interrupt enable 1 register:
; bit assignments. 1=enable 0=disable
;
;<7>=pspie=parallel_slave_port_int_enable
;<6>=adie=a/d_int_enable
;<5>=rcie=receiver_int_enable for uart (may use later)
;<4>=txie=transmit_int_enable for uart (may use later)
;<3>=sspie=sync_serial_int_enable
;<2>=ccp1ie=ccp1_int_enable
;<1>=tmr2ie=timer2_int_enable
;<0>=tmr1ie=timer1_int_enable
;
clrf pie1 ;no interrupts used in this example
;
;uart specific initialization
;txsta=Transmit STAtus and control register.
;take nothing for granted.
bcf txsta,csrc ; <7> (0) don't care in asynch mode
bcf txsta,tx9 ; <6> 0 select 8 bit mode
bsf txsta,txen ; <5> 1 enable transmit function
; *MUST* be 1 for transmit to work!!!
bcf txsta,sync ; <4> 0 asynchronous mode.
; *MUST* be 0 !!!
; If NOT 0 the async mode is NOT selected!
; <3> (0) not implemented
bsf txsta,brgh ; <2> 0 disable high baud rate generator !!!
; lsk for 16F628
; 1 (0) trmt is read only.
bcf txsta,tx9d ; <0> (0) tx9d data cleared to 0.
;
; For brgh=0 baudrate=Fosc/(64(spbrg+1))
; So when brgh=0 spbrg_value = (xtal_freq/(baudrate*d'64'))-1
; For brgh=1 baudrate=Fosc/(16(spbrg+1))
; So when brgh=1 spbrg_value = (xtal_freq/(baudrate*d'16'))-1
;
xtal_freq = d'4000000' ;crystal frequency in Hertz.
baudrate = d'19200' ;desired baudrate.
; ;now calculate spbrg_value...
;spbrg_value = (xtal_freq/(baudrate*d'64'))-1
spbrg_value = (xtal_freq/(baudrate*d'16'))-1
;
movlw spbrg_value ;set baud rate generator value
movwf spbrg
;
bcf status,rp0 ;allow access to page 0 stuff again. (normal)
;
;more uart specific initialization
;
;rcsta=ReCeive STAtus and control register
;
bsf rcsta,spen ; 7 spen 1=rx/tx set for serial uart mode
; !!! very important to set spen=1
bcf rcsta,rx9 ; 6 rc8/9 0=8 bit mode
bcf rcsta,sren ; 5 sren 0=don't care in uart mode
bsf rcsta,cren ; 4 cren 1=enable constant reception
;!!! (and low clears errors)
; 3 not used / 0 / don't care
bcf rcsta,ferr ; 2 ferr input framing error bit. 1=error
; 1 oerr input overrun error bit. 1=error
;!!! (reset oerr by neg pulse clearing cren)
;you can't clear this bit by using bcf.
;It is only cleared when you pulse cren low.
bcf rcsta,rx9d ; 0 rx9d input (9th data bit). ignore.
;
;If you are using a MAX232 that uses
;charge pumping, put a delay routine
;right HERE, a few seconds
;
;we need to initialize some things, so do it here.
;
movf rcreg,w ;clear uart receiver
movf rcreg,w ; including fifo
movf rcreg,w ; which is three deep.
;
movlw 0 ;any character will do.
movwf txreg ;send out dummy character
; to get transmit flag valid!
;
main
bsf intcon,gie ;enable interrupts if you are using any!
;
loop
call ser_in ;get UART input into W and rx_data
call transmitw ;send W to the UART transmitter
goto loop ;blithely echo characters forever...
;*****************************************************************
;SER_IN
ser_in
btfsc rcsta,oerr
goto overerror ;if overflow error...
btfsc rcsta,ferr
goto frameerror ;if framing error...
uart_ready
btfss pir1,rcif
goto ser_in ;if not ready, wait...
;
uart_gotit
bcf intcon,gie ;turn gie off.
btfsc intcon,gie
goto uart_gotit
;
movf rcreg,w ;recover uart data
bsf intcon,gie ;re-enable interrupts!!
movwf rx_data ;save for later
return
;
overerror
bcf intcon,gie ;turn gie off.
btfsc intcon,gie ;
goto overerror ;
;
bcf rcsta,cren ;pulse cren off...
movf rcreg,w ;flush fifo
movf rcreg,w ; all three elements.
movf rcreg,w
bsf rcsta,cren ;turn cren back on.
;this pulsing of cren
;will clear the oerr flag.
bsf intcon,gie ;enable interrupts.
goto ser_in ;try again...
;
frameerror
bcf intcon,gie ;turn gie off.
btfsc intcon,gie ;
goto frameerror
;
movf rcreg,w ;reading rcreg clears ferr flag.
bsf intcon,gie ;enable interrupts.
goto ser_in ;try again...
;
;TRANSMIT subroutine:
transmit
movf tx_data,w ;copy tx_data to w.
transmitw
btfss pir1,txif
goto transmitw ;wait for transmitter interrupt flag
gietx bcf intcon,gie ;disable interrupts
btfsc intcon,gie ;making SURE they are disabled!
goto gietx
movwf txreg ;load data to be sent...
bsf intcon,gie ;re-enable interrupts
return
;
TransWt ; use to ensure that TX buffer is empty
bsf STATUS,RP0
TxWt btfss TXSTA,TRMT ; transmission is complete if hi
goto TxWt
clrf STATUS ; RAM Page 0
return
;
;----------------------------------------------------------------------
end
|