org 100h cpu 8086 jmp start ; Variablen sollwert db tmin tcounts db 0 ; Impulszaehler fuer Servo, Vorwaertszaehler anzeige times 3 db 0 ; Puffer fuer Ausgabe strlen equ $ - anzeige ; Laenge Zeichenpuffer ; Konstanten intab0 equ 20h ; Adresse Interrupttabelle PIT, Kanal 1 eoi equ 20h ; End Of Interrupt (EOI) clrscr equ 0 ; Clear Screen getkey equ 1 ; Funktion auf Tastatureingabe warten ascii equ 1 ; Funktion ASCII-Zeichenausgabe hexbyte equ 4 ; HEX-Byte Ausgabe conin equ 5 ; Console IN conout equ 6 ; Console OUT pitc equ 0a6h ; Steuerkanal PIT pit1 equ 0a2h ; Counter 1 PIT pit2 equ 0a4h ; Counter 2 PIT ppi_ctl equ 0b6h ; Steuerkanal PPI (Parallelinterface) ppi_a equ 0b0h ; Kanal A PPI ppi_pa0 equ 1 ; LED 0 ppi_pa1 equ 2 ; LED 1 ppi_pa2 equ 4 ; LED 2 ppi_pa3 equ 8 ; Lautsprecher ppi_pa6 equ 1 << 6 ; Servomotor ppi_b equ 0b2h ; Kanal B PPI ppi_c equ 0b4h ; Kanal C PPI ocw_2_3 equ 0c0h ; PIC (Interruptcontroller), OCW2,3 ocw_1 equ 0c2h ; PIC (Interruptcontroller), OCW1 icw_1 equ 0c0h ; PIC (Interruptcontroller), ICW1 icw_2_4 equ 0c2h ; PIC (Interruptcontroller), ICW2,4 leds equ 0 ; LED Port schalter equ 0 ; Schalterport keybd equ 80h ; SBC-86 Tastatur gokey equ 11h ; Taste "GO" outkey equ 15h ; Taste "OUT" sseg7 equ 9eh ; Segmentanzeige 7 tcpwm equ 184 ; 1843200 Hz / 184 = ca. 10000 Hz = 0.1 ms ; Taktzyklus ; Zeitkonstante fuer PWM-Interrupt tpwm equ 200 ; Periodendauer des PWM-Signals (* 0.1 ms) tmax equ 25 ; Impulsdauer fuer 0 Grad (* 0.1 ms) tmin equ 6 ; Impulsdauer fuer 180 Grad (* 0.1 ms) divider equ 13 ; Vorteiler Wandlerwert ; 0..255 -> 0..19 -> + tmin -> tmin..tmax ad_start1 equ 00110000b ; AD-Wandler starten und auf "read" ad_start2 equ 00100111b ; AD-Wandler nur "read" und LED's an start: ; Initialisierung mov ah, clrscr ; Anzeige aus int conout call init ; Controller und Interruptsystem scharfmachen mov al, 0 out leds, al mov al, ad_start1 ; ADU init. out ppi_a, al mov al, ad_start2 out ppi_a, al ; Hintergrundprogramm: Lesen des Wandlerwertes, Verarbeitung und Displayausgabe again: in al, ppi_b ; Wandlerwert ; ... ; ... ; ... jmp again ; Ausgabe einer ASCII-Zeichenkette strout: ; ... ; ... ; ... ret ; 8-Bit Division AL / BL ; Return: Quotient in AL, Rest in AH ; Zerstoert AX, BH ; Algorithmus siehe: ; https://www-user.tu-chemnitz.de/~heha/Mikrocontroller/Division.htm ; Wuerde auch mit dem DIV-Befehl der CPU funktionieren, wieso dann das hier? divide: xor ah, ah ; High-Teil Dividend mov bh, 8 ; Anzahl Bits Quotient _div: shl ax, 1 ; Dividend * 2 cmp ah, bl ; teilbar? jb _smaller ; nein sub ah, bl ; ja, abziehen inc al ; Dividend, Bit 0 = 1 _smaller: dec bh ; fertig? jnz _div ; nein, naechste Stelle ret ; Hornerschema rueckwaerts (Teilen des Wertes durch die Zielbasis bis nix mehr ; da ist; die Reste der Division sind die Ziffern, von "hinten" (LOW) beginnend) ; Hexwert (in AL) nach dezimal (ASCII-String) wandeln und in "anzeige" speichern ; Zerstoert AX, BX, CX, DI val2astr: mov di, anzeige + strlen - 1 ; Zielpuffer rueckwaerts beschreiben mov bl, 10 ; Dezimalwandlung (Zielbasis) xor cx, cx v1: call divide ; AL / BL, Rest in AH add ah, '0' ; --> ASCII mov [di], ah ; Zeichen in Puffer dec di ; vorherige Pufferstelle inc cl ; Zaehler++ or al, al ; fertig? (Dividend zerdividiert?) jnz v1 ; noe, nochmal mov al, cl ; Anzahl mov cl, strlen ; max. Stringlaenge sub cl, al ; Anzahl Reststellen ; out leds, al ; Kontrollausgabe jcxz v3 ; fertig? v2: mov byte [di], ' ' ; Rest loeschen dec di loop v2 ; fertig? v3: ret ; Initialisierung Controller und Interruptsystem init: cli ; Interrupts aus ; PIT-Init. mov al, 01110110b ; Kanal 1, Mode 3, 16-Bit ZK out pitc, al ; Steuerkanal mov al, tcpwm & 0ffh ; Low-Teil Zeitkonstante out pit1, al mov al, tcpwm >> 8 ; High-Teil Zeitkonstante out pit1, al ; PPI-Init. mov al, 10001011b ; PPI A/B/C Mode 0, A Output, sonst Input out ppi_ctl, al jmp short $+2 ; I/O-Delay mov al, 0 ; LED's aus (high aktiv) out ppi_a, al ; PIC-Init. mov al, 00010011b ; ICW1, ICW4 benoetigt, Bit 2 egal, ; Flankentriggerung out icw_1, al jmp short $+2 ; I/O-Delay mov al, 00001000b ; ICW2, auf INT 8 gemapped out icw_2_4, al jmp short $+2 ; I/O-Delay mov al, 00010001b ; ICW4, MCS-86, EOI, non-buffered, ; fully nested out icw_2_4, al jmp short $+2 ; I/O-Delay mov al, 11111110b ; Kanal 0 am PIC demaskieren ; PIT K1 out ocw_1, al ; Interrupttabelle init. mov word [intab0], isr_servotimer ; Interrupttabelle (Timer K1) ; initialisieren (Offset) mov [intab0 + 2], cs ; (Segmentadresse) sti ; ab jetzt Interrupts ret isr_servotimer: ; Timer fuer Servo, besser exklusiv (CLI) push ax ; ... ; ... ; ... isr_servotimer_out: mov al, eoi ; EOI an PIC out ocw_2_3, al pop ax iret