📄 1620timr.a51
字号:
; This module services the real time interrupt
; It is also responsible for the "real world" thermometers
;
; CHANGE SINCE THE BOOK TEXT WAS FINALIZED: Idle_Time is used by the Operating System
; to override the report times defined in the Endpoint Descriptor. A device driver
; will modify Idle_Time to change the reporting characteristics of a HID device.
; During initialization the OS sets Idle_Time = 0 which turns reporting OFF unless
; a change is detected; an application that starts to poll a HID device will appear
; to hang. While it is possible to write extra PCHost application code to re-enable
; Idle_Time is it simpler to defeat this mechanism by IGNORRING the Idle_Time value.
;
; Get a Real Time interrupt every One millisecond (using SOF interrupt)
;
; We have one task = Read the thermometers
; We will poll the thermometers at 100msec intervals and store the temperatures
; directly in the EP1InBuffer. This way the PCHost will always get the latest
; temperature readings.
;
; The hardware for this example is shown in Figure 9-7.
; We are using Port A for Output
; CLK is on Bit0, DQ is on Bit1 and the thermometers are selected by Bits[7:2]
;
; The registers used in this routine are:
; A = Value written to Port A
; DPTR = Pointer to EP1InBuffer
; R0 = Pointer to PortA_Out
; R1 = Pointer to PortA_Config then PortA_Pins
; R2 = a save register
; R5 = Data to be sent, or received
; R6 = Thermometer selector
; R7 = Bit counter
;
CSEG
ServiceTimerRoutine:
DJNZ Msec_counter, Done ; Only need to check every 100msec
MOV Msec_counter, #100 ; Reinitialize
;
MOV DPTR, #EP1InBuffer
MOV R0, #Low(PortA_Out)
MOV A, #00000100b ; Select pattern
Loop: MOV R6, A
MOV A, #00000001b ; Port A idle state
ORL A, R6
MOVX @R0, A ; Select one of the thermometers
MOV R5, #0AAH ; Get temperature command
CALL SendByte
CALL ReceiveByte
MOV A, R6 ; Get select pattern
CLR C ; Need to zero fill
RLC A ; Rotate pattern
JNZ Loop
; Check for ALARMs
MOV DPTR, #EP1InBuffer ; Current temperature values
MOV R0, #LimitValues ; Low limits
MOV R1, #LimitValues+6 ; High limits
MOV R5, #0 ; Alarm Value
MOV R6, #00000001b ; Alarm mask
MOV R7, #6 ; Counter
LCLoop: MOVX A, @DPTR
CLR C
SUBB A, @R0 ; Check low limit
JNC Over1
MOV A, R5 ; Need to set this ALARM bit
ORL A, R6
MOV R5, A
Over1: MOVX A, @DPTR
CLR C
SUBB A, @R1 ; Check upper limit
JC Over2
MOV A, R5 ; Need to set this ALARM bit
ORL A, R6
MOV R5, A
Over2: MOV A, R6 ; Rotate Alarm mask
RL A
MOV R6, A
INC DPTR ; Update pointers
INC R0
INC R1
DJNZ R7, LCLoop
MOV A, R5 ; Get Alarm byte
MOVX @DPTR, A ; Store in Byte 7 of Report
JMP CreateInputReport ; RETurn via CreateInputReport
SendByte: ; Transmit a byte to a thermometer
MOV R7, #8
SLoop: DEC A
MOVX @R0, A ; Set CLK low
XCH A, R5 ; Get the data to be sent
RRC A ; Put LS bit in Carry
XCH A, R5
MOV ACC.1, C ; Put data bit in DQ
MOVX @R0, A
INC A
MOVX @R0, A ; Set CLK high
DJNZ R7, SLoop
RET
ReceiveByte: ; Receive a byte from a thermometer
MOV R7, #9 ; Actually we get 9 bits and discard bit0
MOV R2, A ; Save A while we reconfigure
MOV R1, #Low(PortA_OE)
MOV A, #11111101b
MOVX @R1, A ; Set bit 1 as input
MOV R1, #Low(PortA_Pins)
MOV A, R2 ; Retreive A
GLoop: DEC A
MOVX @R0, A ; Set CLK low
NOP ; Give thermomemter time to respond
MOVX A, @R1 ; Read the data bit
MOV C, ACC.1 ; Copy DQ into Carry
XCH A, R5
RRC A ; Copy DQ into MSB
XCH A, R5
INC A
MOVX @R0, A ; Set CLK high
DJNZ R7, GLoop
MOV A, R5 ; Get the received temperature
MOVX @DPTR, A ; Save in EPOInBuffer
INC DPTR
Done: RET
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -