Hallo Forum,
mein BF537 stellt mich gerade vor ein Kuriosum. Es geht dabei um den
Port F (PF2 bis PF5) GPIO über den ich die Taster von meinem EZ-Kit auf
steigende Flanke prüfen möchte. Im ersten Schritt konfigurierte ich die
betreffenden Pins des GPIO's:
1 | void Init_Flags(void)
|
2 | {
|
3 | // ...
|
4 | *pPORTF_FER = 0x0000;
|
5 | *pPORTF_FER = 0x0000;
|
6 |
|
7 | // set PORTF direction register
|
8 | *pPORTFIO_DIR = 0x1FC0;
|
9 | //EZ-Kit switches as Input (PF5..2), LEDs (PF6..11) as Output
|
10 |
|
11 | // set PORTF input enable register
|
12 | *pPORTFIO_INEN = 0x003C;
|
13 | //EZ-Kit switches enable Input (PF5..2), LEDs as Output (PF6..11)
|
14 |
|
15 | //set PORTF polarization register
|
16 | *pPORTFIO_POLAR = 0x0020;
|
17 | //EZ-Kit switch SW10 is active low (bypass switch)
|
18 |
|
19 | //set PORTF edge register
|
20 | *pPORTFIO_EDGE = 0x001C;
|
21 | //EZ-Kit switches SW11-13 are rising edge sensitive
|
22 |
|
23 | // set PORTF clear register
|
24 | *pPORTFIO_CLEAR = 0x0FC0 & 0x0FC0;
|
25 | //EZ-Kit LEDs off
|
26 | }
|
Hier geht es erstmal um den Switch SW11 und SW12 (PF4 und PF3) zum
testen. Anschließend strickte ich mir eine einfache Abfrage in der die
LED1 mit SW11 an und mit SW12 wieder ausgeschaltet werden sollte:
1 | //...
|
2 | #define FUNCTION 4
|
3 | #define DOWN 3
|
4 | // ...
|
5 |
|
6 | void main(void)
|
7 | {
|
8 | Init_Flags();
|
9 | // ...
|
10 |
|
11 | while(1)
|
12 | {
|
13 | if( *pPORTFIO & (1 << FUNCTION) ) // rising edge?
|
14 | {
|
15 | *pPORTFIO_SET = (1 << 6) & 0x0FC0; // LED6 on
|
16 | *pPORTFIO_CLEAR = (1 << FUNCTION); // (1)
|
17 | }
|
18 | else if( *pPORTFIO & (1 << DOWN) )
|
19 | {
|
20 | *pPORTFIO_CLEAR = (1 << 6) & 0x0FC0; // LED6 off
|
21 | *pPORTFIO_CLEAR = (1 << DOWN); // (1)
|
22 | }
|
23 | }
|
24 | }
|
(1) "For GPIOs configured as edge-sensitive, a readback of 1 from one
of these registers is sticky. That is, once it is set it remains set
until cleared by user code. [...]" (Hardware Reference page 14-12)
Das funktionierte leider nicht. Die LED geht weder an (und
logischerweise auch nicht wieder aus ;^) ). Also versuchte ich es
hiermit:
1 | //...
|
2 | #define FUNCTION 4
|
3 | #define DOWN 3
|
4 | // ...
|
5 |
|
6 | void main(void)
|
7 | {
|
8 | Init_Flags();
|
9 | // ...
|
10 |
|
11 | while(1)
|
12 | {
|
13 | if( *pPORTFIO & (1 << FUNCTION) ) // rising edge?
|
14 | {
|
15 | *pPORTFIO_SET = (1 << 6) & 0x0FC0; // LED6 on
|
16 | }
|
17 | else if( *pPORTFIO & (1 << DOWN) )
|
18 | {
|
19 | *pPORTFIO_CLEAR = (1 << 6) & 0x0FC0; // LED6 off
|
20 | }
|
21 |
|
22 | *pPORTFIO_CLEAR = (1 << FUNCTION);
|
23 | *pPORTFIO_CLEAR = (1 << DOWN);
|
24 | }
|
25 | }
|
Und siehe da, es klappt; Aber nicht perfekt, d.h. manchmal mit etwas
Verzögerung - eher marginal, aber für einen 600MHz Prozessor doch
deutlich zu langsam. Lösche ich die pPORTFIO_CLEAR Register nicht so
bleibt die LED (wie zu erwarten) an, nehme ich die "else"-Anweisung weg
dann flackert sie - das macht alles Sinn. Ich sollte noch erwähnen, dass
ein Interrupt mit 48kHz ausgelöst wird in dem bisher ein paar einstufige
IIR's und ein mächtiger 1300er FIR durchgezogen werden (alles fractional
1.15). Wo liegt der Fehler? Habe ich etwas übersehen/vergessen zu
setzen?
pumpkin
Edit:
Was mich stutzig macht ist der folgende Abschnitt in der Hardware
Reference (page 1-11):
"GPIO interrupt sensitivity registers – The two GPIO interrupt
sensitivity
registers specify whether individual pins are level- or edge-sensitive
and specify—if edge-sensitive—whether just the rising edge or both the
rising and falling edges of the signal are significant. One register
selects the type of sensitivity, and one register selects which edges
are significant for edge-sensitivity."
Plötzlich ist von Interrupt-Registern die Rede (sicher kann man damit
welche auslösen, aber ist das nicht etwas inkonsistent formuliert?).