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

📄 picclock.asm

📁 pic系列单片机得控制程序 主要进行温度采集和转换控制
💻 ASM
字号:
;	Thermometer / clock
;	Jan 2001
;	LCD hookup on RB3 - RB0
;	RS to ground
;	RW on RB4
;	Enable on RB5
;	RA0 input on A/D
;	RA1 output on A/D
;	RA2 input for setting time
;	RA3 input for entering time
;	RA4 input for detecting charging
;	RA7 output high to turn on LCD/temp
;	

	INCLUDE	'M16F62x.inc'
	DEVICE	PROTECT_OFF,  WDT_OFF,  PWRT_ON, BOD_OFF, MCLR_ON, LVP_OFF
	DEVICE	INTRC_OSC_NOCLKOUT
	DEVICE	PIC16F628

porta_buf	equ	0x20
portb_buf	equ	0x21
trisa_buf	equ	0x22
trisb_buf	equ	0x23

W_s	equ	0x24
STATUS_s	equ	0x25

LCD_data	equ	0x26
LCD_Enable	equ	5
LCD_RS	equ	4  
;LCD_RW	equ	tied to ground

TimeH	equ	0x27
TimeM	equ	0x28
TimeS	equ	0x29
TimePos	equ	7	;position on screen where time is drawn

tempF	equ	0x30
tempC	equ	0x31
i	equ	0x32
x	equ	0x33	;16 bit registers.  high comes lower in ram
xlow	equ	0x34
y	equ	0x35
ylow	equ	0x37
t	equ	0x38
tlow	equ	0x39

tempF_f	equ	0x3a	;fractional portion of temperatures
tempC_f	equ	0x3b
TempPos	equ	0x40 + 4
TempPin	equ	1	;pin on port A to sample

waitcounter	equ	0x3c	;file register for wait
DispTempEn	equ	0x40	;non-zero if enabled


	org	0x0000
	BCF	INTCON, GIE
	goto	start

MOVLF	macro	LITERAL, FILE
	movlw	LITERAL
	movwf	FILE
	ENDM
	
BSW	macro	LITERAL
	iorlw	(1<<LITERAL)
	ENDM

BCW	macro	LITERAL
	andlw	((0xff) ^ (1<<LITERAL))
	ENDM
	
MODF	macro	FILE, LITERAL	;FILE mod LITERAL (doesn't work if file/literal > 1)
	movf	FILE, W	;move to working
	MOD	LITERAL
	movwf	FILE	;move back to register
	ENDM

MOD	macro	LITERAL	; W mod LITERAL
	addlw	(256 - LITERAL)	;subtract literal
	BTFSS	STATUS, C	;if negative, add back
	addlw	LITERAL	
	ENDM
	
WAITMACRO	MACRO	LITERAL
	movlw	LITERAL
	call	wait
	ENDM		
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; interrupt handler
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	org	0x0004	;interrupt handler
	movwf	W_s	;save context
	swapf	W_s, F
	swapf	STATUS, W
	movwf	STATUS_s
	
	;main interrupt routine
	movlw	0x80
	addwf	TMR1H	;use half of cycle
	
	;handle time
	incf	TimeS
	MODF	TimeS, 60
	BTFSS	STATUS, Z
	  goto updatetime
	
	;second overflow
	incf	TimeM
	MODF	TimeM, 60
	BTFSS	STATUS, Z
	  goto updatetime
	
	;minutes overflow
	incf	TimeH
	MODF	TimeH, 24

updatetime	call	CheckPower
	;bsf	disptempen,7
	btfss	DispTempEn, 7	;if zero, don't update
	  goto exit_int
	movlf	TimePos, LCD_Data
	call	MoveLCD
	call	DrawTime
	
	movlw	11101111b
	BSF	STATUS, RP0
	andwf	TRISA
	BCF	STATUS, RP0
	movlw	11101111b
	andwf	porta
	movf	timeS, w
	andlw	1
	addlw	1111b
	andlw	10000b
	iorwf	PORTA
	
	;handle temperature

	movlf	TempPos, LCD_Data
	call	MoveLCD
	
	call	sampleTemp
	call	DrawTempF
	
	;exit interrupt
exit_int	BCF	PIR1,TMR1IF	;clear timer overflow
	swapf	STATUS_s, W
	movf	STATUS
	swapf	W_s, W
	retfie
		
	
	
	
;;;;;;;;; start of program
start	
	
	MOVLW	0x07
	MOVWF	CMCON
	movlf	00000000b,porta
	bsf	STATUS, rp0
	movlf	11111111b, trisa
	bcf	STATUS, rp0
 	clrf	DispTempEn
 
waitforpower	WAITMACRO 20
	;call 	CheckPower
	call InitLCD
	;btfss	DispTempEn, 7
	;  goto waitforpower
	
	;configure the LCD
	;call	InitLCD	;done in checkpower
	;set display mode
	;movlf	00000100b, LCD_Data
	;call	ModeLCD

	;call set time routine
	
	
	clrf	DispTempEn
	bsf	DispTempEn, 4
	clrf	TimeH
	clrf	TimeM
	clrf	TimeS
	clrf	TempF
	clrf	TempF_f
	clrf	TempC
	clrf	TempC_f
	;call SetTime
	call ClearLCD
	
	;configure timer interrupt

	call	InitTimer1	;set up timer
	call	CheckPower	;see if it should stay powered up
stable	sleep
	goto stable
	
	



;;;;;;;;;;;;;;;;;;;;;
; subroutines
;;;;;;;;;;;;;;;;;;;;;

InitTimer1	movlw	0x80	;only use half of cycle.  otherwise would be too long of loop
	movwf	TMR1H	;
	clrf	TMR1L	;set initial value
	movlw	00001110b	; 1:1 prescale, oscillator enabled, not synchronized, external clock, not enabled yet
	movwf	T1CON	;set timer1 control register

	BSF	INTCON, PEIE	; open up interrupts
	bsf	STATUS, rp0
	BSF	PIE1, TMR1IE
	bcf	STATUS, rp0
	BSF	INTCON, GIE	
	BSF	T1CON, 0	; start timer
	return



Wait	clrf	waitcounter
	incf	waitcounterincf
	btfss	STATUS, Z
	  goto 	$ - 2
	addlw	0xff	;ms to wait in W (approx)
	btfss	STATUS, Z
	  goto wait
	return

LATCHLCD	MACRO

	movf	portb_buf, w
	BSW	LCD_Enable
	movwf	portb
	nop
	clrw
	addlw	1
	btfss	STATUS,Z
	  goto	$ - 2
	nop
	BCW	LCD_Enable
	movwf	portb
	nop
	nop
	ENDM
	
;;; initiate LCD display
InitLCD	BCF	STATUS, RP1
	BSF	STATUS, RP0	;bank 1
	movlf	11000000b, TRISB	;bit mask for LCD output
	BCF	STATUS, RP0	;bank 0
	
	WAITMACRO	20
	
	movlf	00000011b, portb_buf
	LATCHLCD		
	WAITMACRO	5
	
	movlf	00000011b, portb_buf
	LATCHLCD		
	WAITMACRO	5
	
	movlf	00000011b, portb_buf
	LATCHLCD		
	WAITMACRO	5
	
	movlf	00000010b, portb_buf
	LATCHLCD		
	WAITMACRO	5
		
	;set function byte 1
	movlf	00000010b, portb_buf
	LATCHLCD
	WAITMACRO	2	
	
	;set function byte 0
	movlf	00001000b, portb_buf
	LATCHLCD
	WAITMACRO	2
	
	;clear display
	movlf	00000000b, portb_buf
	LATCHLCD
	WAITMACRO	2
	movlf	00001000b, portb_buf
	LATCHLCD
	WAITMACRO	1
	;reset display
	movlf	00000000b, portb_buf
	LATCHLCD
	WAITMACRO	2
	movlf	00000001b, portb_buf
	LATCHLCD	
	WAITMACRO	2
	return

;;; clear display
ClearLCD
	movlf	00000000b, portb_buf
	LATCHLCD
	WAITMACRO	1
	movlf	00000001b, portb_buf
	LATCHLCD	
	WAITMACRO	1
	return
	
	
;;;; set display mode bits
; bit 2 - on/off
; bit 1 - cursor
; bit 0 - blink

ModeLCD	movlf	00000000b, portb_buf
	LATCHLCD
	
	WAITMACRO	1
	
	movlw	00000111b
	andwf	LCD_Data, W
	iorlw	00001000b
	movwf	portb_buf
	LATCHLCD
	WAITMACRO	1
	
	clrf	portb_buf
	clrf	portb
	return
	
	
;;; LCD_Data is sent as data
DataLCD	swapf	LCD_Data, W
	andlw	00001111b
	BSW	LCD_RS
	movwf	portb_buf
	LATCHLCD
	WAITMACRO	1
	
	movf	LCD_Data, W
	andlw	00001111b
	BSW	LCD_RS
	movwf	portb_buf
	LATCHLCD
	WAITMACRO	1
	
	clrf	portb_buf
	clrf	portb
	return
	
;;;; Move to location
MoveLCD	swapf	LCD_Data, W
	andlw	00000111b
	iorlw	00001000b
	movwf	portb_buf
	LATCHLCD
	
	WAITMACRO	1
	
	movf	LCD_Data, W
	andlw	00001111b
	movwf	portb_buf
	LATCHLCD
	
	WAITMACRO	1
	
	clrf	portb_buf
	clrf	portb
	return
;;; draw temp at current location on LCD
DrawTempF	movf	TempF, W
	movwf	X
	movlw	100
	movwf	Y
	call	Divide	;find 100s
	movf	X, w
	btfsc	STATUS, Z
	  movlw	( ' ' - '0' )
	addlw	'0'
	movwf	LCD_Data
	Call	DataLCD	;draw 100s digit
	movf	T, W	;use remander (10s and 1s
	movwf	X
	movlw	10
	movwf	Y
	Call	Divide
	movf	X, W	;tens
	addlw	'0'
	movwf	LCD_Data
	Call	DataLCD
	movf	T, W
	addlw	'0'	;ones
	movwf	LCD_DATA
	call	DataLCD
	movlw	'.'
	movwf	LCD_DATA
	Call	DataLCD
	movf	TempF_f, W
	addlw	'0'
	movwf	LCD_Data
	Call	DataLCD
	movlw	0xDF	;degree symbol
	movwf	LCD_Data
	Call	DataLCD
	movlw	'F'
	movwf	LCD_Data
	Call	DataLCD
	return
	
	
	


;;; draw time at current location on LCD
DrawTime	
	;draw hours
	movf	TimeH, W
	MOD	12
	btfsc	STATUS, Z
	  movlw	12
	;w contains hour number
	movwf	X
	movlw	10
	movwf	Y
	Call	Divide
	movf	X, W	;move 10s to w
	btfsc	STATUS, Z	;if 0, then set to space
	  movlw	(' ' - '0')
	addlw	'0'	;set to correct digit
	movwf	LCD_Data
	Call	DataLCD
	movf	T, W
	addlw	'0'
	movwf	LCD_Data
	Call	DataLCD
	movlw	':'
	movwf	LCD_Data
	Call	DataLCD
	;minutes
	movf	TimeM, W
	movwf	X
	Call	Divide	;divide by ten
	movf	X, W
	addlw	'0'
	movwf	LCD_Data
	Call	DataLCD
	movf	T, W
	addlw	'0'
	movwf	LCD_Data
	Call	DataLCD
	movlw	':'
	movwf	LCD_Data
	Call	DataLCD
	;seconds
	movf	TimeS, W
	movwf	X
	Call	Divide	;divide by ten
	movf	X, W
	addlw	'0'
	movwf	LCD_Data
	Call	DataLCD
	movf	T, W
	addlw	'0'
	movwf	LCD_Data
	Call	DataLCD
	movlw	' '
	movwf	LCD_Data
	Call	DataLCD
	movf	TimeH, W
	movwf	X
	movlw	12
	movwf	Y
	Call	Divide	;find am/pm
	movlw	'a'
	btfsc	X, 0
	  movlw	'p'
	movwf	LCD_Data
	call	DataLCD
	return




;;; get user input for time
SetTime	clrf	TimeS	;clear time
	clrf	TimeM
	clrf	TimeH
	movlf	00000101b, LCD_Data
	Call	ModeLCD

	clrf	LCD_Data
	Call	MoveLCD

	movlf	TIMEMESSAGE, LCD_Data
	Call	MessageLCD
	
setH	movlf	TimePos + 0x40, LCD_Data
	Call	MoveLCD
	Call	DrawTime
	movlf	( TimePos + 0x40 + 1 ), LCD_Data
	Call	MoveLCD
	Call	getIncrementSetTime
	movwf	X
	addwf	TimeH, W
	MOD	24
	movwf	TimeH
	Call WaitSecond
	BTFSC	X, 0
	  goto	setH
	
	
	
setMh	movlf	TimePos + 0x40, LCD_Data
	Call	MoveLCD
	Call	DrawTime
	movlf	( TimePos + 0x40 + 3 ), LCD_Data
	Call	MoveLCD
	Call	getIncrementSetTime
	movwf	X
	BTFSC	X, 0
	  movlw	10	; add ten if was 1
	addwf	TimeM, W
	MOD	60
	movwf	TimeM
	Call WaitSecond
	BTFSC	X, 0
	  goto	setMh

setM	movlf	TimePos + 0x40, LCD_Data
	Call	MoveLCD
	Call	DrawTime
	movlf	( TimePos + 0x40 + 4 ), LCD_Data
	Call	MoveLCD
	Call	getIncrementSetTime
	movwf	X
	addwf	TimeM, W
	MOD	60
	movwf	TimeM
  	Call WaitSecond
	BTFSC	X, 0
	  goto	setM
	  


setSh	movlf	TimePos + 0x40, LCD_Data
	Call	MoveLCD
	Call	DrawTime
	movlf	( TimePos + 0x40 + 6 ), LCD_Data
	Call	MoveLCD
	Call	getIncrementSetTime
	movwf	X
	BTFSC	X, 0
	  movlw	10	; add ten if was 1
	addwf	TimeS, W
	MOD	60
	movwf	TimeS
  	Call WaitSecond
  	BTFSC	X, 0
	  goto	setSh


setS	movlf	TimePos + 0x40, LCD_Data
	Call	MoveLCD
	Call	DrawTime
	movlf	( TimePos + 0x40 + 7 ), LCD_Data
	Call	MoveLCD
	Call	getIncrementSetTime
	movwf	X
	addwf	TimeS, W
	MOD	60
	movwf	TimeS
    	Call WaitSecond
    	BTFSC	X, 0
	  goto	setS
	
	movlf	00000100b, LCD_Data
	Call	ModeLCD
	return

;;; wait one second
WaitSecond
	WAITMACRO 250
	WAITMACRO 250
	WAITMACRO 250
	WAITMACRO 250
	return
;;; return 1 if pressed + button, and 0 if pressed enter
getIncrementSetTime
	btfsc	PORTA, 2
	  goto	onehigh
	btfsc	PORTA, 3
	  goto	zerohigh
	goto getIncrementSetTime
onehigh	WAITMACRO	50	
	btfsc	PORTA, 2
	  retlw	1
	goto getIncrementSetTime
zerohigh	WAITMACRO	50
	btfsc	PORTA, 3
	  retlw	0
	goto getIncrementSetTime
;;;; divide x by y into register x, remander in T
Divide
	clrf	T
	movlw	8
	movwf	i
divtop	bcf	STATUS, C
	rlf	X, F
	rlf	T, F
	movf	Y, W
	subwf	T, W
	btfsc	STATUS, C
	  movwf	T
	btfsc	STATUS, C
	  bsf	X, 0
	decfsz	i
	  goto 	divtop
	return

;;; more math
;;; add X:Xl + Y:Yl -> X:Xl
add16	clrf	T	;hold carry if needed
	movf	Y+1, W
	addwf	X+1, F
	btfsc	STATUS, C
	  incf	X
	btfsc	STATUS, C
	  incf	T
	movf	Y, W
	addwf	X, F
	movf	T, W
	iorwf	STATUS	;status has C as 1 if carried.
	return

add16m	MACRO	Xm, Ym
	movf	Ym+1, W
	addwf	Xm+1, F
	btfsc	STATUS, C
	  incf	Xm
	movf	Ym, W
	addwf	Xm, F
	ENDM
		
sub16	clrf	T	
	movf	Y+1, W
	subwf	X+1, F
	btfss	STATUS, C	;check for borrow
	  decf	X	;was a borrow
	btfss	STATUS, C	;again
	  incf	T	;T = 1 if borrow
	movf	Y, W
	subwf	X, F	
	movf	T, W
	xorwf	STATUS	; if borrow occured once, C will be 0.  else, 1.  borrow can't happen twice
	return

sub16m	MACRO	Xm, Ym
	movf	Ym+1, W
	subwf	Xm+1, F
	btfsc	STATUS, C
	  decf	Xm
	movf	Ym, W
	subwf	Xm, F
	ENDM
	
; x:x1 by y:y1 into t:t1:x:x1
mult16	clrf	T	;32 bit result is T:Tl:X:Xl
	clrf	T+1
	movlw	16	;16 rounds
	movwf	i
loopmult16	btfss	X+1, 0
	  goto 	noadd
	add16m	T, Y
noadd	bcf	STATUS, C
	rrf	T
	rrf	T+1
	rrf	X
	rrf	X+1
	decfsz	i
	  goto loopmult16
	return
	
MOV16	MACRO	Xm,Ym	;Xm <- Ym
	movf	Ym, W
	movwf	Xm
	movf	Ym+1, W
	movwf	Xm+1
	ENDM
	
;;; get temperature
sampleTemp
	movlw	11111101b	;1 is output, 0 is input
	BSF	STATUS, rp0
	andwf	TRISA
	BCF	STATUS, rp0
	clrf	T+1
	movlf	16, T
	clrf	T+1
presampleloop	movf	porta, W
	andlw	1
	btfss	STATUS, Z
	  bcf	porta, 1	;skip if 0
	btfsc	STATUS, Z	
	  bsf	porta, 1	;skip if 1
	nop
	nop
	nop
	decfsz	T+1
	  goto presampleloop
	decfsz	T
	  goto presampleloop
	  
	clrf	X
	clrf	X+1
	movlf	32, T	; 8192 samples
	clrf	T+1
	
	
	;bcf	porta, 1	;output 0
	;btfsc	porta, 0	;wait until 0
	;goto 	$ - 1
	
	;bsf	porta, 1	;output 1
	;btfss	porta, 0	;wait until 1
	;goto	$ - 1
	
sampleloop	movf	porta, W
	andlw	1
	btfss	STATUS, Z
	  bcf	porta, 1	;skip if 0
	btfsc	STATUS, Z	
	  bsf	porta, 1	;skip if 1
	addwf	X+1, F
	btfsc	STATUS, C
	  incf	X
	decfsz	T+1
	  goto sampleloop
	decfsz	T
	  goto sampleloop
	  
	;sensor measurement in x,x+1
	movf	X+1, W
	movwf	TempF
	movlf	4, Y+1
	clrf	Y
	call 	mult16	;multiply by 4, so upper is 128 - 0 range.

	;correction math	
	movlf	0, Y	;  f(x) = 1.6445 * X  - 48.402
	movlf	156, Y + 1
	call	mult16
	movf	X, w
	movwf	X+1
	movf	T+1, w
	movwf	X
	
	movlf	28, Y	; 29 and 84/256
	movlf	229, Y + 1
	call 	Add16
	
	;now format
	movf	X, W
	movwf	TempF
	movf	x+1,w
	movwf	X
			;range of 0 - 256, 16 interval. 
	movlf	26, Y	;divide lower by 26 to get 0-9 interval
	call	Divide	
	movf	x,w
	movwf	TempF_f
	
	;BSF	STATUS, rp0
	;clrf	TRISA	;turn off output
	;BCF	STATUS, rp0
	bcf	PORTA, 1
	return

CheckPower	movf	PORTA, W
	andlw 	10000000b
	xorwf	DispTempEn, w
	btfsc	STATUS, Z
	  return		;if zero, no change
	xorwf	DispTempEn, w
	btfss	STATUS, Z	;if not set...
	  goto  displayon		;... turn on display...
displayoff	movlw	10111111b
	andwf	PORTA
	movlw	10111111b
	bsf	STATUS, RP0
	andwf	TRISA, F
	movlw	11111111b
	iorwf	TRISB, F
	bcf	STATUS, RP0
	clrf	DispTempEn
	return
	
displayon	movlw	01000000b
	iorwf	PORTA, F
	movlw	10111111b
	bsf	STATUS, RP0
	andwf	TRISA, F
	bcf	STATUS, RP0	
	movlw	01000000b
	iorwf	PORTA, F
	
	call InitLCD
	movlf	00000100b, LCD_Data
	call	ModeLCD
	
	movlf	10000000b, DispTempEn
	return

;;; displayable messages
TIMEMESSAGE	equ	0

	org	0x0400
getbyte	addwf	PCL, F	;message data follows
	db	"Enter current time:", 0
	
	
;;; draw message subroutine.  message index in LCD_Data
MessageLCD	clrf	i
	movlf	03h, PCLATH
	movf	LCD_Data, W
	movwf	i	;location to fetch from
messageloop	movf	i, W
	incf	i
	call	getbyte
	addlw	0
	btfsc	STATUS, Z	;return when 0 in W
	  goto	exitmessage
	movwf	LCD_DATA	; otherwise, display character
	Call	DataLCD
	WAITMACRO	1
	goto messageloop
exitmessage	movlf	00h, PCLATH
	return
	

⌨️ 快捷键说明

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