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

📄 part3.asm

📁 PIC16F84+STH11系统原理图和asm源程序
💻 ASM
📖 第 1 页 / 共 2 页
字号:

; 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 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:

	call	SHT11GetByte
	movf	SHT11Byte,W
	movwf	hi
	call	SendAck		;acknowledge the byte

	; get the least sig byte:

	call	SHT11GetByte
	movf	SHT11Byte,W
	movwf	lo
	call	SendAck		;acknowledge the byte

	call	SHT11GetByte	; gets the checksum (not needed)

	; Send the data as ASCII:
	call	SendAsciiNum

	; Send the terminating CR and LF:
	call	SendCRLF

SHT11TXRXDone
	return

;------end SHT11TXRX--------------------------------------------------

;------begin SHT11GetByte---------------------------------------------
;
; Gets a byte of data from the SHT11. Assumes that the data
; is ready to be sent by the SHT11. Also assumes that _SHT11_DAT has
; been set to input. Also assumes that _SHT11_SCK has been set to low.
; Returns the byte in SHT11Byte.

SHT11GetByte
	; clear SHT11Byte:

	clrf	SHT11Byte

	; set counter to get eight bits

	movlw	8
	movwf	counter

SHT11GetByteLoop
	bsf	PORTA,_SHT11_SCK	;set the clock high to get the next bit
	btfss	PORTA,_SHT11_DAT	;is the next bit a one?
	goto	SHT11GetZeroBit	;no--it's a zero
	bsf	SHT11Byte,0	;if it's a one, set the LSB in SHT11Byte
	goto	SHT11GotBit

SHT11GetZeroBit
	bcf	SHT11Byte,0	;set the LSB to zero in SHT11Byte

SHT11GotBit
	bcf	PORTA,_SHT11_SCK	;set the clock line low again.
	decfsz	counter,F
	goto	SHT11GetNextBit
	goto	SHT11GetByteDone

SHT11GetNextBit
	rlf	SHT11Byte,F	;move the bits over to get the next bit
	goto	SHT11GetByteLoop

SHT11GetByteDone

	return

;------end SHT11GetByte-----------------------------------------------

;------begin SendAck-------------------------------------------------
;
; send the ack. Set the data line as an output:

SendAck
	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

	; now send the ack. Take the data line low.

	bcf	PORTA,_SHT11_DAT
	bsf	PORTA,_SHT11_SCK
	bcf	PORTA,_SHT11_SCK

	; now make the data line an input again.

	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

	return

;------end SendAck---------------------------------------------------

;------begin SendErrorCode-------------------------------------------
;
; send error code back to PC. Error code is 'e' plus a digit. Load
; ASCII value of digit into 'digit' register before calling.

SendErrorCode
	movlw	'e'
	movwf	TXChar
	call	SendAChar
	movf	digit,W
	movwf	TXChar
	call	SendAChar
	call	SendCRLF
	return
	
;------end SendErrorCode---------------------------------------------

;------begin TellTemperature-----------------------------------------

;This subroutine is called when the 't' command is received. Calls
;SHT11TXRX.

TellTemperature

	movlw	3
	movwf	SHT11Byte
	call	SHT11TXRX

	goto	MainLoop

;------end TellTemperature-------------------------------------------

;------begin TellHumidity--------------------------------------------

;This subroutine is called when the 'h' command is received. Calls
;SHT11TXRX.

TellHumidity

	movlw	5
	movwf	SHT11Byte
	call	SHT11TXRX

	goto	MainLoop

;------end TellHumidity----------------------------------------------

;------begin SendCRLF------------------------------------------------
;
; Send the terminating CR and LF:

SendCRLF
	movlw	13
	movwf	TXChar
	call	SendAChar
	movlw	10
	movwf	TXChar
	call	SendAChar
	return

;------end SendCRLF--------------------------------------------------

;------begin SendAsciiNum--------------------------------------------
;
; load lo, hi with 16 bit unsigned num to send

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

; "dosub" is called by the "dodigit" macro defined above.
; Subtract the number in shi/slo from hi/lo until the result
; is negative, incrementing the ascii equivelent each time.

dosub	movlw	'0'-1
	movwf	digit
moresub	incf	digit,F		; increment ASCII character
	movf	slo,w		; subtract current power of 10
	subwf	lo,f
	movf	shi,w
	btfss	STATUS,C
	addlw	1
	subwf	hi,f
	btfsc	STATUS,C	; any carry?
	goto	moresub		; no, keep subtracting

	movf	slo,w		; reverse the last subtraction
	addwf	lo,f
	movf	shi,w
	btfsc	STATUS,C
	addlw	1
	addwf	hi,f
	return

;------end SendAsciiNum----------------------------------------------

;------begin ReportVersion-------------------------------------------

; send a string with the version in it. The string comes from EEPROM
; memory and is null-terminated. The null terminator is not sent. The
; protocol dictates that the string sent is terminated by a CR, which
; is sent. This subroutine is called when the 'v' command is received.

ReportVersion
	bcf	STATUS,RP0
	clrf	EEADR		;the string we want starts at the 
				;beginning of EEPROM memory.

GetNextVersionChar
	bsf	STATUS,RP0
	bsf	EECON1,RD
	bcf	STATUS,RP0
	movf	EEDATA,W
	btfsc	STATUS,Z	;if the character in W is null, don't
                                ;send any more.
	goto	MainLoop

	movwf	TXChar
	call	SendAChar
	incf	EEADR,F
	goto	GetNextVersionChar

;------end ReportVersion---------------------------------------------

;------begin Idle----------------------------------------------------
;
; Idle should be called whenever the chip is waiting for something
; to happen (waiting for a character to be sent or received, for
; example). Here it's not doing anything.

Idle
	return

;------end Idle------------------------------------------------------

;------Main Program--------------------------------------------------

Main

; set up the ports as inputs and outputs as needed.

	bsf	STATUS,RP0	;switch to bank 1
	movlw	0xFF
	movwf	TRISB		;make Port B input
	movlw	0x00
	movwf	TRISA		;make Port A output
	bcf	STATUS,RP0

	clrf	PORTA

	call	SerSetup	;set up serial comm routines & int.

; this main program simply waits for characters to be received, then
; calls the handler for the command indicated by the received character.

MainLoop
	call	GetAChar	;wait for a character

	movf	RXBuff,W	;move the rx char into W
	sublw	't'		;compare with 't' character
	btfsc	STATUS,Z
	goto	TellTemperature	;if t, report the temperature

	movf	RXBuff,W	;move the rx char into W
	sublw	'h'		;compare with 'h' character
	btfsc	STATUS,Z
	goto	TellHumidity	;if h, report the humidity

	movf	RXBuff,W	;move the rx char into W
	sublw	'v'		;compare with 'v' character
	btfsc	STATUS,Z
	goto	ReportVersion	;if v, report the version number

	goto	MainLoop

;------Version EEPROM------------------------------------------------

	org	0x2100
	de	"WxPIC v0.3b (c) 2002 by NK0E",0x0D,0x0A,0x00	; Version 0.3b
	end
	

⌨️ 快捷键说明

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