Podzielę się tu problemami jakie napotkałem przy pisaniu tego programu. A nuż się komuś przyda.
Najpierw kilka informacji o samych sygnałach jakie pojawiają się na wyjściu modelarskiego odbiornika RC. Są to impulsy o dł. w zakresie 800-2200us (standard to 1000-2000us) a wartość 1500us to pozycja "Zero" czyli "Neutrum". W przypadku odbiornika 6-kanałowego impulsy pojawiają się kolejno (bez przerwy pomiędzy nimi) od kanału pierwszego do szóstego, a następnie jest przerwa synchronizująca wypełniająca czas ramki do 20ms. Widać to na rysunku. I tu napotkałem pierwszy kłopot: Jak kończy się impuls na którymś kanale to na następnym się pojawia. Wcześniej napisałem, że następuje to bez przerwy- ściśle mówiąc przerwa tam jest. W moim przypadku (aparatura Taranis) ta przerwa ma 2us.
Żeby sprawdzić jak PCINT sobie z tym poradzi napisałem prosty program, który wyglądał podobnie jak ten, z tym że tam po przekroczeniu "Neutrum" była zmiana stanu odpowiedniego wyjścia.
Code: [Zaznacz cały] [Rozwiń/Zwiń]
- $regfile = "attiny25.dat"
- $crystal = 8000000
- $hwstack = 40
- $swstack = 16
- $framesize = 32
- Dim P As Byte 'długość impulsu dla kanału A
- Dim Q As Byte ' zmienna pobrana z ADC
- Dim R As Byte 'długość impulsu dla kanału B
- Dim A As Bit 'bit dla identyfikacji przerwań PCINT
- Dim B As Bit 'j.w.
- Dim C As Bit 'bit zezwalający na skok do podprogramu Obliczenia
- Config Portb = &B11111000 'PB0 wej Kanał A, PB1 wej Kanał B, PB2 wej ADC
- Portb = &B11100000 'PB3 wyj nr1, PB4 wyj nr2.
- Enable Pcint0
- On Pcint0 Pomiar
- Pcmsk = &B00000011 'przerwanie aktywne dla wejść PB0 i PB1
- Enable Interrupts
- Config Timer0 = Timer , Prescale = 64
- Config Timer1 = Timer , Prescale = 64 'krok 8us
- Config Adc = Single , Prescaler = Auto ,
- Start Adc
- Do
- If C = 1 Then Gosub Obliczenia
- Loop
- End
- Pomiar:
- 'dla kanału A
- If A = 1 Then 'jeśli poprzednie przerwanie było z wej PB0
- Stop Timer0 'zatrzymaj timer1
- A = 0 'wyzeruj A
- End If
- If Pinb.0 = 1 Then 'jeśli pojawi się impuls na wej PB0
- Start Timer0 'włącz timer0
- A = 1 'zapamiętaj że z tego wejścia było przerwanie PCINT
- End If
- 'dla kanału B
- If B = 1 Then 'jeśli poprzednie przerwanie było z wej PB1
- Stop Timer1 'reszta jak wyżej
- B = 0
- End If
- If Pinb.1 = 1 Then 'jeśli pojawi się impuls na wej PB1
- Start Timer1
- B = 1 'zapamiętaj że z tego wejścia było przerwanie PCINT
- C = 1 'zainicjuj skok do podprogramu Obliczenia
- End If
- Return
- Obliczenia:
- C = 0 'skasuj bit skoku do podprogramu
- P = Timer0 'przepisz wartości timerów do zmiennych
- Timer0 = 0
- R = Timer1
- Timer1 = 0
- 'tutaj można wstawić operacje na uzyskanych wartościach
- Return
Kilka uwag do listingu: jest tam uruchomiony przetwornik ADC bo go potrzebuję do moich zadań. W przerwaniu od PCINT (Pomiar) najpierw jest warunek, który wyłącza timer a dopiero potem ten załączający. Tak musi być żeby natychmiast nie skasować bitu A (lub B) i zatrzymać timer. Czy ten program działał? I tak i nie Działał tylko w przypadku gdy podłączałem kanały, które nie były kolejnymi. Czyli np. K1 i K3, K1 i K4, K3 i K1, ale już K2 i K3 powodował, że program wariował. Na wyjściu pojawiały się dwa impulsy zamiast jednego itp. cuda. Poradziłem sobie z tym w taki sposób, że wprowadziłem dodatkowy warunek sprawdzający stany pinów i bitów A i B. To pomogło.
Code: [Zaznacz cały] [Rozwiń/Zwiń]
- 'dla kanału A
- If A = 1 And Pinb.0 = 0 Then 'jeśli poprzednie przerwanie było z wej PB0
- Stop Timer0 'zatrzymaj timer1
- A = 0 'wyzeruj A
- End If
- If Pinb.0 = 1 And A = 0 Then 'jeśli pojawi się impuls na wej PB0
- Start Timer0 'włącz timer0
- A = 1 'zapamiętaj że z tego wejścia było przerwanie PCINT
- End If
- 'dla kanału B
- If B = 1 And Pinb.1 = 0 Then 'jeśli poprzednie przerwanie było z wej PB1
- Stop Timer1 'reszta jak wyżej
- B = 0
- End If
- If Pinb.1 = 1 And B = 0 Then 'jeśli pojawi się impuls na wej PB1
- Start Timer1
- B = 1 'zapamiętaj że z tego wejścia było przerwanie PCINT
- C = 1 'zainicjuj skok do podprogramu Obliczenia
- End If
Zdaję sobie sprawę, że można to zrobić inaczej. Pewnie jest tyle rozwiązań ilu bascomowców ale to rozwiązanie jest najlepsze. Bo moje.