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

📄 8051-uart(asm)_2.asm

📁 Full Uart by 8051 (assembly)
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;		- Right shift Carry into RXSHIFT 
;		- set up timer to capture the next bit
;		- enable timer
;		- advance state variable
;
SWRX_S1:
SWRX_S2:
SWRX_S3:
SWRX_S4:
SWRX_S5:
SWRX_S6:
SWRX_S7:
SWRX_S8:
			clr	TR0					; Stop Timer0 (low)
			clr	TF0					; Clear any pending interrupts

			mov	BCRHI, #HIGH(RX_BT); load bit time value into 16-bit virtual 
											;  counter
			mov	TL0, #-LOW(RX_BT)

			setb	TR0					; START RX bit timer

			mov	C, SW_RX_GPIO		; Move RX state into Carry prior to rshift

			mov	a, RXSHIFT
			rrc	a						; right shift Carry into shift register
			mov	RXSHIFT, a			; re-store

			inc	SURXST				; advance state variable

SWRX_S2_END:
			ajmp	Timer0_ISR_END

;SWRX_S9: Capture STOP bit
; At this point, we've shifted all the data bits into RXSHIFT, and we're ready to 
; sample the STOP bit. Here, we indicate that we've received a character, and reset 
; the state machine back to IDLE. In this implementation, we don't actually capture 
; the STOP bit; we assume it's good.  Here's where we would add support for Framing 
; Error detection.
;	- 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 RXSHIFT into RDR
;		- Set SRI
;		- Disable timer interrupt
;		- Enable /INT0 interrupt
;		- Reset state variable to IDLE
;		- Check to see if User-level interrupt support is enabled (EIS): If so:
;			- Enable IE7
;			- Toggle P1.7 to activate IE7
;
SWRX_S9:
			clr	TR0					; Stop Timer0L
			mov	RDR, RXSHIFT		; move data from shift reg to data reg
			
			setb	SRI					; set SW UART SRI bit to indicate RX complete
			clr	ET0					; Disable Timer0L interrupt
			clr	IE0					; Disable pending /INT0 interrupts
			setb	EX0					; Enable /INT0 interrupt
			mov	SURXST, #00			; reset RX state to IDLE

			jnb	SES, SWRX_S9_END	; check to see if user-level interrupt 
											;  support is enabled
			orl	EIE2, #00100000b	; enable IE7; leave priority alone
			orl	PRT1IF, #10000000b; activate IE7
SWRX_S9_END:
			ajmp	Timer0_ISR_END

;-----------------------------------------------------------------------------
; Timer1_ISR (note that this is actually called by the upper-half of Timer0
;  which is operating in Mode 3)
;
; This interrupt drives the SW UART transmit state machine
;
SWTX_STATE_TABLE:						; each table entry is 1 byte; 11 entries
											;  total
	DB		SWTX_S0  - SWTX_STATE_TABLE	; START bit
	DB		SWTX_S1  - SWTX_STATE_TABLE	; b0
	DB		SWTX_S2  - SWTX_STATE_TABLE	; b1
	DB		SWTX_S3  - SWTX_STATE_TABLE	; b2
	DB		SWTX_S4  - SWTX_STATE_TABLE	; b3
	DB		SWTX_S5  - SWTX_STATE_TABLE	; b4
	DB		SWTX_S6  - SWTX_STATE_TABLE	; b5
	DB		SWTX_S7  - SWTX_STATE_TABLE	; b6
	DB		SWTX_S8  - SWTX_STATE_TABLE	; b7
	DB		SWTX_S9  - SWTX_STATE_TABLE	; STOP bit onset edge
	DB		SWTX_S10 - SWTX_STATE_TABLE	; STOP bit terminus

Timer1_ISR:
			push	PSW					; resource preservation
			push	acc

			mov	a, BCTHI				; if BCTHI is non-zero, we need to roll 
											;  through the timer again...
			jz		SWTX_PROCESS_STATE
			dec	BCTHI
			ajmp	Timer1_ISR_EXIT

SWTX_PROCESS_STATE:
			push	DPH					; resource preservation
			push	DPL

			mov	a, SUTXST			; read state offset from table
			mov	DPTR, #SWTX_STATE_TABLE
			movc	a, @A+DPTR			; acc now contains state offset
			jmp	@A+DPTR				; execute State x

Timer1_ISR_END:						; ALL TX states return here

			pop	DPL					; resource restoration
			pop	DPH
Timer1_ISR_EXIT:
			pop	acc					; resource restoration
			pop	PSW

			reti

;SWTX_S0: TX START bit state
; At this point, user code has placed the char to be transmitted in TDR and has 
; called the Timer1 interrupt handler explicitly by setting TF1.
;	- Clear STI
;	- Drop TX_GPIO (START bit onset edge)
;	- Configure TH0, BCTHI for next bit time, which will be the LSB
;	- Enable TH0
;	- Set next state to SWTX_S1
;
SWTX_S0:
			mov	BCTHI, #HIGH(TX_BT); load bit time value into 16-bit virtual 
											;  counter
			mov	TH0, #-LOW(TX_BT)
			clr	SW_TX_GPIO			; START bit onset edge
			clr	TF1					; clear any pending interrupts

			inc	SUTXST				; next state is SWTX_S1
SWTX_S0_END:
			ajmp	Timer1_ISR_END

;SWTX_S1 thru SWTX_S9: TX b0..b7 and STOP bit
; At this point, we start shifting the character in TDR out the TX_GPIO pin, bit 
; by bit, one bit per state transition.  We shift in an extra '1' at the MSB which 
; becomes the STOP bit.
;	- If BCTHI is non-zero, then we need to spin through the timer again
;		- DEC BCTHI
;		- let timer roll over on its own
;		- leave state as is
;	- If BCTHI is zero:
;		- stop timer
;		- set up timer for next bit
;		- right-shift TDR
;		- enable timer
;		- output bit
;		- advance state variable
;
SWTX_S1:
SWTX_S2:
SWTX_S3:
SWTX_S4:
SWTX_S5:
SWTX_S6:
SWTX_S7:
SWTX_S8:
SWTX_S9:
			mov	BCTHI, #HIGH(TX_BT); load bit time value into 16-bit virtual 
											;  counter
			mov	TH0, #-LOW(TX_BT)

			mov	a, TDR				; right shift next bit to transmit into Carry
			setb	C						; shift STOP bit into MSB
			rrc	a
			mov	TDR, a				; re-store value
			mov	SW_TX_GPIO, C		; output bit on GPIO pin
			clr	TF1					; clear any pending interrupts

			inc	SUTXST				; advance to next state

SWTX_S1_END:
			ajmp	Timer1_ISR_END

;SWTX_S10 STOP bit complete / reset to IDLE
; At this point, we've shifted the STOP bit out, and we're ready to reset the state 
; machine and indicate transmit complete, including initiating a user-level interrupt
; if it's enabled.
;	- If BCTHI is non-zero, then we need to spin through the timer again
;		- DEC BCTHI
;		- let timer roll over on its own
;		- leave state as is
;	- If BCTHI is zero:
;		- stop timer
;		- set STI
;		- clear STXBSY
;		- check for IE7 support, and activate if enabled
;		- set state variable to S0
;
SWTX_S10:
			clr	ET1					; Disable Timer1 interrupts
			setb	TF1					; Force a pending Timer1 interrupt.  This 
											;  allows the Enable Timer1 interrupt 
											;  operation to immediately trigger a 
											;  transmit operation

			mov	SUTXST, #00h		; reset state variable to IDLE state
			setb	STI					; Set STI to indicate transmit complete
			clr	STXBSY				; Clear TXBSY to indicate transmitter 
											;  available
			jnb	SES, SWTX_S10_END	; activate user-level interrupt IE7 if 
											;  enabled
			orl	EIE2, #00100000b	; enable IE7; leave priority alone
			orl	PRT1IF, #10000000b; activate IE7
SWTX_S10_END:
			ajmp	Timer1_ISR_END

;-----------------------------------------------------------------------------
; IE7_ISR
;
; This is the user-level interrupt handler for the SW UART.  Note:  this code
; MUST check both SRI and TRI, and if both are set, it must handle one case, and
; retrigger IE7 for the other case (or handle it in the same call) if that case
; is interrupt handled.  This is not required, for example, if the RX case is 
; handled in the interrupt and the TX case is polled.
;
; Note, if the TX case is polled, STI should not be cleared here.
;
; In this example, if SRI is set, indicating that a character was received by
; the SW UART, that received character is stored in a circular buffer (RX_BUF).
; If STI is set, indicating transmit complete, the character stored in TX_VAL
; is transmitted (and post incremented).
; 
;
IE7_ISR:
			push	PSW
			push	acc

			anl	PRT1IF, #NOT(10000000b); clear IE7
			jbc	SRI, SW_RX_HANDLE	; handle receive first, since 
											;  it's the most sensitive to 
											;  latency
			jbc	STI, SW_TX_HANDLE	; handle TX case
IE7_ISR_END:
			pop	acc
			pop	PSW
			reti							; all IE7_ISR routines return here...

SW_RX_HANDLE:
			push	ar0					; resource preservation

			mov	r0, RX_TAIL			; point r0 to location to store
			mov	@r0, RDR				; read value into buffer
			inc	RX_TAIL				; update the TAIL pointer
			mov	a, RX_TAIL			; wrap pointer if necessary
			add	a, #-(RX_BUF+RX_BUFSIZE)
			jnc	SW_RX_HANDLE_END
			mov	RX_TAIL, #RX_BUF	; wrap the pointer

SW_RX_HANDLE_END:
			jnb	STI, NO_TX_PENDING; if TX interrupt is pending,
			orl	PRT1IF, #10000000b;  activate it (IE7)

NO_TX_PENDING:
			pop	ar0
			ajmp	IE7_ISR_END

SW_TX_HANDLE:
         setb  STXBSY            ; Claim SW UART Transmitter
			mov	TDR, TX_VAL			; load byte to trasmit into TDR
			setb	ET1					; start SW UART transmitter
			inc	TX_VAL				; next byte to store

SW_TX_HANDLE_END:
			jnb	SRI, NO_RX_PENDING; if RX interrupt is pending,
			orl	PRT1IF, #10000000b;  activate it (IE7)
NO_RX_PENDING:
			ajmp	IE7_ISR_END			; exit

;-----------------------------------------------------------------------------
; SUBROUTINES
;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------
; SW UART SUBROUTINES (non-user code)
;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------
; SW_UART_Init
;
; Init:
;  - /INT0 is falling-edge triggered
;  - Timer0 in Mode 3, (2) 8-bit timers, interrupt handlers for TL0, TH0 (TF0, TF1)
;    timers initially disabled...
;  - RX/TX State machines and state variables
;  - SW UART TX state machine and RX state machine operate at HIGH priority
SW_UART_Init:
			; Init /INT0
			clr	EX0					; disable /INT0 interrupts
			setb	IT0					; /INT0 is falling-edge triggered
			clr	IE0					; forcibly clear /INT0 interrupt flag
			setb	PX0					; /INT0 is HIGH priority interrupt

			; Init Timer0
			clr	ET0					; disable Timer0 interrupts
			clr	ET1					; disable Timer1 interrupts
			clr	TR0					; Timer0 off
			clr	TR1					; Timer1 off
			clr	TF0					; forcibly clear interrupt flags
			clr	TF1
			orl	TMOD, #00000011b	; Timer0 in Mode 3 (2) 8-bit timers
			anl	TMOD, #NOT(00001100b); GATE0=0; C/T0 = 0
			orl	CKCON, #00001000b	; Timer0 uses system clock as time base
			setb	PT0					; Timer0 interrupt is HIGH priority
			setb	PT1					; Timer1 interrupt is HIGH priority

			; User-level interrupt (IE7) is initialized explicitly by the state
			;  machines
	
			; Init State Machines and Variables
			clr	a						; Init state machines
			mov	SURXST, a			;  RX state variable
			mov	SUTXST, a			;  TX state variable
			mov	BCRHI, a				;  RX bit timer MSB
			mov	BCTHI, a				;  TX bit timer MSB
			clr	SES					; Disable user-level interrupt support
			clr	SREN					; Disable SW UART receiver
			clr	TXBSY					; clear TXBSY indicator
			clr	SRI					; clear RX complete indicator
			clr	STI					; clear TX complete indicator

			ret

;-----------------------------------------------------------------------------
; SW_UART_Enable
;
; The SW_UART is enabled by enabling the interrupt handlers that move the transmit
; and receive state machines from their IDLE states to their corresponding next
; states.  /INT0 transitions the RX state machine from IDLE to START.  Timer1,
; which is called explicitly by the user code (setb TF1), transitions the
; transmit state machine from IDLE/START to TX_LSB.
;
; The user-level interrupt (IE7) is enabled in the state machines themselves
; after polling EIS (external interrupt support).
;
SW_UART_Enable:
			clr	IE0					; clear pending /INT0 interrupts
			setb	TF1					; Force a pending Timer1 interrupt
			setb	EX0					; enable /INT0 interrupts
			clr	ET1					; keep Timer1 interrupts disabled
			setb	TR1					; Enable Timer1

			ret
;-----------------------------------------------------------------------------
; SW_UART_Disable
;
; The SW UART is disabled by disabling all of its state machine interrupts, 
; including the user-level interrupt (IE7), if the status register indicates that
; it's enabled.
SW_UART_Disable:
			clr	EX0					; disable /INT0 interrupts
			clr	ET0					; disable Timer0 interrupts
			clr	ET1					; disable Timer1 interrupts
			jnb	SES, SW_UART_Dis_End; check to see if IE7 use is enabled
			anl	EIE2, #NOT(00100000b); disable IE7 interrupts
SW_UART_Dis_End:
			ret

;-----------------------------------------------------------------------------
; End of file.

END

⌨️ 快捷键说明

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