Forum: Mikrocontroller und Digitale Elektronik Cortex M4E 16E Treiberprobleme


von Ferid M. (fried)


Lesenswert?

Hallo allesamt,

ich habe in einem Projekt ein Problem mit den Atmel IO Treibern, die 
einem zur Verfügung gestellt werden. Es handelt sich um ein an der Uni 
entwickeltes Board, dass für studentische Projekte genutzt werden soll 
und das ich gerade teste. Es sind einige Peripherigeräte angeschlossen 
für Ethernet, SD, CAN, ein Motortreiber und für die IO gibt es Rotary 
Encoder, ein Display und eine Taster-Matrix. Das Board benutzt den 
SAM4E16C mit FreeRTOS fürs Task Management.
Es wird AVR Studio 6.2 genutzt und ein SAM-ICE als Schnittstelle 
verwendet .

Das Problem an dem ich gerade hänge liegt bei der Taster-Matrix. Bei 
dieser wird jede Spalte von Knöpfen normal auf ein High Signal gezogen 
und an jeder Reihe abwechselnd ein Low Signal vom uC angelegt. Wenn ein 
Knopf gedrückt wird, dann wird das Signal der Spalte auf das Niveau der 
Reihe gezogen und dort lässt sich für einen kurzen Interval das Low 
Signal der Reihe auslesen.
Wenn an einer Spalte ein Low Signal erkannt wird, dann kann die Nummer 
des Knopfes aus Reihe und Spalte berechnet werden. Das ist die 
Funktionsweise.

Zum Einarbeiten habe ich zunächst den Code von jemand anderes 
übernommen, der mit der Vorgängerversion von dem Board gearbeitet hat, 
und damit ein bisschen getestet. Leider konnte ich mit meinem Code nur 8 
von 12 Knöpfen erkennen und mit dem Oszilloskop an einer Reihe gar kein 
Signal abgreifen. Es stellte sich heraus, dass für das Projekt das Model 
SAM4E16E verwendet wurde und dieser ein 144-pin uC ist. Ein paar Pins 
sind dort anders belegt, sodass ich das Projekt neu angelegt habe für 
den SAM4E16C.

Der gleiche Code, der in dem vorherigen Projekt noch zum Teil 
funktionierte liefert hier leider andere Ergebnisse. Es lassen sich nun 
wie erwartet alle Reihen richtig ansprechen und die angelegten 
Signalverläufe entsprechen den Erwarnten (mit dem Oszilloskop getestet). 
Wenn die IO-Funktion "ioport_get_pin_level" benutzt wird liefert diese 
immer das gleiche (High Level) Ergebnis, obwohl beim direkten Messen der 
Leitung etwas anderes angezeigt wird.

Die genau Position des Problems wäre also die Abfrage: val_col = 
ioport_get_pin_level(BUTTON_COL1);   , da diese immer ein High Pegel 
ausgibt, auch wenn ein Low Pegel anliegt. Wenn der Pin als Ausgang 
geschaltet ist, lässt sich dort problemlos ein Low Pegel ansetzen.

Falls jemand eine Idee hat, wie sich das Verhalten erklären lässt, wäre 
ich sehr dankbar für Hinweise. Ich erkläre gerne weitere Punkte, falls 
noch etwas unklar ist.
1
 #include <asf.h>
2
#include <string.h>
3
#include <stdint.h>
4
#include "conf_board.h"
5
#include "IO_PINS.h"
6
7
/***************Defines for the tasks****************************/
8
xQueueHandle QueueButtons;
9
10
xTaskHandle task_buttonreaction ;
11
xTaskHandle task_buttons ;
12
13
void task_Buttons(void *pvParameters);
14
void task_ButtonReaction(void *pvParameters);
15
16
17
void task_Buttons(void *pvParameters){
18
  unsigned char val_col = 1;
19
  char butten_number=0, old_button1=0, old_button2=0, old_button3=0, old_button4=13, row=0;
20
  while(1){
21
    for (int col=0;col<=2;col++){
22
      val_col=1;
23
      switch (col){  
24
        case 0: val_col = ioport_get_pin_level(BUTTON_COL1);  break;
25
        case 1: val_col = ioport_get_pin_level(BUTTON_COL2);  break;
26
        case 2: val_col = ioport_get_pin_level(BUTTON_COL3);  break;
27
      }
28
      
29
      if(!(val_col==0)){                  // When val_col==0 a button was pressed
30
        butten_number=(row)*3+(col+1);          // Calculates the button number (1-12) by row+column
31
      }
32
    }
33
    
34
    // Resets the ROW-pins to "1"
35
    switch (row){
36
      case 0: ioport_set_pin_level(BUTTON_ROW1,IOPORT_PIN_LEVEL_HIGH); break;
37
      case 1: ioport_set_pin_level(BUTTON_ROW2,IOPORT_PIN_LEVEL_HIGH); break;
38
      case 2: ioport_set_pin_level(BUTTON_ROW3,IOPORT_PIN_LEVEL_HIGH); break;
39
      case 3: ioport_set_pin_level(BUTTON_ROW4,IOPORT_PIN_LEVEL_HIGH); break;
40
    }
41
    // Selects next row and sets the level of this row to "0"
42
    if (row==3)  { row=0; } else { row++; }
43
      
44
    switch (row){
45
      case 0: ioport_set_pin_level(BUTTON_ROW1,IOPORT_PIN_LEVEL_LOW); break;
46
      case 1: ioport_set_pin_level(BUTTON_ROW2,IOPORT_PIN_LEVEL_LOW); break;
47
      case 2: ioport_set_pin_level(BUTTON_ROW3,IOPORT_PIN_LEVEL_LOW); break;
48
      case 3: ioport_set_pin_level(BUTTON_ROW4,IOPORT_PIN_LEVEL_LOW); break;
49
    }
50
    vTaskDelay(1);
51
  }
52
}

von W.S. (Gast)


Lesenswert?

Ferid Mahdi schrieb:
> Wenn die IO-Funktion "ioport_get_pin_level"...

Könntest du eventuell mal versuchen, die benötigten HW-Ressourcen direkt 
anzusprechen und dir dabei zugleich einen Gedanken zu machen, wieviel 
Zeit zum Einschwingen der Signale von und zu den Tasten tatsächlich 
vonnöten ist, bevor man beim Abfragen den tatsächlichen Zustand 
herauskriegen kann?

Jedes Vorhaben - auch das Abfragen von Bedientasten - bedarf einer 
Strategie, also eines Gedanken, WIE zum Kuckuck man das 
bewerkstelligen will. Deine scheint nicht zu taugen, also bemühe deine 
grauen Zellen um eine bessere Strategie.

W.S.

von Gerhard (Gast)


Lesenswert?


von Ferid M. (fried)


Lesenswert?

Die Einschwingungszeit, wenn ein neuer Pegel angesetzt wird liegt 
zwischen 50-100ns (gemessen) und damit 4 Größenordnungen unter dem 
angesetzten Zeitraum von 1ms, der gewartet wird, bis das Signal 
abgegriffen wird. Nach Datenblatt werden nur minimale Werte für High und 
Low Level Pulse Rise/Fall-Time angegeben welche dort für die Pin Groups 
bei ~ 10-20ns liegen, also kommt das gut hin.

Der gleiche Code funktioniert in einem vorherig erstellten Projekt, auch 
wenn er nicht die unbedingt gut und schön ist, sollte er durch die 
Portierung nicht sein Verhalten komplett ändern... Es kann gut sein, 
dass der Fehler an einer ganz anderen Stelle ist und die Frage deswegen 
hier nichts zu suchen hat. Da ich es derzeit leider nicht genau weiß, 
wollte ich fragen, ob jemanden ein Problem mit den IO Funktionen 
geläufig ist.

von Ferid M. (fried)


Lesenswert?

Das Problem ist jetzt wohl gelöst. Aus dem  Atmel Studio 6.1 Projekt 
waren noch configs für ein anderes Board (EK) vorhanden, wodurch die 
unterschiedliche Pinbelegung zustande kam. Mit angepasster 
Initialisierung hat es dann funktioniert. Auch wenn der Code für die 
Taster nicht der Beste ist, ging es nur darum rudimentale Funktionalität 
zu zeigen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.