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

📄 16f84.asm

📁 pic系列单片机得控制程序 主要进行温度采集和转换控制
💻 ASM
📖 第 1 页 / 共 3 页
字号:
; check to see if we need to send the stop bit:

	movf	BitCount,F
	btfsc	STATUS,Z	;18th cycle
	goto	SendStopBit

; if we get to here, we're in the middle of sending. Send the next
; bit: (16 cycles to get to the next instruction from the start of
; the interrupt).

	rrf	TXChar,F	;doing rrf on TXChar puts the
	btfss	STATUS,C	;least significant bit in the
	goto	SendZero	;carry flag.
	nop
	bsf	PORTA,_SER_OUT	;if carry is set, send a one.
	goto	EndDoBit	;PORTA,1 is set on the 24th cycle

SendZero
	bcf	PORTA,_SER_OUT	;otherwise, send a zero. (24th cycle)
	nop			;nop's are for taking the same time
	nop			;to get to reloading TMR0 as for when
				;a one is sent.

; Decrement the bit counter.

EndDoBit
	decf	BitCount,F

; reload TMR0 for the next interrupt, and
; go to the end of the interrupt routine.

	movlw	_BitTxDelay	
	movwf	TMR0		;29th cycle
	goto	Restore


; Here we need to send the stop bit, turn off the TMR0 interrupt,
; turn on the external interrupt, and set the SerStatus register
; flags appropriately.

SendStopBit
	nop
	nop
	nop
	bsf	PORTA,_SER_OUT	;no. Send the stop bit. (24th cycle)
	bsf	SerialReg,3	;set the "sending stop bit" flag

; reload TMR0 for the next interrupt, and
; go to the end of the interrupt routine.

	movlw	_StopTxDelay
	movwf	TMR0		;27th cycle
	goto	Restore

; we're completely done sending or receiving. Clean up.

Done	movlw	b'00010000'	;set bits in INTCON to enable
	movwf	INTCON		;external interrupt
	movlw	b'00000001'
	andwf	SerialReg,F	;clear the busy bits in SerialReg
	goto	Restore

;------end DoBit-----------------------------------------------------

;------Subroutine SendChar-------------------------------------------
;
; This is not called by the interrupt handler. Rather, it activates 
; the interrupts needed to send it. Put the character to be sent in
; the TXChar file register before calling this subroutine.
;

SendChar
	
; send the start bit:

	bcf	PORTA,_SER_OUT

; set the SerStatus to indicate that the routines are busy sending
; a character:

	movlw	b'00000110'
	movwf	SerialReg

; load up TMR0 so it overflows at the right time.

	nop			;for timing
	movlw	_BitTxDelay
	movwf	TMR0		;5th cycle after write to PORTA

; clear the external interrupt flag, disable the external interrupt,
; and enable the TMR0 interrupt.

	movlw	b'10100000'
	movwf	INTCON

; set the BitCount for the eight bits to send:

	movlw	8
	movwf	BitCount

	return

;------end SendChar--------------------------------------------------

;------begin GetAChar------------------------------------------------

GetAChar
	call	Idle
	btfss	SerialReg,0	;wait for a character to be received
	goto	GetAChar
	bcf	SerialReg,0
	return

;------end GetAChar--------------------------------------------------

;------begin SendAChar-----------------------------------------------

SendAChar
	call	SendChar

WaitToFinish
	call	Idle
	btfsc	SerialReg,1	;wait for the character to be sent
	goto	WaitToFinish
	return

;------end SendAChar-------------------------------------------------

;------Subroutine WaitMS---------------------------------------------
;
; WaitMS is an approximate millisecond delay. It assumes a 4 MHz
; oscillator, meaning instructions are executed at a rate of 1 MHz.
; I got the timing info (number of cycles per instruction) from the
; Microchip PIC16F84 data sheet.

; the call to this subroutine takes 2 cycles to execute.

WaitMS
	movlw	248		;1 cycle
	movwf	MSDelay		;1 cycle
	nop			;1 cycle--these nops are added to 
	nop			;1 cycle  make the total number of
	nop			;1 cycle  instructions executed in
				;         the routine to be 1000.
				;the nop instruction simply does 
				;nothing except take time to execute.

; The loop below takes four cycles for every time through except the
; last, when it takes five (including the time needed to execute the
; return). So, the total number of instructions executed in getting
; to and returning from this subroutine is:
;
;        2 to get here
;    +   2 to set the MSDelay value
;    +   3 for the nops
;   + 247*4 for the first 247 times through the loop
;    +   5 for the last time through the loop and to return
;   --------
;    = 1000

RepeatWaitMS
	nop			;1 cycle
	decfsz	MSDelay,F	;1 cycle if not zero, 2 if zero
	goto	RepeatWaitMS	;2 cycles
	return			;2 cycles

;------end WaitMS----------------------------------------------------


;------begin WaitDit-------------------------------------------------
;
; WaitDit is a delay loop which times dits.

WaitDit
	movf	DitLen,W
	movwf	DitLoopIndex

RepeatWaitDit
	call	WaitMS
	decfsz	DitLoopIndex,F
	goto	RepeatWaitDit

	return

;------end WaitDit---------------------------------------------------

;------begin WaitDah-------------------------------------------------
;
; WaitDah is a delay loop which times dahs. Dahs are three times the
; length of dits.

WaitDah
	call WaitDit
	call WaitDit
	call WaitDit
	return

;------end WaitDah---------------------------------------------------

;------begin WaitWordDit---------------------------------------------
;
; WaitWordDit is a delay loop which times dits based on intercharacter
; spacing.

WaitWordDit
	movf	DitWordLen,W
	movwf	DitLoopIndex

RepeatWaitWordDit
	call WaitMS
	decfsz	DitLoopIndex,F
	goto	RepeatWaitWordDit
	return

;------end WaitWordDit-----------------------------------------------

;------begin WaitWordDah---------------------------------------------
;
; WaitWordDah is a delay loop which times dahs based on intercharacter
; spacing. WordDahs are three times the length of Worddits.

WaitWordDah
	call WaitWordDit
	call WaitWordDit
	call WaitWordDit
	return

;------end WaitWordDah-----------------------------------------------

;------begin SendCWDit-----------------------------------------------
;
; actually sends the dit over the LED

SendCWDit
	bcf	PORTA,_INVCW	; turn on LED
	call	WaitDit		; wait the appropriate amount of time
	bsf	PORTA,_INVCW	; turn off LED
	call	WaitDit		; wait for space between dits and dahs
	return

;------end SendCWDit-------------------------------------------------

;------begin SendCWDah-----------------------------------------------
;
; actually sends the dah over the LED

SendCWDah
	bcf	PORTA,_INVCW	; turn on LED
	call	WaitDah		; wait the appropriate amount of time
	bsf	PORTA,_INVCW	; turn off LED
	call	WaitDit		; wait for space between dits and dahs
	return

;------end SendCWDah-------------------------------------------------

;------begin SendCWDigit---------------------------------------------
;
; load CharToSend with the ASCII value of the character to be sent.

SendCWDigit
	movlw	0x30		;we'll subtract 48 from the ASCII value
				;since we're only interested in characters
				;starting with ASCII 48 (zero)
	subwf	CharToSend,F	;subtract 48 from the next character ASCII value

	movlw	HIGH Table	;preset the PCLATH for the computed goto
	movwf	PCLATH

	movf	CharToSend,W	;now put the value in W for table lookup
	call	Table		;return value will be the bit string to send
	movwf	CharToSend	;store the bit string in CharToSend

; find the Start bit. Start looking at bit 6 and continue down until a 1 is encountered.
; the rest of the bits to send will follow.

	rlf	CharToSend,F	; get rid of bit 7.
	movlw	0x08		; load the bit counter so we know when we're out of bits.
	movwf	CharBitCount
	bcf	STATUS,C

FindCWStartBit
	decf	CharBitCount,F	; count the bits we check.
	rlf	CharToSend,F	; look at the next bit. is it a 1? if so, that's our start bit.
	btfss	STATUS,C
	goto	FindCWStartBit

SendCWBit
	decfsz	CharBitCount,F	; check to see if we're out of bits to send.
	goto	SendNextCWBit
	goto	DoneSendingCWBits

SendNextCWBit
	rlf	CharToSend,F	; get the next bit. 1 is a dah, 0 is a dit.
	btfss	STATUS,C
	goto	SendADit
	goto	SendADah

SendADit
	call	SendCWDit	; send the dit
	goto	SendCWBit	; do the next dit or dah

SendADah
	call	SendCWDah	; send the dah
	goto	SendCWBit	; do the next dit or dah

DoneSendingCWBits

; wait a dah length for the next character.

	call	WaitWordDah	; use the intercharacter spacing

	return

;------end SendCWChar------------------------------------------------

;------begin SendCWAsciiNum--------------------------------------------
;
; load lo, hi with 16 bit unsigned num to send. Sends the resulting
; ASCII sequence of digits in CW via the LED.

SendCWAsciiNum
	dodigit	10000
	movf	digit,W
	movwf	CharToSend
	call	SendCWDigit
	dodigit	1000
	movf	digit,W
	movwf	CharToSend
	call	SendCWDigit
	dodigit	100
	movf	digit,W
	movwf	CharToSend
	call	SendCWDigit
	dodigit	10
	movf	digit,W
	movwf	CharToSend
	call	SendCWDigit
	movf	lo,w		; ls byte is already correct
	addlw	'0'		; convert to ascii
	movwf	CharToSend
	call	SendCWDigit
	return			; done

;------end SendCWAsciiNum----------------------------------------------

;------begin SHT11TXRX-----------------------------------------------
;
; Sends a byte command to the SHT11 temp/humidity sensor and retrieves
; a two-byte response. Sends the response back to the PC as an ASCII
; string representation of the number.
;
; Put the byte to send in SHT11Byte before calling this routine. 

SHT11TXRX

	;make _SHT11_DAT an output

	bsf	STATUS,RP0	;switch to bank 1
	bcf	TRISA,_SHT11_DAT	;make Port A data line an output
	bcf	STATUS,RP0	;switch back to bank 0

	;send the Transmission Start sequence:

	bsf	PORTA,_SHT11_DAT	;set the data line high
	bsf	PORTA,_SHT11_SCK	;take the clock line high
	bcf	PORTA,_SHT11_DAT	;take the data line low
	bcf	PORTA,_SHT11_SCK	;take the clock line low
	bsf	PORTA,_SHT11_SCK	;take the clock line high again
	bsf	PORTA,_SHT11_DAT	;set the data line high again
	
	;load up the counter to loop through the eight bits to send:

	movlw	8
	movwf	counter

SHT11SendBitLoop
	bcf	PORTA,_SHT11_SCK	;take the clock line low

	btfss	SHT11Byte,7	;is the next bit to send a one?
	goto	SHT11SendZero	;nope. Go send a zero.
	bsf	PORTA,_SHT11_DAT	;if it's a one, send it.
	goto	SHT11SendBit

SHT11SendZero
	bcf	PORTA,_SHT11_DAT	;set the data line to zero

SHT11SendBit
	bsf	PORTA,_SHT11_SCK	;take the clock line high to send

	rlf	SHT11Byte,F	;move the next bit into MSB

	decfsz	counter,F	;dec the counter and check for zero.
	goto	SHT11SendBitLoop	;if not zero, more bits to send

	bcf	PORTA,_SHT11_SCK	;take the clock line low

	;no more bits to send. Set the data line to be an input and
	;wait for the ack from the SHT11:

	bsf	STATUS,RP0	;switch to bank 1
	bsf	TRISA,_SHT11_DAT	;make Port A data line an input
	bcf	STATUS,RP0	;switch back to bank 0

	; now look for an ack (SHT11 pulls data line low--should
	; happen on the next rise of the SCK line). If it doesn't
	; happen, return an 'e' and quit.

	bsf	PORTA,_SHT11_SCK

SHT11WaitAck
	btfss	PORTA,_SHT11_DAT
	goto	SHT11GotAck

	;if we don't get an ack, quit, send an 'e1' for error and return.

	movlw	'1'
	movwf	digit
	call	SendErrorCode
	goto	SHT11TXRXDone

	; we got an Ack. Get ready for the data to be returned. take
	; the clock line low, and then wait for the data line to be
	; pulled low again.

SHT11GotAck
	bcf	PORTA,_SHT11_SCK

	; now wait for the data. It takes approximately 210 ms for
	; the temperature measurement, or 55 ms for the humidity
	; measurement, so we'll wait up to 255 ms before giving up.

	movlw	255
	movwf	counter

SHT11WaitData
	btfss	PORTA,_SHT11_DAT
	goto	SHT11DataReady
	call	WaitMS
	decfsz	counter,F
	goto	SHT11WaitData

	;if we don't get the data, quit, send an 'e2' error and return.

	movlw	'2'
	movwf	digit
	call	SendErrorCode
	goto	SHT11TXRXDone

SHT11DataReady

	; get the most sig byte:

⌨️ 快捷键说明

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