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

📄 8051-uart(asm)_2.asm

📁 Full Uart by 8051 (assembly)
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;-----------------------------------------------------------------------------
;	COPYRIGHT 2001 CYGNAL INTEGRATED PRODUCTS, INC.
;
; 	FILE NAME  	: an015_2.ASM 
; 	TARGET MCU	: C8051F000
; 	DESCRIPTION	: Example source code for a software UART
;
; IMPLEMENTATION NOTES:
;  - uses Timer0 in Mode3 (two 8-bit timers)
;  - Timer0 run/overflow is used for RX state machine
;  - Timer1 overflow is used for TX state machine
;  - 8N1, no Framing error detection
;  - uses IE7 as user-level interrupt
;  - uses single-byte PC offset for state table implementation
;  - uses /INT0 falling as START bit detect (primitive START bit verification)
;
;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------
; EQUATES
;-----------------------------------------------------------------------------

$MOD8F000

; SW UART constants
SW_TX_GPIO	EQU	P0.4				; SW UART TX GPIO pin (can be any GPIO pin)
SW_RX_GPIO	EQU	P0.2				; SW UART RX GPIO pin (must be /INT0)

TIME_COUNT	EQU	320				; = SYSCLK_FREQ / BAUD_RATE (MIN = 128 HD / 
											;  480 FD)
											; Note: 320 is the limit for reliable
											;  FD operation...
											; FOR SYSCLK = 18.432 MHz:
											;  115200 = 160
											;  57600 = 320
											;  38400 = 480
											;  19200 = 960
											;  9600 = 1920
											;  4800 = 3840
											;  2400 = 7680

TX_CORR		EQU	41					; (41) Timer preload correction value in 
											;  cycles for TX
RX_CORR		EQU	47					; (47) Timer preload correction value in 
											;  cycles for RX
THALF_CORR	EQU	113				; (113)Timer preload correction value for 
											;  3/2 RX

TX_BT		EQU TIME_COUNT - TX_CORR	; actual 16-bit bit counter cycle value 
												;  TX
RX_BT		EQU TIME_COUNT - RX_CORR	; actual 16-bit bit counter cycle value 
												;  RX
THALF_BT	EQU TIME_COUNT*3/2 - THALF_CORR ; actual 16-bit 1.5 bit cycle value 
												;  RX

RX_BUFSIZE	EQU	16					; size of RX buffer in chars
;-----------------------------------------------------------------------------
; VARIABLES
;-----------------------------------------------------------------------------

BSEG
			org 0h

SRI:		DBIT		1					; SW UART Receive complete flag
STI:		DBIT		1					; SW UART Transmit complete flag
STXBSY:	DBIT		1					; SW UART TX BSY flag
SREN:		DBIT		1					; SW UART RX Enable
SES:		DBIT		1					; SW UART user-Interrup Support Enable

DSEG at 30h

TDR:		DS			1					; SW UART TX data register
RDR:		DS			1					; SW UART RX data register
RXSHIFT:	DS			1					; SW UART RX shift register
SURXST:	DS			1					; SW UART RX state variable
SUTXST:	DS			1					; SW UART TX state variable
BCRHI:	DS			1					; MSB of 16-bit bit timer for SW UART RX
BCTHI:	DS			1					; MSB of 16-bit bit timer for SW UART TX

;test variables
RX_TAIL:	DS			1					; write pointer to RX message buffer
TX_VAL:	DS			1					; value to transmit
;-------------------
; Indirect address space variables

ISEG at 80h

RX_BUF:	DS			RX_BUFSIZE		; RX message buffer

;-------------------
; STACK

STACK_TOP:	DS		1					; placeholder in symbol table for 
											;  beginning of hardware stack

;-----------------------------------------------------------------------------
; MACRO DEFINITIONS
;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------
; RESET AND INTERRUPT VECTOR TABLE
;-----------------------------------------------------------------------------

CSEG
			org	00h					
			ljmp	Reset					; RESET initialization vector

			org	03h
			ljmp	INT0_ISR				; Software UART RX START bit detect

			org	0bh
			ljmp	Timer0_ISR			; Software UART RX state machine interrupt

			org	1bh
			ljmp	Timer1_ISR			; Software UART TX state machine interrupt

			org	9bh
			ljmp	IE7_ISR				; user-level Software UART interrupt
			
;-----------------------------------------------------------------------------
; MAIN PROGRAM CODE
;-----------------------------------------------------------------------------

			org	0B3h

Main:
;			ajmp	PolledRX_PolledTX	; leave one of these lines uncommented

			ajmp	InterruptRX_InterruptTX	; leave one of these lines uncommented

			sjmp	$						; spin forever...

;-----------------------------------------------------------------------------
; MAIN SUBROUTINES
;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------
; PolledRX_PolledTX
;-----------------------------------------------------------------------------
; This routine demonstrates polled access to the SW UART.
;
; The transmitter transmits a sequence from $00 to $ff
;
; The receiver receives characters and stores them in a circular buffer.
;
PolledRX_PolledTX:
			acall	SW_UART_Init		; initialize SW UART (leave in a
											;  disabled state)

			setb	SREN					; enable SW UART receiver
			clr	SES					; disable user-level interrupt
											;  support
			acall	SW_UART_Enable		; enable SW UART

			; transmit message -- polled mode
			jb		STXBSY, $			; wait for SW TX available

			; transmit chars $00 to $ff
			clr	a
TX_LOOP:	setb  STXBSY            ; Claim SW UART Transmitter
         mov	TDR, a				; write char to transmit data reg
			setb	ET1					; initiate SW TX operation
			inc	a						; set next value to write
			jnb	STI, $				; wait for TX complete
			clr	STI					; clear TX complete indicator
			jnz	TX_LOOP
TX_LOOP_END:

			mov	RX_TAIL, #RX_BUF	; init TAIL pointer

			; receive message -- polled mode
RX_LOOP:	mov	r0, RX_TAIL			; indirect address to write character to
			jnb	SRI, $				; wait for RX character
			clr	SRI					; clear RX complete indicator
			mov	@r0, RDR				; store it
			inc	RX_TAIL				; advance TAIL pointer
			mov	a, RX_TAIL			; handle TAIL wrapping
			add	a, #-(RX_BUF + RX_BUFSIZE)
			jnc	RX_LOOP
			mov	RX_TAIL, #RX_BUF	; wrap TAIL

			sjmp	RX_LOOP				; repeat forever...

;-----------------------------------------------------------------------------
; InterruptRX_InterruptTX
;-----------------------------------------------------------------------------
; This routine demonstrates interrupt access to the SW UART.
;
; The receiver receives characters and stores them in a circular buffer.
; Both the transmit and receive routines are located in the IE7_ISR handler.
;
InterruptRX_InterruptTX:

			acall	SW_UART_Init		; initialize SW UART (leave in a
											; disabled state)
			setb	SES					; Enable user-level interrupt support
			setb	SREN					; Enable SW UART receiver
			
			mov	RX_TAIL, #RX_BUF	; init TAIL pointer

			acall	SW_UART_Enable		; enable SW UART

			setb	STI					; kick-start SW UART transmitter
			orl	EIE2, #00100000b	; by enabling IE7
			orl	PRT1IF, #10000000b; and activating IE7

			sjmp	$

;-----------------------------------------------------------------------------
; INTERRUPT VECTORS
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
; Reset Interrupt Vector
;
; This routine initializes the device and all peripherals and variables.
;   - External oscillator started (sysclk will be switched to external osc. 
;     once XTLVLD goes high)
;   - Watchdog timer is disabled
;   - Crossbar and GPIO output modes are defined
;   - H/W stack pointer is initialized
;   - interrupt priorities and enables are initialized here
;     - /INT0
;     - Timer0
;     - Timer1

Reset:
         mov	OSCXCN, #01100110b; Enable Crystal osc., divide by 1 mode
											;  XFCN = '110' for 18.432 MHz crystal
											;  External oscillator will be selected
											;  below after XTLVLD has gone high
											;  indicating that the external osc
											;  has started and settled (several
											;  hundred microseconds from now).

			mov	WDTCN, #0deh		; disable watchdog timer
			mov	WDTCN, #0adh

			; set up Crossbar and Port I/O
			mov	XBR0, #00000100b	; enable HW UART on P0.0 (TX), P0.1 (RX)
			mov	XBR1, #10000100b	; enable /INT0 on P0.2; /SYSCLK on P0.3
			mov	XBR2, #01000000b	; enable crossbar w/ pull-ups enabled
			orl	PRT0CF, #00011101b; enable P0.0, 0.2, 0.3, and 0.4 as push-pull
											; P0.4 is SW UART TX pin
											; P0.2 is SW UART RX pin
			orl	PRT1CF, #01000000b; enable P1.6 (LED on target board) as 
											;  push-pull

			mov	SP, #STACK_TOP		; init stack pointer to end of allocated RAM

		; Wait >1 ms before checking external crystal for stability
		   clr 	a
		   mov	r0, a		          ; Clear r0

		   djnz	r0, $		          ; Delay ~380 祍
		   djnz	r0, $	             ; Delay ~380 祍
		   djnz	r0, $			       ; Delay ~380 祍				
											

OSC_WAIT:
			mov	a, OSCXCN			; spin here until crystal osc is stable
			jnb	acc.7, OSC_WAIT

			orl	OSCICN, #00001000b; Select external osc. as
											;  system clock source
			anl	OSCICN, #NOT(00000100b); Disable internal oscillator
			orl	OSCICN, #10000000b; Enable missing clock detector
											;  this must be done AFTER
											;  selecting ext osc as system
											;  clock source

			setb	EA						; enable GLOBAL interrupts

			ljmp 	Main

;-----------------------------------------------------------------------------
; Timer0_ISR / INT0_ISR
;
; These interrupts start and drive the SW UART receive state machine
;
SWRX_STATE_TABLE:							; each table entry is 1 byte
	DB		SWRX_S0 - SWRX_STATE_TABLE	; IDLE / START detect
	DB		SWRX_S1 - SWRX_STATE_TABLE	; b0
	DB		SWRX_S2 - SWRX_STATE_TABLE	; b1
	DB		SWRX_S3 - SWRX_STATE_TABLE	; b2
	DB		SWRX_S4 - SWRX_STATE_TABLE	; b3
	DB		SWRX_S5 - SWRX_STATE_TABLE	; b4
	DB		SWRX_S6 - SWRX_STATE_TABLE	; b5
	DB		SWRX_S7 - SWRX_STATE_TABLE	; b6
	DB		SWRX_S8 - SWRX_STATE_TABLE	; b7
	DB		SWRX_S9 - SWRX_STATE_TABLE	; STOP bit capture

INT0_ISR:
Timer0_ISR:
			push	PSW					; resource preservation
			push	acc

			mov	a, BCRHI				; if BCRHI is non-zero, we need to roll 
											;  through the timer again...
			jz		SWRX_PROCESS_STATE
			dec	BCRHI
			ajmp	Timer0_ISR_EXIT

SWRX_PROCESS_STATE:
			push	DPH					; resource preservation
			push	DPL

			mov	a, SURXST			; read state offset from table
			mov	DPTR, #SWRX_STATE_TABLE
			movc	a, @A+DPTR			; 'a' now contains state offset (PC)
			jmp	@A+DPTR				; execute state

Timer0_ISR_END:						; ALL RX states return here

			pop	DPL					; resource restoration
			pop	DPH
Timer0_ISR_EXIT:
			pop	acc					; resource restoration
			pop	PSW
			reti

;SWRX_S0: RX IDLE state
; At this point, a falling edge has been detected on /INT0.  
; We first check to see if the SW UART receiver is enabled.  If it is, we check
; once to see if the RX pin is still low (START bit valid).  If it is, we set up 
; Timer0 to count for 3/2 bit time in order to capture the LSB.  Here, we also 
; disable /INT0 interrupts.
;	- Check for SREN = '1':  IF '1':
;		- Load TL0 with 3/2 bit time value
;		- Start Timer
;		- Enable TF0 interrupt
;		- Disable /INT0 interrupt
;		- INC state variable to S1
;	- IF SREN = '0' (SW UART RX disabled)
;		- exit gracefully, next state is S0
;
SWRX_S0:
			jnb	SREN, SWRX_S0_END	; Check to see if SW UART RX is enabled
											;  if not, exit and remain at IDLE state

			jb		SW_RX_GPIO, SWRX_S0_END	; check to see if START bit is good

			clr	EX0					; disable /INT0

			clr	TR0					; Stop Timer0 (low)
			clr	TF0					; Clear any pending interrupts

			mov	BCRHI, #HIGH(THALF_BT)	; set Timer0 (low) + BCRHI for 1.5 bit 
			mov	TL0, #-LOW(THALF_BT)	;  times from now (we assume the start
											;  bit is good)

			setb	ET0					; enable Timer0 interrupts
			setb	TR0					; Start Timer0L

			inc	SURXST				; next state is SWRX_S1 (we assume START bit 
											;  is good)

SWRX_S0_END:
			ajmp	Timer0_ISR_END

;SWRX_S1 thru SWRX_S8: Capture b0..b7
; At this point, we've determined that the START bit is valid, and we're going to 
; query RX_GPIO at bit intervals, shifting the results into RXSHIFT.
;	- If BCRHI is non-zero, then we need to spin through the timer again
;		- DEC BCRHI
;		- let timer roll over on its own
;		- leave state as is
;	- If BCRHI is zero:
;		- stop timer
;		- Move RX_GPIO state into Carry

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -