; Stehwellen- und Leistungsmesser V1.0 ; von Oliver Graffunder, DL7JGR ; ; vom 20.10.2001 ; timer reload calculation ; baud_const = 256 - (crystal / (12 * 16 * baud)) .equ baud_const, 253 ; 9600 @11,059, 19200@22.1184 MHz ;.equ baud_const, 250 ; 4800 @11,059, 9600@22.1184 MHz ;.equ baud_const, 244 ; 2400 @11,059, 4800@22.1184 MHz ;.equ baud_const, 232 ; 1200 @11,059, 2400@22.1184 MHz ;.equ baud_const, 208 ; 600 @11,059, 1200@22.1184 MHz ;.equ baud_const, 160 ; 300 @11,059, 600@22.1184 MHz .equ begin, 0 .equ adp, 90h ; AD-Eingang .equ adn, 91h ; AD-RC-Glied .equ lcd_rs, 92h ; LCD-RS-Leitung .equ lcd_e, 93h ; LCD-E-Leitung .equ lcd_d4, 94h ; LCD-D4-Leitung .equ lcd_d5, 95h ; LCD-D5-Leitung .equ lcd_d6, 96h ; LCD-D6-Leitung .equ lcd_d7, 97h ; LCD-D7-Leitung .equ f_rx, 0xb0 ; RxD-Leitung .equ f_tx, 0xb1 ; TxD-Leitung .equ in_a, 0xb2 ; Analogeingang 1 .equ in_b, 0xb3 ; Analogeingang 2 .equ in_c, 0xb4 ; Analogeingang 4 .equ in_oe, 0xb5 ; Analogeingang Outputenable .equ adi, 0xb6 ; P3.6 Komperatorausgang .equ frei1, 0xb7 ; ; Analogeingang ; 0 1 2 3 4 5 6 7 ; FWD1 REV1 FWD2 REV2 FWD3 REV3 FWD4 REV4 ; ------------------------------- RAM Belegung .equ fwd_h, 0x7f .equ fwd_l, 0x7e .equ rev_h, 0x7d .equ rev_l, 0x7c .equ swr_h, 0x7b .equ swr_l, 0x7a .equ akt_in, 0x79 .equ null_h, 0x78 .equ null_l, 0x77 .equ dawert, 0x76 ; ********************************************************************** ; Programmanfang ; ********************************************************************** .org begin ljmp poweron ;reset vector .org begin+3 ;ext int0 vector .org begin+11 ;timer0 vector .org begin+19 ;ext int1 vector .org begin+27 ;timer1 vector .org begin+35 ;uart vector .org begin+43 ;timer2 vector (8052) .org begin+48 ;finally we can begin ; ##### Warte 5ms bei 22,1MHz ########################################## wait5: mov r6,#16 ; 16 bei 22,1MHz und 8 bei 11,05MHz mov r7,#0 wait5l: djnz r7,wait5l djnz r6,wait5l ret ; ##### Warte 1.7ms bei 22,1MHz ######################################## await: ; Wartezeit f|r den Analogeingang wait2: mov r6,#6 ; 6 bei 22MHz mov r7,#0 wait2l: djnz r7,wait2l djnz r6,wait2l ret ; ********************************************************************** ; misst einen Wert am Wandler analog: clr adn mov dptr,#0 setb adn analog1: inc dptr jb adi,analog1 clr adn ret ; ********************************************************************** ; schaltet einen eingang durch ad_in: mov a, r0 clr in_oe ; Analog-MUX einschalten mov c, acc.0 ; und die einzelnen Bits an den Decoder mov in_a, c ; schicken. mov c, acc.1 mov in_b, c mov c, acc.2 mov in_c, c ret ; ********************************************************************** ; LCD-Funktionen ; ********************************************************************** ; Bit's so drehen, wie das LCD-Display angeschlossen ist. bitdr: mov c,acc.7 mov P1.7,c mov c,acc.6 mov P1.6,c mov c,acc.5 mov P1.5,c mov c,acc.4 mov P1.4,c bitdr2: nop nop nop setb lcd_e nop nop nop clr lcd_e ret ; ***************** Ausgabe auf ein LCD-Display ************************ ; ++++++++++ 1 Zeichen senden +++++++++++ ; A: Zeichen ; Ausgabe über P1, Pinbelegung: ; P1.4-P1.7: D4-D7 des LCD-Displays (siehe bitdr ; P1.3: E ; P1.2: RS ; D0-D3,R/W an Masse (0V) cblcd: clr lcd_rs ; Kontrollbyte sjmp cblcd1 colcd: setb lcd_rs ; Datenbyte cblcd1: mov r5,a ; Zeichen merken acall bitdr mov a,r5 ; zeichen wiederholen swap a acall bitdr jb lcd_rs,colcd3 acall wait2 ; bei Befehlen 2ms warten colcd3: mov r6,#100 ; und warten colcd2: djnz r6,colcd2 ret ; ++++++++++ LCD-Display initialisieren +++++++++++ ; Keine Parameter lcd_init: mov P1,#00000001b ; E=0, RS=0 acall wait5 ; mov P1,#01000001b ; E=0, DL=0; RS=0 mov P1,#00100001b ; E=0, DL=0; RS=0 acall bitdr2 acall wait5 mov a, #00000001b ; Display-Clear acall cblcd mov a, #00001100b ; Display, Cusor OFF und Blink OFF acall cblcd mov a, #00101000b ; Display, 2-Zeilig acall cblcd mov a, #01000000b ; CGRAM laden ab Adresse 0 acall cblcd mov dptr, #lcd_bar acall lprt mov a, #10000000b ; und wieder zur Normalausgabe acall cblcd ret ; +++++++++++ LCD-PRINT ++++++++++++++++++ lprt2: mov a,#00000010b ; HOME Ausgeben lprt4: acall cblcd acall wait5 lprt: clr a ; Text Ausgeben movc a,@a+dptr jz lprte inc dptr acall colcd sjmp lprt lprte: ret ; ***************** Zahlen auf LCD ************************************* ; Sendet ein Byte in HEX ; A: Byte lhex: PUSH ACC SWAP A ACALL lhex1 POP ACC ACALL lhex1 RET lhex1: ANL A,#0FH ADD A,#3 MOVC A,@A+PC ACALL colcd RET .DB "0123456789ABCDEF" ; Gigt 16Bit Hex aus ; A: Lowbyte ; B: Highbyte lhex16: push acc mov a,b acall lhex pop acc ljmp lhex ; ********************************************************************** ; gibt eine Zahl dez. aus ... signed ; A: Zahl lvzd: mov b,a jnb acc.7,lvzd1 mov a,#'-' acall colcd mov a,b cpl a inc a sjmp ldez lvzd1: mov a,#' ' acall colcd mov a,b ; ------ Unsigned ----------------------------- ldez: mov B,#100 div ab add a,#48 acall colcd mov a,B ldezx: mov B,#10 div ab add a,#48 acall colcd ldez1: mov a,B add a,#48 acall colcd ret ; ********************************************************************** ; gibt r3,r2 als dezimale unsigned zahl aus ; ldez2: clr psw.5 mov r4, #16 ;ten-thousands digit mov r5, #39 acall ldez2x ; acall ldez2z ; wir brauchen hier keinen 10000er mov r4, #232 ;thousands digit mov r5, #3 acall ldez2x acall ldez2z mov r4, #100 ;hundreds digit mov r5, #0 acall ldez2x ; Ausgabeposition berichtigen jb psw.5, ldez2b ; wenn schon was ausgegeben, dann weiter jz ldez2b ; wenn Null dann nix ausgeben mov r4, a mov a, #' ' ; doch noch ein Leer ausgeben acall colcd mov a, r4 ldez2b: acall ldez2z mov a, r2 ;tens digit mov b, #10 div ab add a, #'0' acall colcd jb psw.5, ldez2a ; wenn weniger als 2 Ziffern ausgegeben sind mov a,#',' ; dann kommastellen ausgeben acall colcd mov a, b ;and finally the ones digit add a, #'0' lcall colcd ldez2a: ret ; Div16 langsam aber richtig ldez2x: mov r0,#0 ldez2y: inc r0 clr c mov a, r2 subb a, r4 mov r2, a mov a, r3 subb a, r5 mov r3, a jnc ldez2y dec r0 mov a, r2 add a, r4 mov r2, a mov a, r3 addc a, r5 mov r3, a mov a, r0 ret ; Ausgabe der einzelnen Ziffern ldez2z: jz ldez21 setb psw.5 ldez22: add a, #'0' ljmp colcd ldez21: jb psw.5, ldez22 ; mov a, #' ' ; ljmp colcd ret ; ********************************************************************** cin: jnb ri, cin clr ri mov a, sbuf ret cout: jnb ti, cout mov sbuf, a clr ti ret PSTR: ;print string PUSH ACC PSTR1: CLR A MOVC A,@A+DPTR JZ PSTR2 mov c, acc.7 anl a, #01111111b lcall cout Jc pstr2 inc dptr SJMP PSTR1 PSTR2: POP ACC RET ; ********************************************************************** ; Einen Balken mit ACC (0 - 40) Länge ausgeben lbar: mov r2, #8 ; 8 Zeichen ausgeben mov r3, a ; Merken clr c ; und ACC auf 40 begrenzen subb a, #41 jc lbar1 mov r3, #40 lbar1: mov a, r3 jz lbar0 dec r2 cjne a, #1, lbar2 mov a, #0 acall colcd sjmp lbar0 lbar2: cjne a, #2, lbar3 mov a, #1 acall colcd sjmp lbar0 lbar3: cjne a, #3, lbar4 mov a, #2 acall colcd sjmp lbar0 lbar4: cjne a, #4, lbar5 mov a, #3 acall colcd sjmp lbar0 lbar5: clr c subb a, #5 mov r3, a mov a,#0xFF acall colcd sjmp lbar1 lbar0: mov a, r2 jz lbare lbar6: mov a, #'.' acall colcd djnz r2, lbar6 lbare: ret ; ********************************************************************** ; Multipliziert (R3,R2) * (B,A) = (15,14,13,12) mul16: mov 9,b mov 8,a mov b,r2 mul ab mov 12,a mov 13,b mov a,9 mov b,r3 mul ab mov 14,a mov 15,b mov a,9 mov b,r2 mul ab add a,13 mov 13,a mov a,b addc a,14 mov 14,a clr a addc a,15 mov 15,a mov a,8 mov b,r3 mul ab add a,13 mov 13,a mov a,b addc a,14 mov 14,a clr a addc a,15 mov 15,a ret ; ********************************************************************** ; div16 teilt r3,r2 = r3,r2 / DPTR div16: mov r4,#0 ; ergebnis_l mov r5,#0 ; ergebnis_h mov r6,#1 ; zähler mov a, dpl ; wenn DPTR 0 ist, dann Fehler ausgeben orl a, dph jnz div163 mov r3, #3 ; maximalwert 999 ausgeben mov r2, #231 ret div163: mov a, dph ; bits nach vorne schieben jb acc.7, div164 ; wenn alle bits vorne sind , dann teilen mov a, dpl clr c rlc a mov dpl, a mov a, dph rlc a mov dph, a inc r6 sjmp div163 div162: clr c ; divisor durch 2 teilen mov a, dph rrc a mov dph, a mov a, dpl rrc a mov dpl, a div164: mov a,r2 ; divisor abziehen clr c subb a, dpl mov r1, a mov a, r3 subb a, dph jc div161 ; wenn negativ, dann weiter mov r3, a ; wenn positiv, dann mov r2, 1 ; Wert merken und 4 -> R4 nach R2 div161: cpl c ; C umdrehen (pos. Ergebnis gibt eine 1) mov a, r4 ; und Ergebis reinschieben rlc a mov r4, a mov a, r5 rlc a mov r5, a djnz r6, div162 mov r3, 5 mov r2, 4 ret ; ********************************************************************** ; power r3,r2 = hoch2(DPTR)/256 => x=716 sind 200,0W power: mov b, dph mov a, dpl mov r3, dph mov r2, dpl acall mul16 ; mit sich selbst multiplizieren mov a, 15 ; geteilt durch 1024 clr c rrc a mov 15, a mov a, 14 rrc a mov 14, a mov a, 13 rrc a mov 13, a mov a, 15 mov c, acc.0 mov a, 14 rrc a mov r3, a mov a, 13 rrc a mov r2, a ret ; ********************************************************************** ; swr berechnet das SWR, SWR = (FWD + REV) / (FWD - REV) swr: mov a, fwd_l ; FWD + REV rechnen clr c addc a, rev_l mov r2, a mov a, fwd_h addc a, rev_h mov r3, a mov b, #0 ; und mal 10 nehmen, damit die Anzeige mov a, #10 ; stimmt (x.x) acall mul16 mov r3, 13 mov r2, 12 mov a, fwd_l ; FWD - REV rechnen clr c subb a, rev_l mov dpl, a mov a, fwd_h subb a, rev_h mov dph, a jnc swr1 ; wenn das Ergebnis negativ ist, mov dpl, #0 ; dann 0 eintragen mov dph, #0 swr1: acall div16 ; und teilen cjne r3, #3, swr4 ; vergleich mit Max-Wert 999 jc swr2 cjne r2, #231, swr4 swr4: jc swr2 ; wenn drueber, dann mov r3, #3 ; maximalwert 999 ausgeben mov r2, #231 swr2: ret ; ********************************************************************** ; vswr berechnet das vswr, vswr(ACC) = REV * 40 / FWD vswr: mov r3, rev_h ; REV * 40 mov r2, rev_l ; für die 40 Balkenelemente mov b, #0 mov a, #40 acall mul16 mov r3, 13 ; und durch FWD teilen mov r2, 12 mov dph, fwd_h mov dpl, fwd_l acall div16 mov a, r2 ret ; ********************************************************************** ; Hauptschleife ; ; ********************************************************************** ; ********************************************************************** ; ********************************************************************** help1: .db "SWR-Meter OV D11",0 help2: .db "by DL7JGR 2001 ",0 text1: .db "FWD:",0 text2: .db "REV:",0 text3: .db "SWR:",0 ; ********************************************************************** poweron: MOV SP, #22h ; clr psw.3 ; clr psw.4 ; clr ea setb lcd_rs clr lcd_d4 clr lcd_d5 clr lcd_d6 clr lcd_d7 clr lcd_e clr adn mov th1, #baud_const orl PCON,#00000000b ; normale Baud-Rate MOV TMOD,#00100001b ; T0=16 bit, T1=8 bit, Reload MOV SCON,#01010010b ; Set Serial for mode 1 & ; Enable reception, ti=1, ri=0 ORL TCON,#01010000b ; Beide Timer laufen mov IE, #10000000b ; INT aus! mov IP, #00000000b ; hohe Prioritaet Keine mov r1, #10 ; und 0,05Sek. warten ??? pow02: acall wait5 ; bis sich alles beruhigt hat djnz r1, pow02 acall lcd_init ; LCD-Display initialisieren acall wait5 mov dptr, #help1 ; Startmeldung ausgeben acall lprt2 mov a, #11000000b ; CR+NL Ausgeben acall cblcd mov dptr, #help2 acall lprt mov r1, #200 ; und 1Sek. warten ??? pow01: acall wait5 ; bis sich alles beruhigt hat djnz r1, pow01 ; +++ Hauptschleife +++ pow1: mov a, #11001111b ; 2.Zeile, letzte stelle acall cblcd ; soll der aktive Wandler stehen mov a, #'-' ; Kein wandler aktiv acall colcd ; +++ aktiven Wandler suchen mov r0, #8 ; Mit Wandler D beginnen pow10: dec r0 dec r0 acall ad_in ; den entsprechenden Eingang durchschalten acall wait5 ; 5ms warten acall analog ; Wert messen mov a, dpl ; sehen, ob eine Spannung anliegt anl a, #11111000b ; die letzten 3 Bit ignorieren orl a, dph jnz pow20 ; wenn was da ist, dann richtig messen mov a, r0 jnz pow10 ; schon beim letzten Wandler ? mov r1, #20 ; und 100ms warten ??? pow11: acall wait5 ; bis sich alles beruhigt hat djnz r1, pow11 ajmp pow1 ; und weiter suchen ; +++ Das SWR am aktiven Eingang messen pow20: mov akt_in, r0 ; Erstmal merken, wo das herkam mov a, #11001111b ; 2.Zeile, letzte stelle acall cblcd ; soll der aktive Wandler stehen mov a,r0 clr c ; durch 2 teilen rrc a add a, #'A' ; und A, B, C oder D ausgeben acall colcd ; +++ Messschleife +++++++++++++++++++++++++++++++++++++++++++++++++++++ ; + Vorlauf anzeigen pow21: mov a, #11000000b ; Anfang 2. Zeile springen acall cblcd mov dptr, #text1 ; FWD ausgeben acall lprt mov r0, akt_in ; rücklaufende Welle messen inc r0 acall ad_in acall wait5 acall analog mov rev_l, dpl ; und merken mov rev_h, dph mov r0, akt_in ; vorlaufende Welle messen acall ad_in acall wait5 acall analog mov a, dpl ; nachsehen, ob noch was da ist anl a, #11111000b ; die letzten 3 Bit ignorieren orl a, dph jz pow1 ; wenn nix da ist, dann wieder suchen mov fwd_l, dpl ; und merken mov fwd_h, dph acall power ; Hoch 2 nehmen und korigieren acall ldez2 ; und Spezialausgabe xxx oder x.x mov a, #' ' ; ein Leerzeichen ausgeben acall colcd ; + Rücklauf anzeigen mov dptr, #text2 ; REV ausgeben acall lprt mov dpl, rev_l ; Rücklaufwelle Ausgeben mov dph, rev_h acall power ; Hoch 2 nehmen und korigieren acall ldez2 ; und Spezialausgabe xxx oder x.x ; + SWR ausgeben mov dptr, #text3 ; SWR ausgeben acall lprt2 ; mit Home acall swr ; SWR als Zahl ausgeben mov swr_l, r2 ; das SWR merken mov swr_h, r3 acall ldez2 ; Zahl ausgeben mov a, #' ' ; ein Leerzeichen ausgeben acall colcd ; + VSWR als Balken ausgeben acall vswr ; Das VSWR berechnen, schöner Balken acall lbar ; Balken ausgeben mov r1, #20 ; und 100ms warten ??? pow22: acall wait5 ; bis sich alles beruhigt hat djnz r1, pow22 ajmp pow21 ; und weitermessen ; ********************************************************************** ; Zeichensatz für die Bargrafik lcd_bar: .db 10010000b,10010000b,10010000b,10010000b .db 10010000b,10010000b,10010000b,10010000b .db 10011000b,10011000b,10011000b,10011000b .db 10011000b,10011000b,10011000b,10011000b .db 10011100b,10011100b,10011100b,10011100b .db 10011100b,10011100b,10011100b,10011100b .db 10011110b,10011110b,10011110b,10011110b .db 10011110b,10011110b,10011110b,10011110b .db 0 ; Ende