📄 fan.asm
字号:
; PC temperature activated fan controller; use a ds1620 digital temperature sensor to ; control a PWM fan motor.; Also output the temperature as rs232; Peter Lynch August 1998 LIST P=12c509 include "C:\picde\P12c509.inc"STALL EQU .4 ; minimum (stall speed) for fanMAX EQU .32 ; maximum PWM value for fanCARRY EQU 0 ; carry bit (0) in STATUS byteZERO EQU 2 ; zero bit (2) in STATUS byteSERIAL EQU 5FAN EQU 4; pin assignments for ds1620RST EQU 2 ; Reset to ds1620CLK EQU 1 ; clockDQ EQU 0 ; Data in/out pin (sometimes ; configured as an input)OPMASK EQU B'11000000'WMASK EQU B'00001000' ; all bits output (except GP3) ; GP4 controls a LED ; GP5 serial outputRMASK EQU B'00001001' ; Set bit 0 as inputPWM1 EQU 0ch ; number of counts of "1"PWM2 EQU 0dh ; number of counts of "0"TEMP EQU 0eh ; temp byte from DS1620TX_BYTE EQU 0F ; store transmitted byteTX_COUNT EQU 10h ; transmitted bit countDELAY EQU 11h ; time delayLOOPS EQU 12hHALF_SER EQU 13h ; used to convert hex to ASCIISPEED EQU 14h ; fan speedD0 EQU 15h ; used for BCD conversionD1 EQU 16hD2 EQU 17h ORG 1ff ; for 12c508 DW 0c40 ORG 3ff ; for 12c509 DW 0c70 ORG 0 ; start of main code MOVWF OSCCAL MOVLW OPMASK OPTION MOVLW WMASK TRIS GPIO CLRF TEMP CLRF TX_BYTE; initialise the DS1620 MOVLW 0ch ; Write Config command CALL DS1620W MOVLW B'00001001' ; one-shot mode CALL DS1620W MOVLW MAX MOVWF SPEED BSF GPIO, FAN ; start the fan, max speed ; this is the main loop.; start the DS1620 temperature conversion,; wait 1 second (poutput PWM data during this time; read the temperature and send it as RS232 dataNEXT MOVLW 0eeh ; start conversion command CALL DS1620W MOVLW .239 ; 240 loops @ 4mSec / loop ~ 1 second MOVWF LOOPS ; number of loops before sending ; temperature data as rs232SETFAN CALL fan DECFSZ LOOPS, F GOTO SETFAN ; now we've had 10 seconds of PWM, during which the DS1620 has done; a temperature conversion, read the result CALL DSTEMP ; stores result in TEMP MOVLW .63 ANDWF TEMP, W CALL WIDTH ; convert temp. into fan speed MOVWF SPEED; anti-stall measure, set the fan to MAX while we output the data BSF GPIO, FAN movlw 'T' call ser_out movlw 'e' call ser_out movlw 'm' call ser_out movlw 'p' call ser_out movlw ' ' call ser_out; convert the temperature to BCD MOVF TEMP, W call B2BCD movlw '0' addwf D0, W call ser_out movlw '0' addwf D1, W call ser_out movlw '0' addwf D2, W call ser_out movlw ' ' call ser_out movlw 'F' call ser_out movlw 'a' call ser_out movlw 'n' call ser_out movlw ' ' call ser_out; convert the fan speed to decimal MOVF SPEED, W call B2BCD movlw '0' addwf D0, W call ser_out movlw '0' addwf D1, W call ser_out movlw '0' addwf D2, W call ser_out movlw .10 ; end it with a newline call ser_out GOTO NEXT; routine to control the speed of the fan.; convert the temperature into a count, between STALL and 64; use this to define the number of 1's to output in the; next PWM burst. The remaining bits are 0's to make a ; constant 64 cycles.fan movf SPEED, W ; subtract the pulse-width value from 32, put the remainder; in the PWM2 counter. This is the amount of time to output a '0' movwf PWM1 movlw .33 ; always have one cycle of 0 movwf PWM2 movf SPEED, W subwf PWM2, F fan1 BSF GPIO, FAN CALL PWM_DEL DECFSZ PWM1, F GOTO fan1 fan0 BCF GPIO, FAN CALL PWM_DEL DECFSZ PWM2, F GOTO fan0 RETURN ; routine to wait a time within the PWM routine.; define the time quantum for a 0 or 1 bit; It gives a loop time of 8mSec with a delay value of 40(d)PWM_DEL MOVLW .40 MOVWF DELAYDEL1 DECFSZ DELAY, F GOTO DEL1 RETURN ; routine to write serial output at 38400 Baud; (using 4MHz clock, 1uS/instruction); equals 26 clock cycles per bitser_out movwf TX_BYTE call bitout_1; nop; nop nop movlw 8 movwf TX_COUNT ser_loop call bitout rrf TX_BYTE, f decfsz TX_COUNT, f goto ser_loop call bitout_0 nop nop nop nop return ; routine to output a bit with the correct timing for 38400Bd @ 4Mhz; this bit-sense works with a MAX-232 (i.e. inverted)bitout btfsc TX_BYTE, 0 goto bitout_0bitout_1 nop nop bcf GPIO, SERIAL goto bit_donebitout_0 bsf GPIO, SERIALbit_done movlw 4 movwf DELAYbit_delay decfsz DELAY, f goto bit_delay return; routine to output to a DS1620; the byte to send is in the W registerDS1620W BSF GPIO, CLK MOVWF TX_BYTE MOVLW 8 MOVWF TX_COUNT BSF GPIO, RST ; enable talking to the device ; write loopDS_WL BCF GPIO, CLK BCF GPIO, DQ BTFSC TX_BYTE, 0 BSF GPIO, DQ NOP BSF GPIO, CLK ; clock the bit on rising edge RRF TX_BYTE, F DECFSZ TX_COUNT, F GOTO DS_WL BCF GPIO, RST RETURN ; routine to read temperature data from a ds1620; first send a READ TEMP command, then without; dropping RST (this is why we can't use a DS1620W call); read the resulting temperature data; throw away the LSB, keep the 8 bit (degree) temeratureDSTEMP MOVLW 0aah ; read TEMP command MOVWF TX_BYTE MOVLW 8 MOVWF TX_COUNT BSF GPIO, RST ; enable talking to the device ; write loopDS_TL BCF GPIO, CLK BCF GPIO, DQ BTFSC TX_BYTE, 0 BSF GPIO, DQ NOP BSF GPIO, CLK ; write the bit on rising edge RRF TX_BYTE, F DECFSZ TX_COUNT, F GOTO DS_TL; here the READ TEMP command has been sent, get the 9 bits of; temperature data (discard the LSB to get just degrees); but first, have to set the DQ pin as an input MOVLW RMASK ; set the DQ pin as input TRIS GPIO MOVLW 9 MOVWF TX_COUNT DS_RL RRF TEMP, F bcf TEMP, 7 BCF GPIO, CLK NOP BTFSC GPIO, DQ BSF TEMP, 7 BSF GPIO, CLK DECFSZ TX_COUNT, F GOTO DS_RL BCF GPIO, RST MOVLW WMASK ; reset DQ as output TRIS GPIO return ; routine to get pulse width from temperature value; The higher the temperature, the greater the fan speed; we want, so the wider the pulse (and the higher the ; value returned from width).; called with the temperature in celcius (up to 32); return values between the minimum stalling speed of; the fan to 32WIDTH ADDWF PCL, F RETLW STALL ; 0 RETLW STALL ; 1 RETLW STALL ; 2 RETLW STALL ; 3 RETLW STALL ; 4 RETLW STALL ; 5 RETLW STALL ; 6 RETLW STALL ; 7 RETLW STALL ; 8 RETLW STALL ; 9 RETLW STALL ; 10 RETLW STALL ; 11 RETLW STALL ; 12 RETLW STALL ; 13 RETLW STALL ; 14 RETLW STALL ; 15 RETLW STALL+.1 ; 16 RETLW STALL+.2 ; 17 RETLW STALL+.3 ; 18 RETLW STALL+.4 ; 19 RETLW STALL+.5 ; 20 RETLW STALL+.6 ; 21 RETLW STALL+.7 ; 22 RETLW STALL+.8 ; 23 RETLW STALL+.9 ; 24 RETLW STALL+.10 ; 25 RETLW STALL+.11 ; 26 RETLW STALL+.12 ; 27 RETLW STALL+.13 ; 28 RETLW STALL+.14 ; 29 RETLW STALL+.15 ; 30 RETLW STALL+.16 ; 31 RETLW STALL+.17 ; 32 RETLW STALL+.18 ; 33 RETLW STALL+.19 ; 34 RETLW STALL+.20 ; 35 RETLW STALL+.21 ; 36 RETLW STALL+.22 ; 37 RETLW STALL+.23 ; 38 RETLW STALL+.24 ; 39 RETLW STALL+.25 ; 40 RETLW STALL+.26 ; 41 RETLW STALL+.27 ; 42 RETLW MAX ; 43 RETLW MAX ; 44 RETLW MAX ; 45 RETLW MAX ; 46 RETLW MAX ; 47 RETLW MAX ; 48 RETLW MAX ; 49 RETLW MAX ; 50 RETLW MAX ; 51 RETLW MAX ; 52 RETLW MAX ; 53 RETLW MAX ; 54 RETLW MAX ; 55 RETLW MAX ; 56 RETLW MAX ; 57 RETLW MAX ; 58 RETLW MAX ; 59 RETLW MAX ; 60 RETLW MAX ; 61 RETLW MAX ; 62 RETLW MAX ; 63 RETLW MAX ; 64 ; routine to convert the byte in W to BCD in D0, D1, D2.; need to add hex 30 to each digit before outputtingB2BCD CLRF D0 CLRF D1 MOVWF D2BCD_1 MOVLW .100 SUBWF D2, W BTFSS STATUS, 0 GOTO BCD_2 INCF D0, F GOTO BCD_1BCD_2 MOVLW .10 SUBWF D2, W BTFSS STATUS, 0 RETLW 0 MOVWF D2 INCF D1, F GOTO BCD_2 END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -