Hallo,
ich versuche grade drei RC Kanäle mit einem ATMega168 auszuwerten.
Dazu nutze ich die drei vorhandenen PinChange Interupts.
Also je RC Kanal einen anderen Port.
1
#define RX_PIN_B PINB
2
#define RX_PORT_B PORTB
3
#define RX_DDR_B DDRB
4
#define RX_1 0
5
6
#define RX_PIN_C PINC
7
#define RX_PORT_C PORTC
8
#define RX_DDR_C DDRC
9
#define RX_2 0
10
11
#define RX_PIN_D PIND
12
#define RX_PORT_D PORTD
13
#define RX_DDR_D DDRD
14
#define RX_3 2
15
16
volatileuint16_ttimerValue[3]={0,0,0};
17
volatileuint16_tchannel[3]={1500,1500,1500};
18
19
/* INIT */
20
21
RX_DDR_B&=~(1<<RX_1_B);
22
RX_DDR_C&=~(1<<RX_1_C);
23
RX_DDR_D&=~(1<<RX_1_D);
24
25
TCCR1B=_BV(CS11);
26
TIMSK1=0;
27
28
//PinChange Interupt an PB 0
29
PCMSK0|=(1<<PCINT0);
30
31
//PinChange Interupt an PC 0
32
PCMSK1|=(1<<PCINT8);
33
34
//PinChange Interupt an PD 2
35
PCMSK2|=(1<<PCINT18);
36
37
//enable pinchange interrupt;
38
PCICR|=((1<<PCIE2)|(1<<PCIE1)|(1<<PCIE0));
39
40
sei();
41
42
/* INIT ENDE */
43
44
ISR(SIG_PIN_CHANGE0)
45
{
46
uint16_ttimer=TCNT1;
47
48
if(RX_PIN_B&(1<<RX_1))
49
{
50
timerValue[0]=timer;
51
}
52
else
53
{
54
channel[0]=timer-timerValue[0];
55
}
56
}
57
58
ISR(SIG_PIN_CHANGE1)
59
{
60
uint16_ttimer=TCNT1;
61
62
if(RX_PIN_C&(1<<RX_2))
63
{
64
timerValue[1]=timer;
65
}
66
else
67
{
68
channel[1]=timer-timerValue[1];
69
}
70
}
71
72
ISR(SIG_PIN_CHANGE2)
73
{
74
uint16_ttimer=TCNT1;
75
76
if(RX_PIN_D&(1<<RX_3))
77
{
78
timerValue[2]=timer;
79
}
80
else
81
{
82
channel[2]=timer-timerValue[2];
83
}
84
}
Nun möchte ich gerne alle drei RC Kanäle an nur einem Port auswerten.
Da habe ich dann aber nur einen PinChange Interupt.
Hat jemand eine Idee wie ich das lösen kann?
Toby schrieb:> Nun möchte ich gerne alle drei RC Kanäle an nur einem Port auswerten.> Da habe ich dann aber nur einen PinChange Interupt.> Hat jemand eine Idee wie ich das lösen kann?
In der ISR den PIN-Zustand einlesen und mit einem vorhergehenden Zustand
vergleichen? Der Vergleich bringt zutage, welcher Pin sich verändert
hat.
Toby schrieb:> Hallo,>> nun bin ich so weit, das die ersten beiden Kanäle gehen.> Nur der dritte nicht. :-(>> [c]> ISR(SIG_PIN_CHANGE0)> {> uint16_t timer = TCNT1;> uint8_t rx_state = RX_PIN;> uint8_t i;>> i = rx_state | rx_state_old;
so kriegst du aber nicht die Pins raus, die sich VERÄNDERT haben!
Du brauchst ein XOR
i = rx_state ^ rx_state_old;
Jetzt hast du in i genau an den Stellen ein 1 Bit, an denen sich
rx_state von rs_state_old unterscheidet.
i sagt dir, welcher Pin den Pin Change Interrupt ausgelöst hat und
rx_state sagt dir, ob der Pin jetzt 0 oder 1 ist.
Ich würde auch das else überall weglassen. Wenn sich mal mehrere Pins
nahezu gleichzeitig ändern, bekommt man sonst nicht alle Änderungen mit,
da der Code ja nur dann was macht, wenn sich exakt einer der drei Pins
geändert hat.
Hallo,
Also in etwa so:
Wenn i = 1
Wenn rx_state = 1 Pulsmessung starten
Sonst Pulsmessung auswerten
Wenn i = 2
Wenn rx_state = 2
...
Wenn i = 4
Wenn rx_state = 4
...
Oder kann/muss ich i und rx_state nochmal vergleichen
Um den Flankenwechsel zu erkennen?
Wenn ich jeden 2. RC Kanal vom Empfänger nehme,
Hab ich ja eindeutige Pulslücken zwischen den Kanälen.
Nehme ich Kanal 1-3 hab ich keine Lücken.
Am Ende des 1. Pulses kommt sofort der zweite Puls.
Kann man das überhaupt Erkennen?
Gruß Toby
Entschuldigt die Schreibweise, aber geht mit dem Handy
so einfacher ;-)
Toby schrieb:> ich habs jetzt so gemacht und es funktioniert:
Gut,
Und wenn du jetzt noch deinen 'magischen Konstanten' 0x01, 0x02 ein paar
schöne Makrokonstanten spendierst, dann kann man das auch leicht auf
andere Pinbelegungen vom µC anpassen. Anstatt i noch einen vernünftigen
Variablennamen nehmen (Frage: Was bedeuten die Bits in dieser Variable?
Antwort: Das sind die Pins die sich verändert haben. Also sollte man
dann auch einen Namen wählen, der das ausdrückt)
1
#define RX_KANAL_1 PB0
2
#define RX_KANAL_2 PB1
3
#define RX_KANAL_3 PB2
4
5
....
6
7
pinsChanged=pinsNow^pinsPrevious;
8
9
if(pinsChanged&(1<<RX_KANAL_1))
10
{
11
if(pinsNow&(1<<RX_KANAL_1)
12
{
13
timerValue[0]=timer;
14
}
15
else
16
{
17
channel[0]=timer-timerValue[0];
18
}
19
}
20
21
if(pinsChanged&(1<<RX_KANAL_2))
22
{
23
if(pinsNow&(1<<RX_KANAL_2)
24
{
25
26
...
liest sich doch gleich viel besser. Je weniger man beim Code lesen
erraten oder sich merken muss, umso besser. Im Idealfall ist der Code
schon fast ein vollständiger Satz, dem lediglich ein paar Füllwörter
fehlen.
wenn sich der Pin gändert hat, an dem der RC Kanal 1 hängt
if( pinsChanged & (1<<RX_KANAL_1) )
Ist fast die gleiche Information, nur das das eine ein deutscher Satz
ist und das andere dasselbe in C ausdrückt.
Hallo Karl-Heinz,
Als ich den Beitrag abgeschickt habe, hatte ich auch noch den Gedanken
die Konstanten zu ändern.
Deine Ausführung ist da natürlich sehr elegant.
Gruß Toby
Eine eigene Frage?
Dieser Thread ist über 14 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.