📄 fc430_es417_iar.s43
字号:
;************************ ZERO-INIT GLOBAL VARIABLES **************************
;------------------------------------------------------------------------------
RSEG DATA16_Z
EVEN
;------------------------------------------------------------------------------
status DS 1 ; Alarm status of system
level DS 1 ; System cooling level setting
LCD DS 2 ; Temp storage for LCD memory map
tachCount DS 2 ; Frequency generator counter 4 fan
tachRPM DS 2 ; Current tachometer reading in RPM
tempDegF DS 2 ; Current temperature in degrees F
lastRPM DS 2 ; Last tachometer reading in RPM
arrowState DS 2 ; State machine for arrows on LCD
TEMP DS 2 ; Temporary storage in temp routine
RESULT DS 2 ; Temporary storage in temp routine
IRBIT DS 2 ; Used for bit test
IROP1 DS 2 ; First operand
IROP2L DS 2 ; Second operand low word
IROP2H DS 2 ; Second operand high word
IRACCL DS 2 ; Math result low word
IRACCH DS 2 ; Math result high word
;------------------------------------------------------------------------------
RSEG CODE
EVEN
;------------------------------------------------------------------------------
;*************************** MAIN SYSTEM PROCESSING ***************************
RESET: mov.w #300h, SP ; Initialize system stackpointer
call #initSystem ; Initialize the system as a whole
main_loop: bis.w #LPM0, SR ; Drop into Low Power Mode 0
call #checkTach ; Update tachometer readings
call #sampleTemp ; Take a temperature reading
call #dispTemp ; Update temperature on LCD
call #checkTemp ; Check temp & set cooling level
call #dispLevel ; Display cooling level setting
jmp main_loop ; Repeat main background loop
;------------------------------------------------------------------------------
initSystem: mov.w #(WDTPW+WDTHOLD),&WDTCTL; Disable the Watchdog
bis.b #XCAP18PF, &FLL_CTL0 ; Set internal load caps for xtal
mov.w #0x00, R15 ; Reset counter
setupFLL: cmp.w #0x2710, R15 ; Delay for FLL to lock (@ power up)
jc setupP1 ; FLL locked, exit calibration loop
add.w #0x01, R15 ; Increment our FLL delay counter
jmp setupFLL ; Busy loop until FLL is locked
setupP1: bic.b #ACTIVITY, &P1SEL ; Configure Port 1 Output Pin(s)
bis.b #ACTIVITY, &P1DIR ; Physically set the Port 1 Pin(s)
setupP2: mov.b #0xFF, &P2SEL ; Set segment outputs for LCD
mov.b #0xFF, &P2DIR ; All outputs
bic.b #TACH, &P2SEL ; Set up tachometer input
bic.b #TACH, &P2DIR ; Set up tachometer direction
bis.b #TACH, &P2IE ; Enable Port 2 interrupt
bis.b #TACH, &P2IES ; Generate ints on falling edge
setupWDT: mov.w #WDT_ADLY_1000, &WDTCTL ; Set up Watchdog Interval
bis.b #WDTIE, &IE1 ; Enable WatchdogTimer Interval int
setupLCD: mov.b #0xFF, &P3SEL ; Set segment outputs for LCD
mov.b #0xFF, &P3DIR ; All outputs
mov.b #0xFF, &P4SEL ; Set segment outputs for LCD
mov.b #0xFF, &P4DIR ; All outputs
mov.b #0xFC, &P5SEL ; Set Rxx and COM pins for LCD
mov.b #0xFF, &P5DIR ; All outputs
; 4mux LCD, segs0-15 = outputs
mov.b #(LCDON+LCDSG0_3+LCD4MUX), &LCDCTL
; Set LCD frame freq = ACLK/128
; Set interrupt interval
setupBT: mov.b #(BT_fLCD_DIV128+BTDIV+BTIP2), &BTCTL
bis.b #BTIE, &IE2 ; Enable Basic Timer interrupt
mov.b #0xFF, &LCDM8 ; Set S15:S14 on LCD
mov.b #0xFF, &LCDM9 ; Set S17:S16 on LCD
mov.b #0xFF, &LCDM10 ; Set S19:S18 on LCD
mov.b #0xF7, &LCDM11 ; Set S21:S20 on LCD
setupPWM: bis.b #PWM, &P2DIR ; Sonfigure for output direction
bis.b #PWM, &P2SEL ; Select peripheral option
mov.w #PERIOD050USEC, &TA1CCR0; Set up the PWM Period
mov.w #(TASSEL_2+MC_1),&TA1CTL; Use SMCLK, count up mode
mov.w #OUTMOD_1, &TA1CCTL1 ; Output HI signal - keep fans off
setupCA0: and.b #~(REF+THERM), &P1SEL ; Select GPIO function for R(ref)
bis.b #(REF+THERM), &P1DIR ; Change R(ref) pin for output
; (vs. floating; saves power)
and.b #~(REF+THERM), &P1OUT ; Clear resistor outputs
mov.b #(REF+THERM+CAIN), &CAPD; Disable input buffers for inputs
mov.b #P2CA0, &CACTL2 ; Set up comparator port
initData: mov.b #0x01, &level ; Initialize to Level 1 (one-time)
mov.w #0x91, &LCD ; Initialize LCD (one-time)
enableInts: eint ; Enable global interrupts
ret ; Return from subroutine
;*************************** MATH UTILITY FUNCTIONS ***************************
;------------------------------------------------------------------------------
; Unsigned multiply routine IROP1 x IROP2L -> IRACH/IRACL
; variables used IROP1, IROP2L, IROP2H, IRACL, IRACH, IRBT
;------------------------------------------------------------------------------
UMPY_16x16: clr.w IRACCL ; 0 -> LSBs of result
clr.w IRACCH ; 0 -> MSBs of resut
clr.w IROP2H ; MSBs multiplier
mov.w #0x01,IRBIT ; Bit test register
MPY1: bit.w IRBIT,IROP1 ; Test actual bit
jz MPY2 ; If 0 do nothing
add.w IROP2L,IRACCL ; If 1 add multiplier to result
addc.w IROP2H,IRACCH ; Add carry to destination
MPY2: rla.w IROP2L ; Multiplier x 2
rlc.w IROP2H ; Rotate P2H left through carry bit
rla.w IRBIT ; Get the next bit to test
jnc MPY1 ; Finished if bit in carry
mov.w TEMP,IROP1 ; Move result into P1 variable
mov.w IRACCL,IROP2L ; Move low word into P2L var
mov.w IRACCH,IROP2H ; Move high word into P2H var
UMPY_DONE: ret ; Return from subroutine
;------------------------------------------------------------------------------
; Unsigned division subroutine 32-bit BY 16-bit
; IROP2M|IROP2L : IROP1 -> IRACL remainder in IROP2H
; return: carry = 0 = OK carry = 1 = quotient > 16 bits
; variables used IROP1, IROP2L, IRACL, IRBT, IROP2H
;------------------------------------------------------------------------------
UDIV_32_16: clr.w IRACCL ; Clear accumulator low
mov.w #17,IRBIT ; Initalize loop counter
DIV1: cmp.w IROP1,IROP2H ; Compare P1 to P2H
jlo DIV2 ; Jump if less than
sub.w IROP1,IROP2H ; Subtract P1 from P2H
DIV2: rlc.w IRACCL ; Rotate left through carry bit
jc UDIV_DONE ; Error: result > 16 bits
dec.w IRBIT ; Decrement loop counter
jz UDIV_DONE ; Is 0: terminate w/o error
rla.w IROP2L ; Rotate P2L left arithmetically
rlc.w IROP2H ; Rotate P2H left thru carry bit
jnc DIV1 ; Jump if carry bit not set
sub.w IROP1,IROP2H ; Subtract P1 from P2H
setc ; Set the carry bit
jmp DIV2 ; Repeat the current loop
UDIV_DONE: ret ; Return from subroutine
;*********************** SLOPE A/D CONVERSION FUNCTIONS ***********************
;--------Capacitor is charged up with reference resistor-----------------------
; SMCLK, clear, continuous
chargeCap: mov.w #(TASSEL1+TACLR+MC1), &TACTL
bic.b #REF, &CAPD ; Must be enabled for output func
bis.b #REF, &P1OUT ; Ref Set
mov.w #PERIOD5MSEC, &CCR1 ; CCR1 ~ TAR+5ms (5tu)
mov.w #CCIE, &CCTL1 ; Compare mode,interrupt
bis.w #LPM0, SR ; Wait for CCR1 interrupt
bis.b #REF, &CAPD ; Input buffer disabled 4 tri-state
bic.b #REF, &P1OUT ; Ref = reset
;--------Measure discharge time -----------------------------------------------
dischargeCap: ; -Comp = 0.25*Vcc, comp on
mov.b #(CARSEL+CAREF0+CAON), &CACTL1
; Neg, CCIB,cap,interrupt
mov.w #(CM1+CCIS0+CAP+CCIE), &CCTL1
push &TAR ; Save TAR at start of conversion
bic.b R14, &CAPD ; Must be enabled for output func
bis.w #LPM0, SR ; Wait for CCR1 interrupt
mov.w &CCR1, R14 ; R14 = TAR (CCR1) at EOC
sub.w @SP+, R14 ; R14 = discharge time
bis.b #(REF+THERM), &CAPD ; Input buffer disabled 4 tri-state
clr.b &CACTL1 ; Disable comparator
clr.w &CCTL1 ; Disable CCTL1
clr.w &TACTL ; Disable Timer_A
ret ; Return from subroutine
;--------Complete an entire sequence to sample temperature --------------------
sampleTemp: mov.w #REF, R14 ; R14 = Ref pin
call #chargeCap ; Charge cap. & measure reference
mov.w R14, TEMP ; Save Ref discharge time
mov.w #THERM, R14 ; R14 = Sensor pin
call #chargeCap ; Charge cap. and measure sensor
mov.w R14, RESULT ; Save Sensor discharge time
;------------------------------------------------------------------------------
; Calculate temperature based on the thermistor's variable resistance
;------------------------------------------------------------------------------
mov.w RESULT, IROP1 ; Get the result and load into RAM
mov.w #10000, IROP2L ; Initialize the multiplier factor
call #UMPY_16x16 ; Call the unsigned multiply func
call #UDIV_32_16 ; Call the unsigned divide function
;------------------------------------------------------------------------------
; Convert sensor resistance value to degrees F for display
; Table search is done directly with BCD subtraction
; Variable 'IRACCL' contains the sensor resistance value
;------------------------------------------------------------------------------
clr.w R13 ; Clear resistance table pointer
mov.w #99h, R14 ; R14 used as temperature counter
readTable: cmp.w RES_TAB(R13), IRACCL ; Compare table value to sensor
jl storeTemp ; Jump if sensor < table
incd.w R13 ; Double increment (word) pointer
dadd.b #99h, R14 ; Subtract 1 from counter
mov.w R14, R12 ; Save in dedicated register in
jmp readTable ; Mode is changed temp is not lost
storeTemp: sub.w #TEMP_CALFACTOR, R12 ; Adjust temp with cal. factor
mov.w R12, &tempDegF ; Store temperature into RAM
ret ; Return from subroutine
;------------------------------------------------------------------------------
checkTemp: cmp.w #PWM_L0, &tempDegF ; Check temp vs. first boundary
jl cTempDone ; Out of range; goto done
cmp.w #PWM_L1toL2, &tempDegF ; Check temp vs. second boundary
jge cTemp1 ; Go to next check
mov.b #0x1, R14 ; Set level = 1 in RAM
jmp cTemp2 ; Now go adjust PWM duty cycle
cTemp1: cmp.w #PWM_L2toL3, &tempDegF ; Check temp vs. third boundary
jge cTemp3 ; Go to next check
mov.b #0x2, R14 ; Set level = 2 in RAM
jmp cTemp2 ; Now go adjust PWM duty cycle
cTemp3: cmp.w #PWM_L3toL4, &tempDegF ; Check temp vs. fourth boundary
jge cTemp4 ; Go to next check
mov.b #0x3, R14 ; Set level = 3 in RAM
jmp cTemp2 ; Now go adjust PWM duty cycle
cTemp4: cmp.w #PWM_L4toL5, &tempDegF ; Check temp vs. fifth boundary
jl cTemp5 ; Now go adjust PWM duty cycle
mov.b #0x5, R15 ; Set level = 5 in RAM
jmp cTemp6 ; Now go adjust PWM duty cycle
cTemp5: mov.b #0x4, R15 ; Set level = 4 in RAM
cTemp6: mov.b R15, R14 ; Retrieve the level setting
cTemp2: mov.b R14, &level ; Store level into RAM
mov.w #OUTMOD_3, &TA1CCTL1 ; Generate PWM via output mode 3
mov.b R14, R15 ; Figure out current level
sub.b #0x1, R15 ; Level 1 ?
jeq cTemp7 ; We're currently in Level 1
sub.b #0x1, R15 ; Level 2 ?
jeq cTemp8 ; We're currently in Level 2
sub.b #0x1, R15 ; Level 3 ?
jeq cTemp9 ; We're currently in Level 3
sub.b #0x1, R15 ; Level 4 ?
jeq cTemp10 ; We're currently in Level 4
sub.b #0x1, R15 ; Level 5 ?
jeq cTemp11 ; We're currently in Level 5
jmp cTemp12 ; Invalid level setting
cTemp7: mov.w #DUTYCYCLE_030, &TA1CCR1; Set 30% fan duty cycle
jmp cTemp12 ; Go to done
cTemp8: mov.w #DUTYCYCLE_045, &TA1CCR1; Set 45% fan duty cycle
jmp cTemp12 ; Go to done
cTemp9: mov.w #DUTYCYCLE_060, &TA1CCR1; Set 60% fan duty cycle
jmp cTemp12 ; Go to done
cTemp10: mov.w #DUTYCYCLE_080, &TA1CCR1; Set 80% fan duty cycle
jmp cTemp12 ; Go to done
cTemp11: mov.w #DUTYCYCLE_100, &TA1CCR1; Set 100% fan duty cycle
cTemp12: mov.b &level, R12 ; Store the level in RAM
cTempDone: ret ; Return from subroutine
;------------------------------------------------------------------------------
checkTach: mov.w &tachRPM, R15 ; Retrieve tachometer reading
cmp.w #0x00, R15 ; Check fan RPM
jne setLED ; RPM not zero, no alarm condition
mov.b #0x00, R12 ; Reset temp register to 0
call #setStatLED ; Raise alarm condition
jmp refresh ; Update tach reading on display
setLED: mov.b #0x01, R12 ; Set temp register to 1
call #setStatLED ; Call func to set the STATUS LED
refresh: call #updateTach ; Refresh tachometer readings
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -