📄 2313temp8.asm
字号:
adc XL,BReg
brcc GR1
inc XH ;carry set, so add to XH and point to device
GR1:
sts romoff,XL
sts romoff+1,XH ;used to point to Temp result
rcall ROMatch ;find it on the bus
ldi AReg,ConvertTemp ;convert Temperature command
rcall PutByte
WaiTemp:
rcall GetBit ;wait while busy
brcc WaiTemp ;DS18S20 will pull bus low while busy
rcall DSReset ;reset bus
rcall ROMatch ;select device again
ldi AReg,RdScratch ;read scratchpad command
rcall PutByte
ldi XL,low(TempLSB) ;point to Scratchpad storage
ldi XH,high(TempLSB)
RdMem: ;read in the 1820 scratchpad memory
rcall GetByte ;read result
st X+,AReg ;ScratchL byte
cpi XL,low(TempLSB+9) ;read 9 bytes
brcs RdMem
lds AReg,TempMSB ;Look at TempMSB
sbrs AReg,0 ;if bit 0 (or any bit) is 0
rjmp GExit ;then it's a positive temperature
lds AReg,TempLSB ;otherwise, it's a negative temp
neg AReg ;so do a 2's complement of the temp
sts TempLSB,AReg ;and save before continuing
GExit:
cli
ret
;**********************************************
;* GetTemp *
;* Reads the extended Temperatures from the *
;* DS1820/18S20 device selected in A. *
;* Result stored in the AReg storage area *
;**********************************************
GetTemp:
rcall GetRegs
;Get Temp falls through to calculate the extended temperature value
;***************************************************************************
;* CvtExt converts the extended temperature into degrees C *
;* In the DS18S20 data sheet, this formula is given as: *
;* Temp = Temp_Read - 0.25 + ( count_per_c - count_remain)/count_per_c *
;* where Temp_Read is TempLSB shfted right to eliminate the 0.5C bit *
;* This formula can be simplified.In the DS18S20,count_per_c is always 16 *
;* Temp = Temp_Read - 0.25 + (16-count_remain)/16 *
;* Multiply everything by 16 to simplify the code: *
;* 16*Temp = 16*Temp_Read - 4 + (16-count_remain) which becomes: *
;* 16*Temp = 16*Temp_Read + 12 - count_remain *
;* Multiplying everything by 25 and dividing by 4 eliminates fixed point *
;* numbers. The result is a 16 bit number with the temperature in the *
;* MSB and the fractional (extended) temperature in the LSB *
;* Convert the data in TempLSB to ASCII, add a decimal point in the output *
;* string, then convert ExtTemp to ASCII *
;***************************************************************************
CvtExt:
lds ScratchL,TempLSB;If TempLSB > 1 then LSR
lsr ScratchL ;shift right (divide by 2) to get rid of 0.5C bit
mov MpyLo,ScratchL ;get ready to multiply the value by 16
ldi ScratchL,16 ;TempLSB * 0016
clr ScratchH
clr MpyHi
rcall mpy16u ;16 x 16 multiply
mov MpyHi,ScratchH ;16 bit multiply result in MpyHi:MpyLo
mov MpyLo,ScratchL
CE01: lds ScratchL,TempMSB
sbrc ScratchL,0 ;skip next instruction if TempMSB bit 0 is positive
sen ;TempMSB was negative, so set the negative flag
adiw MpyHi:MpyLo,12 ;16*TempLSB + 12
lds ScratchL,CountRem
lds ScratchH,TempMSB;Get the high order Temperature byte
sbrc ScratchH,0 ;skip next instruction if TempMSB bit 0 is positive
sen ;TempMSB was negative, so set the negative flag
sub MpyLo,ScratchL ;subtract count remaining from low byte of Temp result
brcc CE1
dec MpyHi ;there was a carry, so subtract it from the MSB
CE1:
ldi ScratchL,25 ;multiply result by 25: 25*(16*TempLSB + 12 - CountRemain)
clr ScratchH ;
rcall mpy16u ;result is a 16 bit number.
lsr ScratchH ;divided by 2
ror ScratchL
CE13:
lsr ScratchH ;divided by 4
ror ScratchL
sts TempLSB,ScratchH ;store temperature result
sts ExtTemp,ScratchL ;store extended result
ret
;**********************************************
;* TempCvt *
;* converts the Temperature in degrees C into *
;* an ASCII string *
;**********************************************
TempCvt:
ldi YL, low(Buffer)
ldi YH,high(Buffer)
lds AReg,TempMSB ;Get the high order Temperature byte
tst AReg ;Test high order byte
brmi TS0 ;ones indicate a negative Temperature
ldi AReg,'+'
st Y+,AReg ;Save a + into the buffer
rjmp Cvt2BCD
TS0:
ldi AReg,'-'
st Y+,AReg ;Save a - into the buffer
Cvt2BCD:
lds BReg,TempLSB ;convert temperature to
lds AReg,ExtTemp ;a packed BCD
rcall BIN2BCD16
mov AReg,r14 ;then convert the resulting 4 digits
swap AReg
rcall Put1Asc ;to 4 ASCII characters
mov AReg,r14
rcall Put1Asc
ldi AReg,'.' ;put a decimal point in the buffer
st Y+,AReg
mov AReg,r13
swap AReg
rcall Put1Asc
mov AReg,r13
rcall Put1Asc
ldi AReg,'C'
st Y+,AReg
clr AReg
st Y,AReg
ret
;**********************************************
;* "mpy16u" 16x16 Bit Unsigned Multiplication *
;* This subroutine multiplies the two 16-bit *
;* register variables *
;* ScratchH:ScratchL and BReg:AReg. *
;* The result is placed in: *
;* r21:r20:ScratchH:ScratchL. *
;* The following registers are used: *
;* MpyLo ;multiplicand low byte *
;* MpyHi ;multiplicand high byte *
;* ScratchL ;multiplier low byte *
;* ScratchH ;multiplier high byte *
;* ScratchL ;result byte 0 (LSB) *
;* ScratchH ;result byte 1 *
;* r20 ;result byte 2 *
;* r21 ;result byte 3 (MSB) *
;* r22 ;loop counter *
;* Based on Atmel Application Note AVR 200 *
;**********************************************
mpy16u:
clr r21 ;clear 2 highest bytes of result
clr r20
ldi r22,16 ;init loop counter
lsr ScratchH
ror ScratchL
m16u_1:
brcc noad8 ;if bit 0 of multiplier set
add r20,MpyLo ;add multiplicand Low to byte 2 of res
adc r21,MpyHi ;add multiplicand high to byte 3 of res
noad8:
ror r21 ;shift right result byte 3
ror r20 ;rotate right result byte 2
ror ScratchH ;rotate result byte 1 and multiplier High
ror ScratchL ;rotate result byte 0 and multiplier Low
dec r22 ;decrement loop counter
brne m16u_1 ;if not done, loop more
ret
;**********************************************
;* Bin2BCD16,16-bit Binary to BCD conversion *
;* converts a 16 bit binary number to *
;* a 5 digit packed BCD number *
;* number to convert in BReg:AReg *
;* returns MSB in ScratchH, LSB in ScratchL *
;* The following registers are used: *
;* r13 BCD value digits 1 and 0 *
;* r14 BCD value digits 3 and 2 *
;* r15 BCD value digit 4 *
;* AReg r16 binary value Low byte *
;* BReg r17 binary value High byte *
;* ScratchL r18 loop counter *
;* ScratchH r19 temporary value *
;* Based on Atmel Application Note AVR 204 *
;**********************************************
.equ AtBCD0 =13 ;address of r13
.equ AtBCD2 =15 ;address of r14
bin2BCD16:
ldi ScratchL,16 ;Init loop counter
clr r15 ;clear result (3 bytes)
clr r14
clr r13
clr ZH ;clear ZH (not needed for AT90Sxx0x)
bBCDx_1:
lsl AReg ;shift input value
rol BReg ;through all bytes
rol r13
rol r14
rol r15
dec ScratchL ;decrement loop counter
brne bBCDx_2 ;if counter not zero
ret ;routine exit point
bBCDx_2:
ldi r30,AtBCD2+1 ;Z points to result MSB + 1
bBCDx_3:
ld ScratchH,-Z ;get (Z) with pre-decrement
subi ScratchH,-$03 ;add 0x03
sbrc ScratchH,3 ;if bit 3 not clear
st Z,ScratchH ;store back
ld ScratchH,Z ;get (Z)
subi ScratchH,-$30 ;add 0x30
sbrc ScratchH,7 ;if bit 7 not clear
st Z,ScratchH ;store back
cpi ZL,AtBCD0 ;done all three?
brne bBCDx_3 ;loop again if not
rjmp bBCDx_1
;**********************************************
;* Convert the LSB nibble of AReg to an ASCII *
;* Hex character and stores it in the buffer *
;* addressed by Y. Exit with Y pointing to *
;* the next empty buffer location *
;**********************************************
Put1Asc:
andi AReg,$0f
cpi AReg,$0a
brmi PTASC1
ldi BReg,7
add AReg,BReg
PTASC1:
ldi BReg,$30
add AReg,BReg
st Y+,AReg
ret
;**********************************************
;* Converts the contents of AReg to 2 ASCII *
;* Hex characters, storing them in the buffer *
;* addressed by Y. Exit with Y pointing to *
;* the next empty buffer location *
;**********************************************
Put1Hex:
mov r0,AReg
lsr AReg
lsr AReg
lsr AReg
lsr AReg
rcall Put1Asc
mov AReg,r0
rcall Put1Asc
ret
;**********************************************
;* ParseIn Scans incoming serial port data *
;* and parses the commands: *
;* R: Outputs ROM count & ROM IDs to ser port *
;* Tn : Outputs the Temperature for sensor n *
;* Vn : Outputs the register contents and *
;* temperature for sensor n *
;**********************************************
ParseIn:
cli ;block off interrupts
rcall SerIn ;look at the incoming character
andi AReg,$5f ;convert to uppercase
cpi AReg,'R' ;ROM IDs found
brne VData
mov AReg,ROMCount ;it was an R - send # of devices found
ldi BReg,$30
add AReg,BReg ;convert to an ASCII number
rcall SerOut ;send it out the serial port
rcall OutCRLF
rcall ShowROM ;send the ROM ID array out the serial port
rjmp PExit
VData:
cpi AReg,'V' ;Verbose - sends DS1820 register contents & temp
brne TTest ;exit if it isn't a Verbose Data command
rcall SerIn ;read number of device
subi AReg,$30 ;convert it to binary
cp AReg,ROMCount ;make sure it's <= to the device count
brcc PExit ;exit otherwise
rcall GetRegs ;read in the register values
rcall ShowData ;convert it to ASCII and send out the serial port
rcall CvtExt ;calculate the extended temperature value
rjmp TT1 ;finish off by displaying the temperature
TTest:
cpi AReg,'T' ;Calculate and send temperatire
brne PExit
rcall SerIn ;read number of device
subi AReg,$30 ;convert it to binary
cp AReg,ROMCount ;make sure it's <= to the device count
brcc PExit ;exit otherwise
rcall GetTemp ;Get the extended temperature and
TT1:
rcall TempCvt ;convert it to ASCII
ldi XL,low(Buffer) ;point to the converted Scratch buffer
ldi XH,high(Buffer)
SenDat:
ld AReg,X+
tst AReg ;output strings are NULL terminated
breq SDEnd ;end of buffer; send a CRLF
rcall SerOut ;send the buffer data until a 0 is detected
rjmp SenDat
SDEnd:
rcall OutCRLF
PExit:
sei ;enable interrupts
reti
;**********************************************
;* Code ends here. *
;**********************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -