📄 uart.asm
字号:
;==========================================================
; This is a part of: Eversmith - AVRSMS
; Copyright (2003) Martin Thomas, Kaiserslautern, Germany.
; This Software is distributed under the Aladdin Free
; Public License (AFPL) Read the file license.txt included
; in the distibution-package. See main-file for more infor-
; mation and license.
;==========================================================
; USART-Handling
; - prepared for devices with two USARTS
; - uses FIFO-Buffers
;
; Receives large amounts of data without handshaking
; because of a large buffer which consumes a lot of SRAM
; Handshaking is on the TODO-list and will lower SRAM demand
; Here UART1 ist the first and UART2 is the second.
; -- this is for one(1) UART --
; Calls to UART2 routines are just passed to UART1
; routines. Numbering different from standard
; UART1 is first UART (0) UART2 is 2nd (1) (COM1/COM2 ;-) )
; TODO: add handling for second UART on Mega128 or Mega162
;.include "globals.inc" ; already in main-file
; from include-file:
;.equ SYSCLOCK = 8000000 ; in Hz ( 1 MHz = 1000000 Hz )
;.equ BAUDRATE = 19200 ;
.equ const_UBRR = (SYSCLOCK/(16*BAUDRATE))-1
.equ XONchar = $11
.equ XOFFchar = $13
.DSEG
;----------------------------------------------------------
; UART Timeout-Counters
; UARTDEFT0CNT is the default timeout for the receive-
; function in 0,01 sec (10ms) (routine
.equ UARTMAXTOCNT=5
UART1TOCNT: .byte 1
UART2TOCNT: .byte 1
;----------------------------------------------------------
; UART Receive FiFo Inits
; this is a test included with Eversmith V0.56:
; Due to the better timeout handling, a smaller buffer
; should work even without handshaking.
; In general handshaking would be better. Software handshake
; is still on the TODO-List.
; When SMS receive does not work reliably increase the
; buffer size (i.e. UARTBUFSIZE = 128)
.equ UARTBUFSIZE = 20
UART1Buf: .byte UARTBUFSIZE
UART2Buf: .byte UARTBUFSIZE
; Buffer-Pointers
RX1HEAD: .byte 1
RX1TAIL: .byte 1
RX2HEAD: .byte 1
RX2TAIL: .byte 1
; Number of chars/bytes in buffers
UART1nBuf: .byte 1
UART2nBuf: .byte 1
.CSEG
;-------------------------------------------------
; Init UARTs - this is for an USART (ATMega)
;-------------------------------------------------
UARTInit:
push r16
; Init USART1 on ATMega16
ldi r16,HIGH(const_UBRR)
out UBRRH,r16 ; set baud rate
ldi r16,LOW(const_UBRR)
out UBRRL,r16
sbi UCSRB,TXEN ;set transmit enable bit
sbi UCSRB,RXEN ;set receive enable bit
ldi r16,(1<<URSEL)|(3<<UCSZ0)
out UCSRC,r16 ;set 8,n,1
; TODO: Init UART2
rcall UARTEnableFIFOs
rcall UART1Flush
rcall UART2Flush
pop r16
ret
;-------------------------------------------------
; Send byte in r16 to UART 1
;-------------------------------------------------
UART1SendByte:
U1SB_L1:
sbis USR,UDRE ;wait till register is cleared
rjmp U1SB_L1
cli ;disable (all) receiver interrupt
out UDR,r16 ;send byte
sei ;enable interrupts
ret
;-------------------------------------------------
; Send byte in r16 to UART 2 - dummy
;-------------------------------------------------
UART2SendByte:
rcall UART1SendByte
ret
;------------------------------------------------------------
; UartEnableFIFOs
;------------------------------------------------------------
UartEnableFIFOs:
push r16
clr r16 ; ldi r16,$00
sts RX1HEAD,r16 ; clear FIFOs
sts RX1TAIL,r16
sts RX2HEAD,r16
sts RX2TAIL,r16
sts UART1nBuf,r16
sts UART2nBuf,r16
cli ; disable all interrupts
sbi UCR,RXC ; switch on UART1 receive interrupt
;TODO: ; switch on UART2 receive interrupt
sei ; enable all interupts
pop r16
ret
;------------------------------------------------------------
; UartDisableFIFO
;------------------------------------------------------------
UartDisableFIFOs:
push r1
push r16
in r1,SREG
cli
cbi UCR,RXC ; switch off UART1 receive interrupt
;TODO: ; switch off UART2 receive interrupt
sei
out SREG,r1
clr r16 ; ldi r16,$00
sts RX1HEAD,r16 ; clear FIFOs
sts RX1TAIL,r16
sts RX2HEAD,r16
sts RX2TAIL,r16
sts UART1nBuf,r16
sts UART2nBuf,r16
pop r16
pop r1
ret
;----------------------------------------------------------
; UART1RXISR - RX Interrupt Handler for UART1
;----------------------------------------------------------
; to implement a FIFO-Buffer for UART1
; RX-Interrupt of UART 1 in Interrupt-Vector must point to
; this Routine
; basic code from Jack Tidwell (I can't remember the URL)
; Avoid using r1 in other interrupt-handlers!
UART1RXISR:
push r1
in r1,SREG ; preserve main OS status reg.
push r22
push r23
push zl
push zh
lds r23,RX1TAIL
clr r22
ldi zl,low(UART1Buf) ; ptr to our rxbuffer
ldi zh,high(UART1Buf)
add zl,r23 ; rxtail
adc zh,r22
in r22,UDR ; get the incomming char
st z,r22 ; Buf[rxtail++] = UDR
lds r22,UART1nBuf
inc r22 ; inc num of bytes in buf
sts UART1nBuf,r22
cpi r22,UARTBUFSIZE ; if (nByte!=BUFFSIZE) goto U1in_noOverrun
brne U1in_noOverrun
push r21
ldi r21,0b10101010 ; dbg - signal overrun with leds
call DebugLEDS
pop r21
U1in_noOverrun:
inc r23 ; rxtail++
cpi r23,UARTBUFSIZE ; if (rxtail!=buffsize) goto U1inx
brlo U1inx
; Circle around to the first buffer pos.
clr r23; ; rxtail=0
U1inx:
sts RX1TAIL,r23
pop zh
pop zl
pop r23
pop r22
out SREG,r1 ; restore previous status reg
pop r1
reti ; return to normal pgm status.
;----------------------------------------------------------
; UART2RXISR - RX Interrupt Handler for UART2 - dummy
;----------------------------------------------------------
; to implement a FIFO-Buffer for UART2
; RX-Interrupt of UART 2 in Interrupt-Vector must point to
; this Routine
UART2RXISR:
push r1
in r1,SREG ; preserve main OS status reg.
;;; TODO
out SREG,r1 ; restore previous status reg
pop r1
reti ; return to normal pgm status.
;-------------------------------------------------------------
; UARTTIMEOUTCNT - increments the timeout-counters
;-------------------------------------------------------------
; called by the T0OVR ISR in avrsms.asm (every 10 ms by
; default)
UARTTIMEOUTCNT:
push r16
lds r16, UART1TOCNT
cpi r16,$ff ; avoid overflow to 0
breq UTcnt_L1
inc r16
sts UART1TOCNT,r16
UTcnt_L1:
lds r16, UART2TOCNT
cpi r16,$ff ; avoid overflow to 0
breq UTcnt_L2
inc r16
sts UART2TOCNT,r16
UTcnt_L2:
pop r16
ret
;-------------------------------------------------------------
; Uart1ReadByte - Get a byte from UART1-RX-FIFO
;-------------------------------------------------------------
;
; Inputs:
; r18 timeout value (0=no timeout)
; Routine waits 10msec*UARTMAXTOCNT before returning
; with error.
; The timeout is a "no data availabe timeout". If the modem
; sends garbage all the time this will never timeout.
;
; Ouputs:
; r17 Byte read
; carry flag set if timeout occured
; carry flag cleared on normal read
;
; based on code from Jack Tidwell
Uart1ReadByteFIFO:
push r2
push r20
push r22 ; head
push r23 ; tail
push zl
push zh
clr r3
clr r17
sts UART1TOCNT,r17 ; reset timeout-counter
U1GBF_L1:
lds r22,RX1HEAD
lds r23,RX1TAIL
cp r22,r23; ; rxhead,rxtail
brne U1GBF_process ; byte in buffer - process
cpi r18,$00
breq U1GBF_L1 ; no Timout value given, loop until receive
lds r20,UART1TOCNT ; load timeout counter
cp r20,r18 ; compare actual count(r20) with given (r18)
brne U1GBF_L1 ; branch if timout not reached
rjmp U1GetBytexit ; timeout occured
U1GBF_process:
lds r22,RX1HEAD
ldi zl,low(UART1Buf) ; Pointer to the rxbuffer (FIFO)
ldi zh,high(UART1Buf)
cli ; disable interrupts to avoid side-eff.
lds r2,UART1nBuf
dec r2 ; dec num of bytes in buf
sts UART1nBuf,r2
sei ; re-enable interrupts
clr r17
add zl,r22 ; rxhead
adc zh,r17
ld r17,z ; tempchar = Buf[rxhead++]
inc r22 ; rxhead
cpi r22,UARTBUFSIZE ; rxhead
brlo U1Gbx
clr r22 ;rxhead, Circle around to the first buffer pos.
U1Gbx:
clc ; mark normal receive
rjmp U1GBF_end ;
U1GetBytexit: ;
sec ; return timout
U1GBF_end:
sts RX1HEAD,r22
pop zh
pop zl
pop r23
pop r22
pop r20
pop r2
ret
;-------------------------------------------------------------
; Uart2ReadByte - Get a byte from UART2-RX-FIFO - dummy
;-------------------------------------------------------------
;
; Inputs:
; see above
;
; Ouputs:
; r17 Byte read
; carry flag set if timeout occured
; carry flag cleared on normal read
;
; no 2nd hardware-UART on ATMega16 -> this simply forwards
Uart2ReadByteFIFO:
rcall UART1ReadByteFIFO
ret
;----------------------------------------------------------
; Uart1Flush - empty receive "buffer" of UART1
;----------------------------------------------------------
; Inputs/Ouputs: none
Uart1Flush:
push r17
push r18
U1F_L1:
ldi r18,$01 ; timeout value
rcall Uart1ReadByteFIFO
brcc U1F_L1
clr r18
sts UART2nBuf,r18
pop r18
pop r17
ret
;----------------------------------------------------------
; Uart2Flush - empty receive "buffer" of UART2
;----------------------------------------------------------
; Inputs/Ouputs: none
Uart2Flush:
push r17
push r18
U2F_L1:
ldi r18,$01 ; timeout value
rcall Uart2ReadByteFIFO ; reads char in r17
brcc U2F_L1
clr r18
sts UART2nBuf,r18
pop r18
pop r17
ret
; Handshaking in RXInter-Hnd:
; if (buffer is >=90% filled && flag "onhold"==0) then
; flag "onhold"=true, send XOFF
; In ReadFifo:
; TODO: handshaking
; if ("onhold"==1 && buffer<20% filled) then
; flag "onhold"=0, send XON
; (US-Robotics Courier Manual)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -