⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uart.asm

📁 Eversmith_-_AVRSMS for pdu mode
💻 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 + -