LIST ; P16C84.INC Standard Header File, Version 1.00 Microchip Technology, Inc. NOLIST ; This header file defines configurations, registers, and other useful bits of ; information for the PIC16C84 microcontroller. These names are taken to match ; the data sheets as closely as possible. ; Note that the processor must be selected before this file is ; included. The processor may be selected the following ways: ; 1. Command line switch: ; C:\ MPASM MYFILE.ASM /PIC16C84 ; 2. LIST directive in the source file ; LIST P=PIC16C84 ; 3. Processor Type entry in the MPASM full-screen interface ;========================================================================== ; ; Revision History ; ;========================================================================== ;Rev: Date: Reason: ;1.00 10/31/95 Initial Release ;========================================================================== ; ; Verify Processor ; ;========================================================================== IFNDEF __16C84 MESSG "Processor-header file mismatch. Verify selected processor." ENDIF ;========================================================================== ; ; Register Definitions ; ;========================================================================== W EQU H'0000' F EQU H'0001' ;----- Register Files------------------------------------------------------ INDF EQU H'0000' TMR0 EQU H'0001' PCL EQU H'0002' STATUS EQU H'0003' FSR EQU H'0004' PORTA EQU H'0005' PORTB EQU H'0006' EEDATA EQU H'0008' EEADR EQU H'0009' PCLATH EQU H'000A' INTCON EQU H'000B' OPTION_REG EQU H'0081' TRISA EQU H'0085' TRISB EQU H'0086' EECON1 EQU H'0088' EECON2 EQU H'0089' ;----- STATUS Bits -------------------------------------------------------- IRP EQU H'0007' RP1 EQU H'0006' RP0 EQU H'0005' NOT_TO EQU H'0004' NOT_PD EQU H'0003' Z EQU H'0002' DC EQU H'0001' C EQU H'0000' ;----- INTCON Bits -------------------------------------------------------- GIE EQU H'0007' EEIE EQU H'0006' T0IE EQU H'0005' INTE EQU H'0004' RBIE EQU H'0003' T0IF EQU H'0002' INTF EQU H'0001' RBIF EQU H'0000' ;----- OPTION Bits -------------------------------------------------------- NOT_RBPU EQU H'0007' INTEDG EQU H'0006' T0CS EQU H'0005' T0SE EQU H'0004' PSA EQU H'0003' PS2 EQU H'0002' PS1 EQU H'0001' PS0 EQU H'0000' ;----- EECON1 Bits -------------------------------------------------------- EEIF EQU H'0004' WRERR EQU H'0003' WREN EQU H'0002' WR EQU H'0001' RD EQU H'0000' ;========================================================================== ; ; RAM Definition ; ;========================================================================== __MAXRAM H'AF' __BADRAM H'07', H'30'-H'7F', H'87' ;========================================================================== ; ; Configuration Bits ; ;========================================================================== _CP_ON EQU H'3FEF' _CP_OFF EQU H'3FFF' _PWRTE_ON EQU H'3FFF' _PWRTE_OFF EQU H'3FF7' _WDT_ON EQU H'3FFF' _WDT_OFF EQU H'3FFB' _LP_OSC EQU H'3FFC' _XT_OSC EQU H'3FFD' _HS_OSC EQU H'3FFE' _RC_OSC EQU H'3FFF' TITLE "datalog" LIST P=PIC16C84 ; define processor type ; This program uses the pic16c84 to read the temperature of the room and ; sends the results to a PC or workstation via the com port. The time interval ; between A/D conversions can be determined from the PC by sending a byte out the ; com port or by using the timer in the micro to do a conversion every 10 minutes ; (or whatever delay is set to). It then converts it to BCD and then ascii and ; sends it off to the PC at 1200 baud (or whatever baud rate is chosen). Note: The ; use of the micro's timer or the PC to determine conversion rate is chosen by a jumper ; on the board. Note: RD NOT and CS NOT on the A/D are tied low temp equ 0x10 ; temperature from A/D converter bitcnt equ 0x11 ; count while sending 8 bit temperature serially out equ 0x12 ; value used to change the serial data out mcnt equ 0x13 ; minute counter scnt equ 0x14 ; second counter fcnt equ 0x15 ; fraction of a second counter ten equ 0x16 ; BCD tens digit one equ 0x17 ; BCD ones digit frac equ 0x18 ; BCD fractional digit TX equ 0x02 ; bit #2 (0-7) used to receive data from PC RX equ 0x03 ; bit #3 (0-7) used to send data to PC WRAD equ 0x01 ; bit #1 (0-7) WR NOT, A/D begin conversion on high to low INTRAD equ 0x00 ; bit #0 (0-7) INTR NOT, A/D signal end of conversion on high to low LED equ 0x04 ; bit #4 (0-7) yellow led will blink if micro is working org 0 goto start org 0x20 ; converts the number in temp to a BCD value. When temp = 0 the BCD representation will start ; at 50.0 deg F for better resolution in the 50 - 100 degree range. Each bit is worth 0.2 deg F. ; ten holds the tens digit, one holds the ones digit, and frac holds the tenths digit bcd movlw 0x05 ; when the A/D reads 0 the temperature is 50.0 deg F movwf ten clrf one clrf frac tinc incf ten,1 ; add one to the tens digit movlw d'50' ; subtract the equivalent of 10 deg F from temp subwf temp,1 ; temp = temp - 50 btfsc STATUS,C ; if result is positive goto tinc ; then go back and subtract 50 again decf ten,1 ; else put the tens value back the way it was addwf temp,1 ; and put temp back the way it was oinc incf one,1 ; add one to the ones digit movlw d'5' ; subtract the equivalent of 1 deg F from temp subwf temp,1 ; temp = temp - 5 btfsc STATUS,C ; if result is positive goto oinc ; then go back and subtract 5 again decf one,1 ; else put the ones value back the way it was addwf temp,1 ; and put temp back the way it was finc movlw 0x02 ; each bit = 0.2 degrees F addwf frac,1 ; therefore add 2 to the tenths digit movlw 0x01 ; sub 0.2 deg F from temp subwf temp,1 ; therefore sub 1 from temp btfsc STATUS,C ; if result is positive goto finc ; then go back and subtract it agian movlw 0x02 ; else put the tenths value back the way it was subwf frac,1 ; each bit = 0.2 degrees F return ; the conversion is done (temp = FF; i.e., 0 - 1) ; waits for a start byte to be sent from the PC wait btfsc PORTA,TX ; if TX is still in the stop bit state goto wait ; stay in the loop call delay ; some ammount of delay is needed to make call delay ; sure that the TX line from the PC is back in the call delay ; stop bit before continuing. Probably don't need call delay ; all 5 of the delay statements but what the hell call delay ; space is cheep. goto pre ; else go to beginning of A/D read section ; sends the character (stored in temp) to the max232 chip at whatever baud rate the ; prescaler determines sbyte call delay ; start at correct time nop ; sync with the other bits nop nop bcf PORTA,RX ; send start bit call seto ; set out to the proper value for the first bit movlw 0x08 ; set the bit counter for sending the temperature byte movwf bitcnt ; to 8 bits again call delay ; wait until time to send next bit call dout ; send the next bit decfsz bitcnt,1 ; if all 8 bits haven't been sent goto again ; then send the next bit call delay ; wait until time to send the stop bit nop ; sync with the other bits nop nop bsf PORTA,RX ; send the stop bit return ; writes the value in "out" to PORTA to update the serial data out line ; of PORTA is connected to the serial out (TX) dout movf out,0 ; w = out movwf PORTA ; PORTA = w (puts bit 1 of out on output pin) rrf temp,1 ; rotate temperature byte for next time in the loop seto movlw 0xff movwf out ; out = all ones (needed because CS NOT should be high) btfss temp,0 ; check LSB of temperature bcf out,RX ; if zero clear RX bit of out return ; delay until time for next bit to be sent out (depends on baud rate) delay btfss INTCON,T0IF ; check if timer0 has overflowed goto delay ; if no wait for it to overflow bcf INTCON,T0IF ; if yes clear bit and return tag return ; Beginnig of main routine Note: baud rate and timing will be off if a 2.4576Mhz XTAL isn't used) start bsf STATUS,RP0 ; bank 1 (upper half of memory on pic16c84) movlw b'00000101' ; set PORTA ; RA2 input from RS232 driver (from PC) ; RA3 output to RS232 driver (to PC) ; RA1 output to A/D (WR NOT - begin conversion) ; RA0 input from A/D (INTR NOT - conversion done) ; RA4 output to yellow LED (if blinking then micro is working) movwf TRISA movlw b'11111111' ; PORTB set for inputs (8 bits from A/D) movwf TRISB movlw b'11000100' ; prescaler set for div by 32 & use Fosc/4 as clk movwf OPTION_REG bcf STATUS,RP0 ; bank 0 (lower half of memory on pic16c84) movlw b'00001010' ; set both outputs of PORTA to default condition movwf PORTA ; (stop bit on RS232 and A/D not doing conversion) clrf TMR0 ; clear timer0 bcf INTCON,T0IF ; clear timer0 overflow bit ; decide wether to take data every so often (10 min for example) or to send the ; data to the PC only after the PC sends a byte out the serial port btfsc PORTA,TX ; if RS232 TX is in stop bit state goto wait ; then wait for the start bit before sending temp to PC movlw d'1' ; read temperature every 0 minutes movwf mcnt ; minute counter mlp movlw d'60' ; count for 60 seconds per minute movwf scnt ; second counter slp movlw d'76' ; 75 overflows a second with the prescaler at /32 movwf fcnt ; fraction of a second counter (1/75 of a sec) movf PORTA,0 ; w = porta (following three lines blinkes the LED) xorlw b'00010000' ; compliment the LED bit movwf PORTA ; update porta (porta = w) flp call delay ; wait until correct time decfsz fcnt,1 ; decrement the fractional counter goto flp ; if not zero stay in loop for 1 second decfsz scnt,1 ; decrement the seconds counter goto slp ; if not zero stay in loop for 1 minutes decfsz mcnt,1 ; decrement the minute counter goto mlp ; if not zero stay in loop for some # of minutes pre bsf STATUS,RP0 ; bank 1 movlw b'11000000' ; set prescaler to /2 for 1200 baud movwf OPTION_REG bcf STATUS,RP0 ; bank 0 ; read A/D and store value in temp bcf PORTA,WRAD ; reset A/D nop ; small time delay (shouldn't be needed) bsf PORTA,WRAD ; tell A/D to begin conversion adw btfsc PORTA,INTRAD ; check if A/D conversion is done goto adw ; if not wait until it's done movf PORTB,0 ; read A/D 8 bit value (w = temperature) movwf temp ; put temperature in variable temp call bcd ; convert temperature to BCD numbers ; send the ascii bytes out the serial port movlw 0x30 ; add 30H to a digit (0 - 9) to convert to ascii addwf ten,0 ; w = tens digit (ascii representation) movwf temp ; temp = tens digit call sbyte ; send byte out the serial port movlw 0x30 ; add 30H to a digit (0 - 9) to convert to ascii addwf one,0 ; w = ones digit (ascii representation) movwf temp ; temp = ones digit call sbyte ; send byte out the serial port movlw 0x2e ; w = hex code for decimal point movwf temp ; temp = w call sbyte ; send byte out the serial port movlw 0x30 ; add 30H to a digit (0 - 9) to convert to ascii addwf frac,0 ; w = tenths digit (ascii representation) movwf temp ; temp = tenths digit call sbyte ; send byte out the serial port movlw 0x0d ; w = hex code for carrage return movwf temp ; temp = w call sbyte ; send byte out the serial port movlw 0x0a ; w = hex code for line feed movwf temp ; temp = w call sbyte ; send byte out the serial port goto start ; start over end