OK, so schlau werd ich aus diesem Ding auch net :S
Also, ich hab mich mal hingesetzt und etwas zusammengespielt:
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
Das ganze Programm beruht auf eine etwas andere Art und Weise, wie du es machen wolltest:
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 :-/ )
Code:
+-----1000µs-----+-----1000µs-----+-----1000µs-----+
|----------------|
-----------------| |-----------------
MfG
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...
Lesezeichen