Drehgeber auf extern Interuppt LPC ARM

Gast #1048433
Lesenswert?

So nun noch mal, habe dies schon mal gepostet, aber unter einer anderen 
nicht mit zutreffenden Überschrift. Ich möchte über einen Drehgeber 
einen externen Interupt auslösen. Hier folgender Code:
1
int zaehler = 0;
2
#define VPBDIV_VAL  0x02                   /*Setze Hardwaretimer[Pclk] auf 30 Mhz */
3

4
__irq void eint0 (void) {
5

6
  IOCLR0 = 0x00000100;                    /* Turn LED On  (P0.8 = 0) */  
7
  ++zaehler;
8
  EXTINT = 0x00000003;
9
  VICVectAddr = 0x0000000;                            // Acknowledge Interrupt
10
}
11
void init_extern(void) 
12
{
13
   /*VPBDIV muss(!!) man auf 0 gesetz werden bevor man ein(!) Register
14
  beschreiben kann*/
15
  // Hardwaretimer auf Null setzen
16
  VPBDIV=0;
17
  //Register kontrolliert falls
18
  EXTMODE = (1<<3);
19
  // Hardwaretimer wird auf 30 Mhz gesetzt 
20
  VPBDIV=VPBDIV_VAL;
21
  // Hardwaretimer auf Null setzen
22
  VPBDIV=0;
23
  // Register kontrolliert welcher Pin eine Flanke auslöst
24
  EXTPOLAR = ~(1<<3);  //fallende Flanke
25
  // Hardwaretimer wird auf 30 Mhz gesetzt 
26
  VPBDIV=VPBDIV_VAL;
27
   // ein Register per Interrupt
28
  VICVectCntl2 = (0x20 | 0x20000) ;
29
  //Vector wird Slot 2 zugewiesen
30
  VICVectAddr2 = (unsigned)eint0;
31
   //Aktiviert Interrupt Eingänge
32
  VICIntEnable = ( 0x20000 );
33
}
34
******** Hauptprogramm  **********/
35
int main (void)
36
{
37
  IODIR1 = 0x00FF0000; 
38
  PINSEL1|=(1<<29);      //P0.30 als EINT3
39
   PINSEL1&=~(1<<28);
40
    IODIR0 = 0x00000100;                     
41
     
42
  init_extern();
43
/*Programm in einer Endlosschleife*/
44
while (1)
45
  {     
46
     
47
  }
So sieht meine Start-Code aus:
1
I_Bit           EQU     0x80   ; when I bit is set, IRQ is disabled
2
F_Bit           EQU     0x40   ; when F bit is set, FIQ is disabled
3

4
UND_Stack_Size  EQU     0x00000000
5
SVC_Stack_Size  EQU     0x00000020
6
ABT_Stack_Size  EQU     0x00000000
7
FIQ_Stack_Size  EQU     0x00000000
8
IRQ_Stack_Size  EQU     0x00000080
9
USR_Stack_Size  EQU     0x00000400
Ich weiß nicht mehr weiter es will nicht laufen. Benutze auch schon 
einen Pull_Down Widerstand um wirklich auf low-Level zu sein!
Gast #1048501
Lesenswert?

@falk Sehr schön aber wie stelle ich das auf einem ARM board dar. Dort 
habe ich keine Funktion wie sei() oder cli()?

@Dannegger Ich benutze ein Board der Frima Phytec mit einem LPC2294 und 
einem Patch-Feld (HD200) und zu Testzwecken gebe ich nun auch meinen 
Port EINT3 (Port30) eine Spannung von 3.3 Volt drauf um zu sehen ob 
irgendetwas kommt, befor ich meinen Inkrementellen Drehgeber anschließe.
#1048514
Lesenswert?

Hotte wrote:

> @Dannegger Ich benutze ein Board der Frima Phytec mit einem LPC2294 und
> einem Patch-Feld (HD200) und zu Testzwecken gebe ich nun auch meinen
> Port EINT3 (Port30) eine Spannung von 3.3 Volt drauf um zu sehen ob
> irgendetwas kommt, befor ich meinen Inkrementellen Drehgeber anschließe.

Damit kann ich absolut garnichts anfangen.
Du mußt schon den richtigen Schaltplan malen.
D.h. wie ist der Drehgeber und die LED konkret angeschlossen.


Peter
#1048672
Lesenswert?

@ Peter, sorry mein Scanner hat den Geist aufgegeben, habe nun den 
Schaltplan fotografiert. Kann ich dir denn auch zu mailen, da die Datei 
viel zu groß ist? Ich bedanke mich auch schon mal für deine Mühe! Als 
LED benutze ich den Port 0.8 der auch auf dem Board festverdrahtet ist 
und auch voll funktionesfähig ist. Am Port 30 habe ich einen 10 kohm 
Widerstand mit der Masse verbunden:

 pos. Flanke 3.3 Volt
  |
  |
  --------------Eingang MC
  |
  |
  R1 10k[Pulldown]
  |
  GND
Nun gebe ich ganz einfach gehalten mit einem Kabel das den Drehgeber 
simulieren soll 3.3 Volt auf den Port 30.
Gast #1048844
Lesenswert?

Poste doch mal das vollständige Projekt. So kann das kein
Mensch nachvollziehen.

Es gibt so etwas wie cli()/sei() auf den ARM7 Controllern. Daran
soll es nicht scheitern. Im einfachsten Fall kannst du das interrupt
enable Flag für den Timer abschalten.
Ich versuche das jedoch zu vermeiden was mir bisher auch (fast)
immer gelungen ist. Ein Blick in das Listfile und in ein C-Buch
zum Thema 'volatile' zeigt das viele dieser cli()/sei() Orgien
unnötig sind. Das sei() ist in einer Abfrageroutine sogar gefährlich.
Ohne Timer wirst du das Prellen des Encoders aber kaum in den Griff
kriegen. Du könntest natürlich auch mit delays arbeiten aber
Abfragezeiten für einen Encoder im Bereich von ms sind bereits
auf langsameren Controllern unpraktisch. Bei Zyklenzeiten von
~20ns ist ein delay() in der Hauptschleife geradezu unverantwortlich.
#1048988
Lesenswert?

So ich glaube dass mit dem externen Interrupt lasse ich liebe, wei ich 
mir den Rat von Herrn Brunner zu Herzen genommen habe. Ich habe jetzt 
versucht das Code-Beispiel Drehgeber von Herrn Dannegger auf einen 
LPC2294 umzuschreiben. Könnte sich jeder mal den Code anschauen ob ich 
irgendwo einen Fehler gemacht habe, wäre verdammt nett von Euch.

Außerdem habe ich noch Verständnisprobleme mit dem Code:
1
if (enc_diff & 1)         // bit 0 = value (1)
2
{
3
enc_last = enc_new;       //speicher new als nächten Wert
4
enc_delta += (enc_diff & 2)-1; // bit 1 = direction (+/-)
5
}

Kann mir jemand mal ganz genau erklären, was ich mit dieser if-Anweisung 
genau mach!
Angehängte Dateien:
#1049154
Lesenswert?

Hotte Meyer wrote:
> LED benutze ich den Port 0.8 der auch auf dem Board festverdrahtet ist
> und auch voll funktionesfähig ist.

So, dann müßte man nur noch wissen, ob die LED gegen VCC oder GND 
geschaltet ist.

Hint:
Kontakte werden üblicher Weise gegen GND geschaltet, weil man dann den 
internen Pullup des MCs aktivieren kann.
LEDs werden üblicher Weise gegen VCC geschaltet.
Kontakte und LEDs sind also in der Regel Low-aktiv.

Ich hab nicht viel Erfahrung mit dem LPC. Ich hab da nicht so den 
richtigen Antrieb, einfache Sachen, die ein 8-Bitter spielend schafft, 
mit nem 32-Bit-Boliden zu machen.


Versuche mal schrittweise vorzugehen:
- LED schalten
- LED über Delayschleife blinken
- LED über Timer blinken
- LED über Timerinterrupt blinken
- LED über Eingangspin schalten
- LED über externen Interrupt schalten.

Danach solltest Du wissen, wo es klemmt.


Peter
Gast #1049284
Lesenswert?

Wenn das Programm im User Mode läuft kann man das CPSR Register
nicht verändern. Aber solange man kein spezielles OS benutzt
das den User Mode für seine Prozesse erfordert kann man die
Anwendung auch gleich im System Mode ausführen.

Ich sehe aber keinen Grund dafür weshalb man alle Interrupts
sperren sollte nur um den Timer-Interrupt zu unterdrücken/verzögern.

@Hotte Meyer:
Eine cli()/sei() Implementierung findest in den Blinky Beispielen von
WinARM.

Du könntest auch mal versuchen was dabei herauskommt wenn du
den Code
1
long encode_read1 (void)
2
{
3
  long val;
4

5
  val = enc_delta;
6
  enc_delta = 0;
7
  return val;
8
}
in diesen
1
long encode_read1 (void)
2
{
3
  static long prev;
4
  long val, tmp;
5

6
  tmp = enc_delta;
7
  val = tmp - prev;
8
  prev = tmp;
9

10
  return val;
11
}
abänderst.

Dann kann dir ruhig ein Interrupt dazwischenfunken, es wird nur einmal
in einem Zyklus auf enc_delta zugegriffen.
Ich habe das gerade mal durch den Compiler gejagt und kann keine
Race Condition erkennen.
#1049730
Lesenswert?

Meyer wrote:
> Habe den Code geändert, doch in der Funktion long encode_read1 (void)
> wird mir immer Null an mein Hauptprogramm übergeben und ich weiß nicht
> warum. Kann mir vielleicht jemand sagen wo mein Fehler liegt?
1
#define PHASE_A     0x00000800    // Port 11
2
#define PHASE_B    0x00002000    // Port 13

Zahlen sind keine Porteingänge, sondern nur Zahlen.
Und diese beiden Zahlen sind immer wahr.

Hast Du auch beide Pullups aktiviert oder Pullups angeschlossen?


Peter
#1050491
Lesenswert?

Erst einmal Danke an alle dir mir geholfen haben. Es läuft endlich mit 
vollster Zufriedenheit. Besonderen Dank an Herrn Dannegger der die 
Code-Vorlage bereit gestellt hat.
Meine letzten beiden Fehler waren 1. Zuweisung der Ports und 2. Abruf 
der Ports. Manchmal sieht man den Wald vor lauter Bäumen nicht.
Für alle die es interressiert hab ich meinen Code noch mal hochgeladen.

Schönen Abend noch, die nächsten Probleme kommen bestimmt. ;-)
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren