Return-Path: Received: (qmail 28269 invoked from network); 27 Jan 2002 00:28:33 -0000 Received: from unknown (HELO warrior.services.quay.plus.net) (212.159.14.227) by excalibur-qfe1-smtp-plusnet.harl.plus.net with SMTP; 27 Jan 2002 00:28:33 -0000 X-Priority: 3 X-MSMail-Priority: Normal Received: (qmail 15601 invoked from network); 27 Jan 2002 00:28:31 -0000 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106 Received: from unknown (HELO post.thorcom.com) (212.172.148.70) by warrior.services.quay.plus.net with SMTP; 27 Jan 2002 00:28:31 -0000 Received: from majordom by post.thorcom.com with local (Exim 3.33 #2) id 16Ud7v-0003tw-00 for rsgb_lf_group-outgoing@blacksheep.org; Sun, 27 Jan 2002 00:24:55 +0000 Received: from tomts12.bellnexxia.net ([209.226.175.56] helo=tomts12-srv.bellnexxia.net) by post.thorcom.com with esmtp (Exim 3.33 #2) id 16Ud7t-0003tr-00 for rsgb_lf_group@blacksheep.org; Sun, 27 Jan 2002 00:24:53 +0000 Received: from server1.sympatico.ca ([216.208.193.81]) by tomts12-srv.bellnexxia.net (InterMail vM.4.01.03.16 201-229-121-116-20010115) with ESMTP id <20020127002400.FBPP8200.tomts12-srv.bellnexxia.net@server1.sympatico.ca> for ; Sat, 26 Jan 2002 19:24:00 -0500 Message-ID: <5.1.0.14.0.20020126192150.00a611c0@POP2.sympatico.ca> X-Sender: b1aemm59@POP2.sympatico.ca X-Mailer: QUALCOMM Windows Eudora Version 5.1 Date: Sat, 26 Jan 2002 19:24:00 -0500 To: rsgb_lf_group@blacksheep.org From: "Larry Kayser" Subject: Re: LF: Re: USART in the 16F628 In-reply-to: <000e01c1a6b0$5661f600$3c9e01d4@g4jnt> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------010303070700020605010208" Precedence: bulk Reply-To: rsgb_lf_group@blacksheep.org X-Listname: rsgb_lf_group Sender: This is a multi-part message in MIME format. --------------010303070700020605010208 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 8bit 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 --------------010303070700020605010208 Content-Type: text/plain; charset=windows-1252; name="Pic8_4b.asm" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="Pic8_4b.asm" ;****************************************************************************** ;kayser@sympatico.ca 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. <> ;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. ; <> 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 --------------010303070700020605010208--