Formatteringen tycker jag aldrig blir bra på forumet, men det är väl hyfsat i alla fall.
Kod: Markera allt
list p=16F628A ; list directive to define processor
#include <p16F628A.inc> ; processor specific variable definitions
errorlevel -302 ; suppress message 302 from list file
__CONFIG _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT
; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file.
; See data sheet for additional information on configuration word settings.
;***** VARIABLE DEFINITIONS (examples)
;#define SHTDATA PORTB, 5
;#define SHTSCK PORTB, 6
#define LED PORTA, 4
; example of using Shared Uninitialized Data Section
;INT_VAR UDATA_SHR
INT_VAR UDATA
w_temp RES 1 ; variable used for context saving
status_temp RES 1 ; variable used for context saving
LCDBL equ 2
hiByte RES 1
loByte RES 1
nibtosend res 1
d1 RES 1
d2 RES 1
;SHT11
counter RES 1
SHT11BYTE RES 1
DIGIT RES 1
;SENDERRORCODE RES 1
;WAITMS RES 1
;SHT11GETBYTE RES 1
MSDelay RES 1 ;register for WaitMS timing
HI RES 1
LO RES 1
;SENDASCIINUM RES 1
;SENDACK RES 1
;SENDCRLF RES 1
count RES 2 ; counter
advalue RES 1 ; Value from A/D
advalue_temp RES 1 ; Value from A/D, temp
temp1 RES 1 ; Temp
temp2 RES 1 ;
digit1 RES 1 ; Digit 1-4
digit2 RES 1 ;
digit3 RES 1 ;
digit4 RES 1 ;
LCDEnable equ 3 ; The LCD enable pin on Port B
LCDRS equ 4; The LCD R/S pins on Port B
_SHT11_SCK equ 6 ;clock line for SHT11 sensor;(PORTA) (ändra till PORTB)
_SHT11_DAT equ 5 ;data line for SHT11 sensor;(PORTA)
;**********************************************************************
RESET_VECTOR CODE 0x000 ; processor reset vector
goto main ; go to beginning of program
INT_VECTOR CODE 0x004 ; interrupt vector location
goto INTERRUPT
MAIN CODE
INTERRUPT
movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
; isr code can go here or be located as a call subroutine elsewhere
movf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents
retfie ; return from interrupt
main
; remaining code goes here
;A/D off
movlw 0x07
movwf CMCON
;Set Tris
clrw
banksel TRISA
clrf TRISA
clrf TRISB
bcf status, rp0
;init LCD
;http://www.piclist.com/techref/io/lcd/4b16x2lcd-ab.htm
CALL LONGDLY
CALL LCDFUN ; sets the LCD's function to 4 bit, 2 line, 5x7 font
CALL LONGDLY
CALL LCDDISP ; Turns on the display and cursor
CALL LONGDLY
CALL LCDENT ; sets auto increment right after write (like a typewriter)
CALL LCDCLR
;Backlight on
bsf PORTB, LCDBL
;LED off
BCF LED
;Welcome message
movlw "H"
movwf LCDByte
CALL LCDCHAR
movlw "E"
movwf LCDByte
CALL LCDCHAR
movlw "L"
movwf LCDByte
CALL LCDCHAR
movlw "L"
movwf LCDByte
CALL LCDCHAR
movlw "O"
movwf LCDByte
CALL LCDCHAR
TellTemperature
;movlw 0x03
;movwf SHT11Byte
;call SHT11TXRX
;goto mainloop
;Blink
BSF LED
call Delay0_3
BCF LED
mainloop
goto mainloop
;------begin SHT11TXRX-----------------------------------------------
;
; Sends a byte command to the SHT11 temp/humidity sensor and retrieves
; a two-byte response. Sends the response back to the PC as an ASCII
; string representation of the number.
;
; Put the byte to send in SHT11Byte before calling this routine.
; http://www.njqrp.org/digitalhomebrewing/pic-wx/part3.asm
SHT11TXRX
;make _SHT11_DAT an output
bsf STATUS,RP0 ;switch to bank 1
bcf TRISB,_SHT11_DAT ;make Port A data line an output
bcf STATUS,RP0 ;switch back to bank 0
;send the Transmission Start sequence:
bsf PORTB,_SHT11_DAT ;set the data line high
bsf PORTB,_SHT11_SCK ;take the clock line high
bcf PORTB,_SHT11_DAT ;take the data line low
bcf PORTB,_SHT11_SCK ;take the clock line low
bsf PORTB,_SHT11_SCK ;take the clock line high again
bsf PORTB,_SHT11_DAT ;set the data line high again
;load up the counter to loop through the eight bits to send:
movlw 8
movwf counter
SHT11SendBitLoop
bcf PORTB,_SHT11_SCK ;take the clock line low
btfss SHT11Byte,7 ;is the next bit to send a one?
goto SHT11SendZero ;nope. Go send a zero.
bsf PORTB,_SHT11_DAT ;if it's a one, send it.
goto SHT11SendBit
SHT11SendZero
bcf PORTB,_SHT11_DAT ;set the data line to zero
SHT11SendBit
bsf PORTB,_SHT11_SCK ;take the clock line high to send
rlf SHT11Byte,F ;move the next bit into MSB
decfsz counter,F ;dec the counter and check for zero.
goto SHT11SendBitLoop ;if not zero, more bits to send
bcf PORTB,_SHT11_SCK ;take the clock line low
;no more bits to send. Set the data line to be an input and
;wait for the ack from the SHT11:
bsf STATUS,RP0 ;switch to bank 1
bsf TRISB,_SHT11_DAT ;make Port A data line an input
bcf STATUS,RP0 ;switch back to bank 0
; now look for an ack (SHT11 pulls data line low--should
; happen on the next rise of the SCK line). If it doesn't
; happen, return an 'e' and quit.
bsf PORTB,_SHT11_SCK
SHT11WaitAck
btfss PORTB,_SHT11_DAT
goto SHT11GotAck
;if we don't get an ack, quit, send an 'e1' for error and return.
movlw '1'
movwf digit
call SendErrorCode
goto SHT11TXRXDone
; we got an Ack. Get ready for the data to be returned. take
; the clock line low, and then wait for the data line to be
; pulled low again.
SHT11GotAck
bcf PORTB,_SHT11_SCK
; now wait for the data. It takes approximately 210 ms for
; the temperature measurement, or 55 ms for the humidity
; measurement, so we'll wait up to 255 ms before giving up.
movlw 254
movwf counter
SHT11WaitData
btfss PORTB,_SHT11_DAT
goto SHT11DataReady
call WaitMS
decfsz counter,F
goto SHT11WaitData
;if we don't get the data, quit, send an 'e2' error and return.
movlw '2'
movwf digit
call SendErrorCode
goto SHT11TXRXDone
SHT11DataReady
; get the most sig byte:
call SHT11GetByte
movf SHT11Byte,W
movwf hi
call SendAck ;acknowledge the byte
; get the least sig byte:
call SHT11GetByte
movf SHT11Byte,W
movwf lo
call SendAck ;acknowledge the byte
call SHT11GetByte ; gets the checksum (not needed)
; Send the data as ASCII:
call SendAsciiNum
; Send the terminating CR and LF:
;call SendCRLF
SHT11TXRXDone
return
;------end SHT11TXRX--------------------------------------------------
;------begin SendErrorCode-------------------------------------------
;
; send error code back to PC. Error code is 'e' plus a digit. Load
; ASCII value of digit into 'digit' register before calling.
SendErrorCode
movlw 'e'
; movwf TXChar
; call SendAChar
movf digit,W
; movwf TXChar
; call SendAChar
; call SendCRLF
return
;------end SendErrorCode---------------------------------------------
;------begin SHT11GetByte---------------------------------------------
;
; Gets a byte of data from the SHT11. Assumes that the data
; is ready to be sent by the SHT11. Also assumes that _SHT11_DAT has
; been set to input. Also assumes that _SHT11_SCK has been set to low.
; Returns the byte in SHT11Byte.
SHT11GetByte
; clear SHT11Byte:
clrf SHT11Byte
; set counter to get eight bits
movlw 8
movwf counter
SHT11GetByteLoop
bsf PORTB,_SHT11_SCK ;set the clock high to get the next bit
btfss PORTB,_SHT11_DAT ;is the next bit a one?
goto SHT11GetZeroBit ;no--it's a zero
bsf SHT11Byte,0 ;if it's a one, set the LSB in SHT11Byte
goto SHT11GotBit
SHT11GetZeroBit
bcf SHT11Byte,0 ;set the LSB to zero in SHT11Byte
SHT11GotBit
bcf PORTB,_SHT11_SCK ;set the clock line low again.
decfsz counter,F
goto SHT11GetNextBit
goto SHT11GetByteDone
SHT11GetNextBit
rlf SHT11Byte,F ;move the bits over to get the next bit
goto SHT11GetByteLoop
SHT11GetByteDone
return
;------end SHT11GetByte-----------------------------------------------
;------begin SendAck-------------------------------------------------
;
; send the ack. Set the data line as an output:
SendAck
bsf STATUS,RP0 ;switch to bank 1
bcf TRISB,_SHT11_DAT ;make Port A data line an output
bcf STATUS,RP0 ;switch back to bank 0
; now send the ack. Take the data line low.
bcf PORTA,_SHT11_DAT
bsf PORTA,_SHT11_SCK
bcf PORTA,_SHT11_SCK
; now make the data line an input again.
bsf STATUS,RP0 ;switch to bank 1
bsf TRISB,_SHT11_DAT ;make Port A data line an input
bcf STATUS,RP0 ;switch back to bank 0
return
;------end SendAck---------------------------------------------------
;------begin SendAsciiNum--------------------------------------------
;
; load lo, hi with 16 bit unsigned num to send
SendAsciiNum
;Hi byte
movf hi
movwf advalue
call conv
movf digit1
addlw 0x30 ;Convert to ASCII
movwf LCDByte
CALL LCDCHAR
movf digit2
addlw 0x30 ;Convert to ASCII
movwf LCDByte
CALL LCDCHAR
movf digit3
addlw 0x30 ;Convert to ASCII
movwf LCDByte
CALL LCDCHAR
;Lo byte
movf lo
movwf LCDByte
CALL LCDCHAR
return ; done
;------end SendAsciiNum----------------------------------------------
;movlw d'239'
;movwf advalue
;Convert read value
;Value is in advalue
conv
movfw advalue ;W=advalue
movwf advalue_temp ;advalue_temp=W
movlw d'100' ;W=100
movwf temp2 ;temp2=100
call conv_ad
movf temp1,w ;digit1 in temp1, move to W
movwf digit1 ;W to digit1
movfw advalue ;W=advalue
movwf advalue_temp ;advalue_temp=W
movlw d'10' ;W=100
movwf temp2 ;temp2=100
call conv_ad
movf temp1,w ;digit1 in temp1, move to W
movwf digit2 ;W to digit2
movfw advalue ;W=advalue
movwf advalue_temp ;advalue_temp=W
movlw d'1' ;W=100
movwf temp2 ;temp2=100
call conv_ad
movf temp1,w ;digit1 in temp1, move to W
movwf digit3 ;W to digit2
goto adconv_done
conv_ad
clrf temp1 ;Clear temp1
;clrf digit_no
movwf temp2 ;temp2=W
conv_ad_l
subwf advalue_temp, 1 ;W-adtemp, result in advalue_temp
btfss status, 0 ;Check if less than 0
goto adconv_done ;if so we're done
incf temp1 ;increase counter
movf temp2 ;W=temp2 = subtract value
subwf advalue,1
;movfw temp2 ;W=temp2
;movf temp2,w
goto conv_ad_l
adconv_done
return
;------Subroutine WaitMS---------------------------------------------
;
; WaitMS is an approximate millisecond delay. It assumes a 4 MHz
; oscillator, meaning instructions are executed at a rate of 1 MHz.
; I got the timing info (number of cycles per instruction) from the
; Microchip PIC16F84 data sheet.
; the call to this subroutine takes 2 cycles to execute.
WaitMS
movlw 248 ;1 cycle
movwf MSDelay ;1 cycle
nop ;1 cycle--these nops are added to
nop ;1 cycle make the total number of
nop ;1 cycle instructions executed in
; the routine to be 1000.
;the nop instruction simply does
;nothing except take time to execute.
; The loop below takes four cycles for every time through except the
; last, when it takes five (including the time needed to execute the
; return). So, the total number of instructions executed in getting
; to and returning from this subroutine is:
;
; 2 to get here
; + 2 to set the MSDelay value
; + 3 for the nops
; + 247*4 for the first 247 times through the loop
; + 5 for the last time through the loop and to return
; --------
; = 1000
RepeatWaitMS
nop ;1 cycle
decfsz MSDelay,F ;1 cycle if not zero, 2 if zero
goto RepeatWaitMS ;2 cycles
return ;2 cycles
;------end WaitMS----------------------------------------------------
;LCD routines
;http://www.piclist.com/techref/io/lcd/4b16x2lcd-ab.htm
LCDADD ; makes LCDAdd the current LCD Address
nop
BCF PORTB,LCDRS
movf LCDAdd, 0
movwf LCDByte
bsf LCDByte, 7
CALL LCDBYTE
bsf PORTB,LCDRS
nop
nop
RETURN
LCDENT ; Entry Mode set - currently set to move cursor to right after each write
nop
BCF PORTB, LCDRS
movlw b'00000110'
movwf LCDByte
CALL LCDBYTE
BSF PORTB,LCDRS
nop
nop
RETURN
LCDDISP ; turns on display, cursor off
nop
BCF PORTB,LCDRS
movlw b'00001100'
movwf LCDByte
CALL LCDBYTE
BSF PORTB,LCDRS
nop
nop
RETURN
LCDFUN ; sets up the LCD function byte, for 4 bit control, 2 lines, standard font
nop
movlw d'2'
movwf nibToSend
BCF PORTB, LCDRS ; we're sending a command, so R/S must be lo
CALL SENDNIB ; due to 4 bit operation, we have to resend the first nibble
CALL SHORTDLY
movlw b'00101000'
movwf LCDByte
CALL LCDBYTE
BSF PORTB, LCDRS
nop
nop
RETURN
LCDCLR ; clears the entire display
clrf LCDAdd
nop
movlw d'1'
movwf LCDByte
BCF PORTB, LCDRS ; 'cause we are doing a command, set the R/S line lo
CALL LCDBYTE ; writes LCDByte to the LCD
CALL LONGDLY ; Clearing the LCD takes ages, so a larger delay is needed
bsf PORTB, LCDRS ; set the R/S line, ready for characters
RETURN
LCDCHAR
;use this for displaying characters only, NOT control chars
;keeps track of cursor colation, and word wraps if necessary
movf LCDAdd, 0
sublw h'50'
btfsc STATUS, Z
RETURN
CALL LCDBYTE
incf LCDAdd, 1
; check if we have hit the end of the top line
movlw d'16'
subwf LCDAdd, 0
btfsc STATUS, Z ; skip if not zero
GOTO LCDLINE2 ; must go to new line
RETURN
LCDLINE2
; here we must go to the new line
movlw b'01000000'
movwf LCDAdd
CALL LCDADD
RETURN
LCDBYTE; sends a byte to the LCD, in 4bit fashion
; responsible for breaking up the byte to send into high and low nibbles
; and dumps them to LCD
;NOT responsible for the status of the LCDRS line, nor the major delays
; IN: LCDByte - distructive OUT: hiByte, loByte
clrf hiByte ; clears the vars, to prevent bugs
clrf loByte
bcf STATUS,0 ; get rif of any carry which could screw up the bitshifts
rlf LCDByte, 1
rlf hiByte
rlf LCDByte, 1
rlf hiByte
rlf LCDByte, 1
rlf hiByte
rlf LCDByte, 1
rlf hiByte
movf LCDByte, 0
movwf loByte
swapf loByte, 1
movf hiByte,0
movwf nibToSend
CALL SENDNIB
movf loByte,0
movwf nibToSend
CALL SENDNIB
CALL SHORTDLY ; blocks until most instructions are done
RETURN
SENDNIB; responsible for sending nibble commands to the LCD.
;IN: nibToSend - non-distructive
clrf W ; clears W
movf nibToSend, 0
movwf PORTA
nop
bsf PORTB, LCDEnable; pulse the LCD Enable high
nop
nop
bcf PORTB, LCDEnable ; lower LCD Enable
nop
nop
RETURN
SHORTDLY ; around 50us
;217 cycles
movlw 0x48
movwf d1
SHORTDLY_0
decfsz d1, f
goto SHORTDLY_0
;4 cycles (including call)
return
LONGDLY ; 25ms delay
;92153 cycles
movlw 0xFE
movwf d1
movlw 0x48
movwf d2
LONGDLY_0
decfsz d1, f
goto $+2
decfsz d2, f
goto LONGDLY_0
;3 cycles
goto $+1
nop
;4 cycles (including call)
return
LCDBACKSPACE ; acts like a backspace
movf LCDAdd,0
andlw b'11111111'
btfsc STATUS, Z ; skip if not zero
RETURN ; already at end, so ignore backspace
sublw h'40'
btfsc STATUS, Z ; skip if at start of 2nd line
GOTO LCDBSTARTBOTLINE ; correct for moveing up to new line
decf LCDAdd, 1;
CALL LCDADD ; move back one
movlw d'32' ; wipe the current char
movwf LCDByte
CALL LCDBYTE
CALL LCDADD
RETURN
LCDBSTARTBOTLINE ; correct for moveing up to new line
movlw d'15'
movwf LCDAdd
CALL LCDADD ; put us at 15
movlw d'32'
movwf LCDByte
CALL LCDBYTE
RETURN
Delay0_3
;299993 cycles
movlw 0x5E
movwf d1
movlw 0xEB
movwf d2
Delay_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_0
;3 cycles
goto $+1
nop
;4 cycles (including call)
return
; initialize eeprom locations
EE CODE 0x2100
DE 0x00, 0x01, 0x02, 0x03
END ; directive 'end of program'