This is a multi-part message in MIME format. ------=_NextPart_000_001C_01C5DAF1.0E6DFD70 Content-Type: text/plain; format=flowed; charset="iso-8859-1"; reply-type=response Content-Transfer-Encoding: 7bit Stephen D. Barnes wrote: > This is what I need! Thanks Olin. This is something I have been trying > to accomplish > but have not been successful with. Looks like the answer in front of my > eyes but I > did not see it. If you just wanted to break up a 16 bit word into two bytes, there are easier ways than what I showed. I thought you were explicitly asking about the MOV instruction used on bytes. If you want the two bytes of 16 bit variable in the low bytes of two separate registers you can do: mov myvar, w0 lsr w0, #8, w1 If you want to send the two bytes of a 16 bit variable someplace successively, you can do: mov myvar, w0 call uart_put lsr w0, #8, w0 call uart_put In this example the subroutine UART_PUT is assumed to preserve W0. > One more quick question. Will the UART on the 30F2010 take a 16-bit word > or do I have to send it data 1 byte at a time, which is what the Family > Reference and the Datasheet seem to indicate? It works like the manual says it works, mostly. I have attached the UART handler of a recent dsPIC project. It has relatively little project-specific stuff in it, so it should be pretty easy to follow the logic. ------=_NextPart_000_001C_01C5DAF1.0E6DFD70 Content-Type: application/octet-stream; name="recv_uart.dspic" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="recv_uart.dspic" ; UART handler. ; ; UART 2 is used for one independent stream of commands/responses. = UART 1 ; is not used and is left disabled. ; /include "recv.ins.dspic" ; ;*********************************************************************** ; ; Configuration constants. ; equiv baud, 115200 ;baud rate equiv fifoi_sz, 8 ;software input FIFO size equiv fifoo_sz, 16 ;software output FIFO size ; ; Derived constants. ; set val_brg, freq_inst / (8 * baud) ;baud rate divisor * 2 set val_brg, (val_brg + 1) / 2 ;round to nearest integer divisor set val_brg, val_brg - 1 ;make actual baud rate register value ; ;*********************************************************************** ; ; Variables. ; ;******************* ; ; Global state. ; section .uart, bss ; ;******************* ; ; Local state. ; fifob_define fifoi, fifoi_sz ;define the UART input FIFO fifob_define fifoo, fifoo_sz ;define the UART output FIFO .if debug equiv fifoo_n, fifoo + fifob_ofs_n equiv fifoo_put, fifoo + fifob_ofs_put equiv fifoo_get, fifoo + fifob_ofs_get global fifoo_n, fifoo_put, fifoo_get .endif text ; ;*********************************************************************** ; ; Subroutine UART_INIT ; ; Initialize the hardware and software state managed by this module. ; glbsub uart_init, regf0 | regf1 ; ; Init local state. ; fifob_init fifoi ;initialize the UART input FIFO fifob_init fifoo ;initialize the UART output FIFO ; ; Init the UART hardware. ; mov #val_brg, w0 ;set the baud rate mov w0, U1brg bclr U1mode, #Uarten ;make sure UART is disabled, forces = reset mov #0b1000000000000000, w0 ; -X-XX-XX---XX--- reserved ; 1--------------- enable the UART ; --0------------- continue operation in idle mode = (not used) ; -----0---------- use primary pins for this UART ; --------0------- start bit doesn't wake from sleep = (not used) ; ---------0------ disable loopback mode ; ----------0----- disable auto baud rate detection ; -------------00- select 8 data bits, no parity ; ---------------0 select 1 stop bit mov w0, U1mode mov #0b0000010000000000, w0 ; -XXX------------ reserved ; 0--------------- set interrupt flag when FIFO can = accept new byte ; ----0----------- do not transmit a break now ; -----1---------- enable the transmitter ; ------X--------- transmit FIFO is full (read only) ; -------X-------- transmit register empty (read only) ; --------00------ set interrupt flag when at least = one char available ; ----------0----- disable address detect mode using = 9th data bit ; -----------X---- receiver is idle (read only) ; ------------X--- parity error (read only) ; -------------X-- framing error (read only) ; --------------X- receive overrun (read only) ; ---------------X receive buffer data available (read = only) mov w0, U1sta ; ; Initialize the UART interrupts. Receive interrupts are enabled here ; and stay enabled. Transmit interrupts are initialized to disabled. ; These are enabled when a byte is written into the software output ; FIFO, and disabled when the FIFO is drained to empty. ; ; The transmit and receive interrupt priority levels are set in the ; project include file with constants IPR_TX and IPR_RX, respectively. ; bclr Iec0, #U1txie ;make sure TX interrupts are disabled mov Ipc2, w0 ;get register containing interrupt priority = fields mov #0xF00F, w1 and w0, w1, w0 ;mask off the UART interrupt priorities mov #(ipr_tx << 8) | (ipr_rx << 4), w1 ior w0, w1, w0 ;merge in the desired priorities mov w0, Ipc2 ;update the priority register bset Iec0, #U1rxie ;enable RX interrupts leaverest ; ;*********************************************************************** ; ; Subroutine UART_PUT ; ; Send the byte in the low 8 bits of W0 out the UART. The byte is ; actually written to the UART output software FIFO, and will be = written ; to the UART by the UART transmit interrupt routine separately. If ; the software output FIFO is full, this routine calls TASK_YIELD = until ; it can receive another byte. All registers are preserved whether ; TASK_YIELD is called or not. ; glbsub uart_put, regf1 | regf2 | regf3 push w0 ;save W0, make sure on top of stack fifob_z_full fifoo ;set Z iff the software FIFO is completely = full bra nz, put_room ;there is room in the output FIFO ? ; ; The output FIFO is completely full. Wait for it to become not full. ; set putwsave, ~(tsksave | savedregs | regf0) ;register to save = around this section pushregs putwsave ;save regs trashed by YIELD and not already = saved 1: ;back here each time FIFO is still full gcall task_yield ;let other tasks run for one timeslice fifob_z_full fifoo ;set Z iff the FIFO is still full bra z, 1b ;FIFO still full, back to check again ? popregs putwsave ;restore registers saved around this = section ; ; The output FIFO has room to accept the new byte. ; put_room: pop w0 ;restore W0 to contain the data byte disi #0x3FFF ;temp disable interrupts fifob_put fifoo ;stuff the byte into the output FIFO bset Iec0, #U1txie ;make sure UART output interrupt is = enabled clr Disicnt ;re-enable interrupts leaverest ; ;*********************************************************************** ; ; UART transmit interrupt routine. ; ; The UART is ready to accept another output byte. This interrupt is ; enabled whenever a byte is written to the output FIFO. It is = disabled ; in this interrupt routine when the FIFO is drained to empty. ; glbsub __U1TXInterrupt, regf0 | regf1 | regf2 push Sr ;save register bclr Ifs0, #U1txif ;clear the interrupt condition fifob_get fifoo ;get next byte from FIFO into W0 mov w0, U1txreg ;write the byte to the UART fifob_z_empty fifoo ;set Z flag if the FIFO is now empty bra nz, 1f ;FIFO not yet empty ? bclr Iec0, #U1txie ;no more chars to send, disable this = interrupt 1: ;done disabling this interrupt on FIFO = empty pop Sr ;restore register explicilty pushed popsaved ;restore general registers implicitly = pushed disi #disintr retfie ;return from the interrupt ; ;*********************************************************************** ; ; UART receive interrupt routine. ; ; The UART has at least one byte available. This routine drains all ; available bytes into the software input FIFO. The firmware is reset ; if an input byte is lost. This can be due to a hardware UART = overrun ; or because the software FIFO was full when a new byte was available. ; Each condition should not occur during normal operation, and = indicates ; a firmware bug. Bytes with associated framing errors are ignored, ; since these can happen due to external hardware glitches, like cable ; being connected to disconnected. ; glbsub __U1RXInterrupt, regf0 | regf1 | regf2 | regf3 push Sr ;save STATUS register ; ; Loop back here until the UART has no received bytes left. All ; UART input bytes MUST be drained in a single interrupt service ; because the interrupt flag is set when a byte is received and ; is reset in software here. This means the interrupt condition ; is cleared regardless of whether just one or multiple input bytes ; are available. If only one input byte was drained and another is ; available, no new interrupt would occur for the remaining byte ; to be read from the UART. ; ; The interrupt flag is reset before the URXDA (byte available) flag ; is checked. If a new byte is received after the URXDA flag is = checked, ; then it will be received next interrupt. ; recv_loop: ;back here to receive each new available = byte bclr Ifs0, #U1rxif ;clear the interrupt condition mov U1sta, w1 ;grab snapshot of status before reading = byte mov U1rxreg, w3 ;get the data byte into low 8 bits of W3 btsc w1, #Oerr ;no overrun error ? jump error_hwov ;hardware overflow error btsc w1, #Ferr ;no framing error ? bra recv_dbyte ;framing error, ignore this byte fifob_z_full fifoi ;set Z if the software input FIFO is full bra nz, 1f ;there is room in the FIFO ? swerr err_uartswov ;software FIFO overflow 1: ;the software FIFO can accept another byte mov w3, w0 ;get the data byte into W0 fifob_put fifoi ;stuff the data byte into the software = input FIFO recv_dbyte: ;done receiving this byte btsc U1sta, #Urxda ;UART completely drained ? bra recv_loop ;no, go back and get the next byte pop Sr ;restore register explicilty pushed popsaved ;restore general register implicitly pushed disi #disintr retfie ;return from the interrupt error_hwov: swerr err_uarthwov ;hardware overflow error ; ;*********************************************************************** ; ; Subroutine UART_GET_READY ; ; Determine whether a byte from the UART is immediately available. ; If a byte is available then the Z flag is reset and set otherwise. ; If this routine returns with the Z flag reset, then the next call ; to UART_GET is guaranteed to return immediately with a new byte. ; glbsub uart_get_ready, regf0 fifob_z_empty fifoi ;set Z if no byte available leaverest ; ;*********************************************************************** ; ; Subroutine UART_GET ; ; Return the next byte from the UART in W0. If no byte is immediately ; available, then TASK_YIELD is called continually until a byte is ; available. All registers W1-W15 are preserved whether TASK_YIELD ; is called or not. ; glbsub uart_get, regf1 | regf2 fifob_z_empty fifoi ;set Z if no byte is available bra nz, get_byte ;a byte is available, go get it ; ; No byte is immediately available. Wait for a new byte. ; set getwsave, ~(tsksave | savedregs | regf0) ;register to save = around this section pushregs getwsave ;save regs trashed by YIELD and not = trashable 1: ;back here each time FIFO is still full gcall task_yield ;let other tasks run for one timeslice fifob_z_empty fifoi ;set Z if still no byte available bra z, 1b ;no byte, go back and check again ? popregs getwsave ;restore registers saved around this = section ; ; At least one byte is available in the software input FIFO. ; get_byte: disi #0x3FFF ;temp disable interrupts fifob_get fifoi ;get the next byte into W0 clr Disicnt ;re-enable interrupts leaverest end ------=_NextPart_000_001C_01C5DAF1.0E6DFD70 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist ------=_NextPart_000_001C_01C5DAF1.0E6DFD70-- ****************************************************************** Embed Inc, Littleton Massachusetts, (978) 742-9014. #1 PIC consultant in 2004 program year. http://www.embedinc.com/products