OK, so schlau werd ich aus diesem Ding auch net :S
Also, ich hab mich mal hingesetzt und etwas zusammengespielt:
Das ganze Programm beruht auf eine etwas andere Art und Weise, wie du es machen wolltest:Code:;usefull Macros and defines list p=16F84A ; list directive to define processor #include <p16F84A.inc> ; processor specific variable definitions movlf MACRO register, literare movlw literare movwf register ENDM #define clock D'156' ;memory CBLOCK 20h c_timer ;starts with 10 and ends with 20, ;and together with timer0 it'll ;generate "interrupts" in an intervalle between 1ms ;and 2ms t_timer W_TEMP STATUS_TEMP ENDC ;data org 0x000 goto main org 0x004 goto interrupt interrupt ;backup important registers movwf W_TEMP ; Copy W to TEMP register, swapf STATUS, W ; Swap status to be saved into W movwf STATUS_TEMP ; Save status to STATUS_TEMP register ISR ;Was it a PORTB-Interrupt? btfsc INTCON,0 call portb_int ;Was it the timer? btfsc INTCON,2 call timer_int swapf STATUS_TEMP, W ; Swap nibbles in STATUS_TEMP register ; and place result into W movwf STATUS ; Move W into STATUS register ; (sets bank to original state) swapf W_TEMP, F ; Swap nibbles in W_TEMP and place result in W_TEMP swapf W_TEMP, W ; Swap nibbles in W_TEMP and place result into W retfie ;the portb-interrupt function portb_int bcf INTCON,3 ;test, if we have 20 in the c_timer register movfw c_timer sublw D'20' BZ port_is_null incf c_timer return port_is_null movlf c_timer,D'10' return ;the timer-interrupt function timer_int bcf INTCON,2 ;test if t_temp = c_temp movlf TMR0,clock movfw t_timer subwf c_timer,W BNZ timer_not_ready clrf t_timer banksel PORTA btfss PORTA,0 goto set_it bcf PORTA,0 return set_it bsf PORTA,0 return timer_not_ready incf t_timer return ;the main routine main ;Because we are using a 4MHz PIC, ;we will get set timer0 to a prescale of ;to get an overflow every 100µs. movlf c_timer,D'10' banksel OPTION_REG clrf OPTION_REG ;setup PORTB banksel PORTB clrf PORTB clrf PORTA banksel TRISB movlf TRISB,B'00010000' ;all Ports except rb.4 are outputs ;and should be pulled to GND or VCC clrf TRISA ;enable Interrupts for timer0 and Portb-changes movlf INTCON,B'10101000' banksel TMR0 movlf TMR0,clock ;do nothing, interrupts make the rest loop goto loop end
Ich benutzt den timer0 mit einem Prescale von 1 (d.h. alle 1 µs eine erhöhung des TMR0's) und lade 156 (d.h. 100 µs bis zu einem overflow) in den TRM0. Danach setzt ich zwei Interrupts, eines ist der Timer selber, das Andere PortB.4 low --> high (c_timer 10 --> 20).
Wenn ein Timer interrupt passiert, checke ich mit einer Laufvariable von (10 --> 20 in 1er Schritten), wie viele µs ich schon hinter mir habe und wenn es = c_timer (counter_timer) ist, invertire ich das Bit PORTA.0 und lösche den t_timer register (temporary_timer). Wenn es dies nicht ist, erhöhe t_timer einfach um eines und verlasse den Interrupt.
Wenn ein PortB-change interrupt auftritt, schaue ich, ob c_timer = 20 ist, wenn ja dann wird c_timer = 10, wenn nicht, erhöhe ich c_timer um eins (1).
Dadurch dass der timer jeden 100µs überläuft und der software-prescale (ich nenn solche Laufvariablen halt so) 10-20 ist, erreiche ich eine Wartezeit von 1 ms --> 2ms in 100µs Schritten.
Leider habe ich mit Servos nicht viel am Hut, aber ich skiziere mal, was für einen Bild du mit einem Osci am Pin PORTA.0 erhälst (PortA musste ich deshalb wählen, weil beim Simulator irgendwie kein Interrupt ankam, wenn ich immer PORTB.0 verändert habe... interessant, ist aber so :-/ )
MfGCode:+-----1000µs-----+-----1000µs-----+-----1000µs-----+ |----------------| -----------------| |-----------------
Mobius
€dit: ich habe den Code nur im Simulator von MPLAB getestet, d.h. ich kann nicht wirklich viel über das Timing aussagen, außer, dass es stimmen müsste.
€€dit: na, wieder einmal ein Beispiel gebracht, wie ein Code NICHT aussehen sollte ^^ Layout war noch nie meine Stärke gewesen...







Zitieren

Lesezeichen