; AVR demo by Randy Ott - 5/1/98 ; Exercise Dallas Semiconductor DS1820 digital thermometer ; Blink result on LEDs on port B ; Power, ground, and data I/O are on port D pins for simplicity ; DS1820A.ASM version combines read/write into one function ; Display degrees C * 2 in BCD (1/2 degree steps) ; Binary to BCD conversion borrowed from Atmel app.note AVR204 ; Changed clock crystal to 9.8304 MHz. 5-4-98 ; Send temperature reading out UART at 9600 bps .nolist ;Suppress listing of include file .include "2313def.inc" ;Define chip particulars .list ;***** Global register variables .def wreg =R16 ;General use working register .def timeout =R17 ;Timeout value passed to subroutine .def inreg =R18 ;Data register for reading DS1820 .def outreg =R19 ;Data register for writing DS1820 .def temphi =R20 ;High byte of temperature reading .def templo =R21 ;Low byte of temperature reading .def loopcnt =R22 ;Loop counter for serial read/write .def decimal =R25 ;Place holder for 0.5 or 0.0 readout ;***** Resisters used for binary to BCD conversion .def fbin =r23 ;8-bit binary value .def tBCDL =r23 ;BCD result MSD .def tBCDH =r24 ;BCD result LSD ;***** Port pin definitions .equ sync =3 ;Scope sync on PD3 .equ dsvcc =4 ;Vcc connected to PD4 .equ dsio =5 ;I/O pin connected to PD5 .equ dsgnd =6 ;Gnd connected to PD6 ;***** Other equates .equ T0PRE =0b00000010 ;Timer 0 prescaler 4MHz / 8 = 2uS .equ BAUD =64 ;9600 bps at 9.8304 MHz. .cseg ;***** Interrupt vectors .org 0 rjmp reset ;Reset Vector .org INT0addr ;External Interrupt0 Vector reti .org INT1addr ;External Interrupt1 Vector reti .org ICP1addr ;Input Capture1 Interrupt Vector reti .org OC1addr ;Output Compare1 Interrupt Vector reti .org OVF1addr ;Overflow1 Interrupt Vector reti .org OVF0addr ;Overflow0 Interrupt Vector rjmp t0int .org URXCaddr ;UART Receive Complete Interrupt Vector reti .org UDREaddr ;UART Data Register Empty Interrupt Vector reti .org UTXCaddr ;UART Transmit Complete Interrupt Vector reti .org ACIaddr ;Analog Comparator Interrupt Vector reti ; Program entry point on reset reset: ldi wreg,RAMEND out SPL,wreg ;Init Stack Pointer ldi wreg,0xFF ;Make all port B pins outputs out DDRB,wreg sbi DDRD,dsvcc ;Make Vcc pin an output sbi DDRD,dsio ;Make I/O pin an output sbi DDRD,dsgnd ;Make ground pin an output sbi DDRD,sync ;Make sync pin an output cbi PORTD,dsgnd ;Pull ground pin low sbi PORTD,dsvcc ;Turn on Vcc to device ldi wreg,0b00000010 ;Enable Timer 0 interrupt out TIMSK,wreg ldi wreg,BAUD out UBRR,wreg ;Set baud rate generator ldi wreg,0b00001000 out UCR,wreg ;Enable UART tx w/o interrupt sei ;Enable interrupts main: sbi PORTD,sync ;Provide scope sync for debugging rcall resetds ;Reset DS1820 device cbi PORTD,sync brts present ;Device found ldi wreg,0xFF ;Turn off all LEDs out PORTB,wreg rjmp main present: ldi outreg,0xCC ;Skip ROM command rcall writeds ldi outreg,0x44 ;Convert T command rcall writeds twait: rcall readds ;Check for conversion complete tst inreg ;Returns all zeros while busy breq twait rcall resetds ;Reset again ldi outreg,0xCC ;Skip ROM command rcall writeds ldi outreg,0xBE ;Read scratchpad command rcall writeds rcall readds ;Read temperature LSB mov templo,inreg ;Store reading rcall readds ;Read temperature MSB mov temphi,inreg ;Store reading rcall resetds ;Don't read the rest ldi decimal,'0' ;Assume nn.0 result clc ;Clear carry bit ror templo ;Divide reading by 2 brcc nohalf ;See if LSB was set ldi decimal,'5' ;If so, get ready to put out nn.5 nohalf: mov fbin,templo ;Copy reading for BCD conversion rcall bin2bcd8 ;Convert it ldi wreg,' ' ;Print a space rcall putchar mov wreg,fbin ;Get packed BCD result swap wreg ;Move MSB to lower nibble andi wreg,0x0f ;Strip off upper bits subi wreg,-'0' ;Add offset for digits 0-9 rcall putchar ;Send to terminal mov wreg,fbin ;Get packed BCD result back andi wreg,0x0f ;Strip off upper bits subi wreg,-'0' ;Add offset for digits 0-9 rcall putchar ;Send to terminal ldi wreg,'.' ;Send a dot rcall putchar ;Send to terminal mov wreg,decimal ;Get last digit rcall putchar ;Send to terminal ldi wreg,0x0D ;Send carraige return rcall putchar ;Send to terminal com fbin ;Invert result for LED display out PORTB,fbin rjmp main ;Do it again..... ;***** Read/write a byte to the DS1820. Write 0xFF to read device readds: ldi outreg,0xFF ;Set output to all ones for reading writeds: ldi loopcnt,8 ;Send 8 bits to device rwloop: sbi DDRD,dsio ;Make I/O pin an output cbi PORTD,dsio ;Pull I/O pin low ldi timeout,-1 ;Make timer 0 count 2uS rcall delay ror outreg ;Get bit from output register into carry brcc wrzero ;If clear, leave line low cbi DDRD,dsio ;Otherwise let pull up go high wrzero: ldi timeout,-12 ;Make timer 0 count 12 * 0.8uS rcall delay ;Give pin time to go high if needed clc ;clear carry, assume bit is a zero sbic PIND,dsio ;Sample input pin sec ;Set carry if pin was high ror inreg ;Get bit into input register ldi timeout,-61 ;Make timer 0 count 61 * 0.8uS rcall delay ;Fill out time slot cbi DDRD,dsio ;Let line go back high ldi timeout,-1 ;Make timer 0 count 2uS rcall delay ;Leave I/O pin high for recovery dec loopcnt ;Decrement bit counter brne rwloop ;Loop for all 8 bits ret ;***** Reset DS1820 and read presence pulse, return result in T ; Modified for new timer to obtain long delays needed resetds: sbi DDRD,dsio ;Make I/O pin an output cbi PORTD,dsio ;Pull I/O pin low ldi timeout,0 ;Make timer 0 count 256 * 0.8uS rcall delay ldi timeout,0 ;Make timer 0 count 256 * 0.8uS rcall delay ldi timeout,-100 ;Make timer 0 count 100 * 0.8uS rcall delay sbi PORTD,dsio ;Pull I/O pin high cbi DDRD,dsio ;Make I/O pin an input ldi timeout,-111 ;Make timer 0 count 111 * 0.8uS rcall delay clt ;Assume device not present sbis PIND,dsio ;Check for presence pulse set ;Indicate result in T ldi timeout,0 ;Make timer 0 count 256 * 0.8uS rcall delay ldi timeout,0 ;Make timer 0 count 256 * 0.8uS rcall delay ldi timeout,-100 ;Make timer 0 count 100 * 0.8uS rcall delay ret ;***** Timer 0 overflow interrupt handler t0int: set ;Set T flag ldi wreg,0 ;Timer 0 off out TCCR0,wreg ;Stop timer reti ;Done, return ;***** Delay n*2 microseconds using timer 0, delay time passed in timeout delay: in wreg,SREG ;Save status register push wreg ; cpi timeout,-1 ;Special case ; breq skipit out TCNT0,timeout clt ;Clear T ldi wreg,T0PRE ;Timer 0 prescaler out TCCR0,wreg ;Run timer dwait: brtc dwait ;Wait for timer 0 interrupt to set T skipit: pop wreg ;Restore status register out SREG,wreg ret ;*************************************************************************** ;* ;* "bin2BCD8" - 8-bit Binary to BCD conversion ;* ;* This subroutine converts an 8-bit number (fbin) to a 2-digit ;* BCD number (tBCDH:tBCDL). ;* ;* Number of words :6 + return ;* Number of cycles :5/50 (Min/Max) + return ;* Low registers used :None ;* High registers used :2 (fbin/tBCDL,tBCDH) ;* ;* Included in the code are lines to add/replace for packed BCD output. ;* ;*************************************************************************** bin2bcd8: clr tBCDH ;clear result MSD bBCD8_1:subi fbin,10 ;input = input - 10 brcs bBCD8_2 ;abort if carry set ; inc tBCDH ;inc MSD ;--------------------------------------------------------------------------- ; ;Replace the above line with this one ; ;for packed BCD output subi tBCDH,-$10 ;tBCDH = tBCDH + 10 ;--------------------------------------------------------------------------- rjmp bBCD8_1 ;loop again bBCD8_2:subi fbin,-10 ;compensate extra subtraction ;--------------------------------------------------------------------------- ; ;Add this line for packed BCD output add fbin,tBCDH ;--------------------------------------------------------------------------- ret ;***** Write a byte from wreg to UART putchar: sbis USR,UDRE ;Is UART transmitter ready? rjmp putchar ;If not, wait out UDR,wreg ;Put character to UART ret