|
[这个贴子最后由成都小财神在 2003/02/17 09:22am 编辑]
是用AVR单片机,用ATTINY 12/15 或 AT90S1200/2313 等都行,只要程序相应部分改一下,可以做得很轻,程序如下,自己慢慢分析。

程序:
.include "2313def.inc" ; Definitionsfile for the microcontroller used.
.equ outpins =0x03
.equ mask_in =0x03
.equ PIN =PINB
.equ PORT =PORTD
.equ output1 =0x01
.equ output2 =0x02
.def mask_ch1 =r0
.def mask_ch2 =r1
;.def mask_ch3 =r2
.def min_l =r3
.def min_h =r4
.def max_l =r5
.def max_h =r6
.def ch1_l =r7
.def ch1_h =r8
.def ch2_l =r9
.def ch2_h =r10
.def ch1o_l =r11 ;debug
.def ch1o_h =r12 ;debug
.def ch2o_l =r13 ;debug
.def ch2o_h =r14 ;debug
.def glitch =r15 ;debug
.def temp =r16
.def temp_l =r16
.def out1_l =r17
.def out1_h =r18
.def out2_l =r19
.def out2_h =r20
.def mask =r21
.def temp2 =r22
.def temp_h =r22
.def temp3 =r23
.def outo1_l =r24
.def outo1_h =r25
.def outo2_l =r26
.def outo2_h =r27
;.def =r28
;.def =r29
;.def =r30
;.def =r31
.org 0
rjmp reset ; Reset vector
reti ; Other inerruptvectors.
reset:
; Stack pointer removed for AT90S1200 compability
ldi temp,ramend
out SPL,temp ; Init stackpointer (for devices with RAM)
; rcall modeselect ; Sense the mode selected with resistors
; on the outputpins (8 pin parts)
ldi temp,outpins ;
out DDRD,temp ;Set outputs
;init the min and max values!
; ser temp
; mov min_l,temp
; mov min_h,temp
; clr temp
; mov max_l,temp
; mov max_h,temp
clr temp
mov max_l,temp
mov min_l,temp
ldi temp,0x03
mov min_h,temp
ldi temp,0x06
mov max_h,temp
; Berit Sofie 74215393
rcall input_order ; Sort out the order of the input signals
; rcall debug_init ; Init of debug-routines
main:
rcall input ; Read the input signals
; rcall input_d ; Debug input routine
; wdr ; Reset watchdogtimer. We don't want to be interrupted.
rcall calc ; Calculate output signals
; rcall output_d; Debug output routine
; rcall calc_d ; Debug calc routine
rcall output ; Send the output signals
rjmp main ; Loop forever.
;
; Input_order: Mesures the input signals and sorts out their order.
; This makes it easier to do more acurate measurements of the
; input signals. The result is stored in
; Mask_ch1, Mask_ch2 and Mask_ch3 (Mask_ch3 is used for power-control)
;
input_order:
rcall w_1ms ; Just hang around and wait for a while.
in temp,pin
andi temp,mask_in
brne input_order ; Signals are still active, wait more
w_inactive:
rcall w_1ms ; Just hang around and wait for a while more just in case
in temp,pin
andi temp,mask_in
brne w_inactive ; Signals are still active, wait more
o_1:
in temp,pin
andi temp,mask_in
breq o_1 ; No active signals test again.
mov mask_ch1,temp ; We have now found the mask for ch1
ldi mask,mask_in
eor mask,temp ; Remove ch1 from the inputmask.
in temp,pin
o_2:
in temp,pin
and temp,mask
breq o_2 ; No active signals test again.
mov mask_ch2,temp ; We have now found the mask for ch2
; eor mask,temp ; Remove ch2 from the inputmask.
; mov mask_ch3,mask ; And we know what the mask for ch3 is. (No 3.rd channel in use)
ret ; Return from input_order
;
; Input: Measures the inputsignals. The result is stored in:
; CH1_l, CH1_h, CH2_l, CH2_h, CH3_l and CH3_h (CH3 optional)
;
input:
w_ch1:
clr ch1_l
clr ch1_h
in Temp,PIN
and Temp,mask_ch1 ; Testing for activ signals
breq w_ch1 ; Check again if not active
ch1:
in temp,pin ;
and temp,mask_ch1
breq w_ch2 ; Break out if the signal go inactive
inc CH1_l ; Inc the low byte of CH1 counter
brne ch1
inc CH1_h ; Inc the high byte of CH1 counter
rjmp ch1
w_ch2:
clr ch2_l
clr ch2_h
in Temp,PIN
and Temp,mask_ch2 ; Testing for activ signals
breq w_ch2 ; Check again if not active
ch2:
in temp,pin ;
and temp,mask_ch2
breq w_ch3 ; Break out if the signal go inactive
inc CH2_l ; Inc the low byte of CH1 counter
brne ch2
inc CH2_h ; Inc the high byte of CH1 counter
rjmp ch2
w_ch3: ; Comment out this section if 3.rd channel is not in use. (done)
; in Temp,PIN
; andi Temp,mask_ch3 ; Testing for activ signals
; breq end_input ; Check again if not active
;
;ch3:
; in temp,pin ;
; and temp,mask_ch3
; brne w_ch3 ; Break out if the signal go inactive
; inc CH3_l ; Inc the low byte of CH1 counter
; brne ch3
; inc CH3_h ; Inc the high byte of CH1 counter
; rjmp ch3
;
; End of 3.rd channel section
;end_input:
ret ; Return from input subroutine
;
; Calc: Calculates the output signals based on the inputsignals
; measured and keeps measurements on highest and lowest value
; measured for selfcompensation of frequence drift.
;
calc:
; Check if any of the measured inputsignals are higher or lower
; Than the hihest and lowest measured so far.
rjmp skipminmax
cp min_l,ch1_l
cpc min_h,ch1_h
brlo nominch1 ; Branch if ch1>=min -> no change
mov min_l,ch1_l
mov min_h,ch1_h
nominch1:
cp min_l,ch2_l
cpc min_h,ch2_h
brlo nominch2 ; Branch if ch2>=min -> no change
mov min_l,ch2_l
mov min_h,ch2_h
nominch2:
; 3.rd channel commented out.
; cp min_l,ch3_l
; cpc min_h,ch3_h
; brlo nominch3 ; Branch if ch2>=min -> no change
; mov min_l,ch3_l
; mov min_h,ch3_h
;nominch3:
cp max_l,ch1_l
cpc max_h,ch1_h
brsh nomaxch1
mov max_l,ch1_l
mov max_h,ch1_h
nomaxch1:
cp max_l,ch2_l
cpc max_h,ch2_h
brsh nomaxch2
mov max_l,ch2_l
mov max_h,ch2_h
nomaxch2:
; cp max_l,ch3_l
; cpc max_h,ch3_h
; brsh nomaxch3
; mov max_l,ch3_l
; mov max_h,ch3_h
;nomaxch3:
; It could be a good idea to add some checking here if you
; run at a fixed frequence
sub ch1_l,min_l ; Remove the first part of the
sbc ch1_h,min_h
sub ch2_l,min_l
sbc ch2_h,min_h
; No 3.rd channel in this version.
; sub ch3_l,min_l
; sbc ch3_h,min_h
skipminmax: ; Debug info only.
; Out1=((ch1+ch2)/2)+min
mov out1_l,ch1_l ;
mov out1_h,ch1_h ; Ch1
add out1_l,ch2_l ;
adc out1_h,ch2_h ; +Ch2
clc
ror out1_h
ror out1_l ; /2
add out1_l,min_l
adc out1_l,min_h ; +min
; Out2 = ((ch1-ch2)/2)+50% = (min+max+ch1-ch2)/2
; 50%=(min+max/2) including offset
mov out2_l,min_l
mov out2_h,min_h ; min
add out2_l,max_l
adc out2_h,max_h ; +max
add out2_l,ch1_l
adc out2_h,ch1_h ; +ch1
sub out2_l,ch2_l
sbc out2_h,ch2_h ; -ch2
clc
ror out2_h
ror out2_l ; /2
;
; Calculations for CH3:
; Out3=ch3*(maxOCRBvalue/max-min)
; Not included. (have'nt got use for it yet...
; out3 -> OCR (PWM register)
ret ; Return from calc subroutine.
;
; Output: Sends the calculated signals
output:
;
;
;
ldi temp,0x01
add out1_l,temp
adc out1_h,temp
add out2_l,temp
adc out2_h,temp
ldi temp,0 ; Inc out1_l if zero (it will otherwise be dec'ed 256 times instead of none)
cp out1_l,temp
brne out1_noz
inc out1_l
out1_noz:
cp out2_l,temp
brne out2_noz
inc out2_l
out2_noz:
ldi Temp,output1
out PORT,Temp
outp_1:
nop
nop
nop
dec Out1_l
brne outp_1
dec Out1_h
brne outp_1
ldi Temp,0x00
out PORT,Temp
ldi Temp,output2
out PORT,Temp
outp_2:
nop
nop
nop
dec Out2_l
brne outp_2
dec Out2_h
brne outp_2
ldi Temp,0x00
out PORT,Temp
ret
;
; Wait ~1ms (4MHz the time is not at all critical)
;
w_1ms:
ser temp
ldi temp2,11 ;
ww:
dec temp
brne ww
dec temp2
brne ww
ret
|
欢迎继续阅读楼主其他信息
|