Anschluss von Peripherien

Transcription

Anschluss von Peripherien
Anschluss von Peripherien
2008 Jiri Spale, Programmierung eingebetteter Systeme
1
Tastenmatrix
Anschluss von vielen Tasten
→ zyklische Abfrage im Zeitmultiplexverfahren
Anordnung der Tasten: m x n Matrix, angestrebt: m ≈ n
Spaltentreiber
Spaltentreiber = Ausgabeport
Zeilerleser
= Eingabeport
pull-up-Widerstände:
extern oder intern (zuschaltbar in MCU)
netX: interne nicht-zuschaltbare
Zeilen- pull-down-Widerstände
leser
!!!
Erkennung von max. 2 Tasten!
(braun=log.0)
2008 Jiri Spale, Programmierung eingebetteter Systeme
2
Abfrage mit Interrupts #1
1. PIOs des Spaltentreibers auf log.0
2. Taste gedrückt →
Int durch log.0 ausgelöst,
ISR startet.
Für jeden Eingangs-PIO eigene ISR
Bei MCUs mit Tiefschlafmodus sogar
ruhestromfreie Abfrage möglich
(Fernbedienungen):
Erst durch Int weckt der MCU aus dem
Schlaf und startet den Oszi
2008 Jiri Spale, Programmierung eingebetteter Systeme
3
Abfrage mit Interrupts #2
3. PIOs des Spaltentreibers gehen in log.1
4. Abfrage beginnt:
PIO1
PIO2
PIO3
PIO4
5. Taste erkannt
6. Erkennen des Loslassens aller Tasten:
Alle PIOs der Spaltentreibers log.0
Losgelassen:alle PIOs des Zeilentreibers log.1
Während der Abfrage müssen andere PIOs
des Spaltentreibers hochohmig sein
(keine „harte“ log. 1), oder müssen in
Einganbemodus geschaltet werden
Treiberausgänge darf man nicht kurzschließen!
2008 Jiri Spale, Programmierung eingebetteter Systeme
4
2 gedrückte Tasten erkennen
a) Beide Tasten in einer Spalte:
mehr als 1 Zeile aktiv
b) Beide Tasten in einer Zeile:
fortwährende Spaltenabfrage
c) 2 Zeilen und 2 Spalten aktiv:
2 Tasten können noch erkannt werden,
eine 3. Taste nicht mehr
Bsp:
(2,2) und (3,3) gedrückt
Falls die 3. Taste (2,3) oder (3,2) wäre,
könnte sie nicht erkannt werden, da
Spalte 2 und 3 sowir Zeile 2 und 3
kurzgeschlossen
2008 Jiri Spale, Programmierung eingebetteter Systeme
5
3 beliebige Tasten gleichzeitig
Keine Kurzschlüsse durch mehrfache
Tastendrücke möglich
Ein reines Ausgabeport als Spaltentreiber
möglich
(tri-state unnötig)
In der Software kann entschieden werden,
ob tatsächlich alle Tastenkombinationen
ausgewertet werden
Entkopplungsdioden
2008 Jiri Spale, Programmierung eingebetteter Systeme
6
Bei zu wenig PIOs
Abfrageschema wie oben, nur dass
Die gerade aktivierte Spalte immer
als aktive Zeile zurückkommt.
Folge: Sie muss ausmaskiert werden.
Nur die restlichen Spalten dürfen
Ausgewertet werden
Verzicht auf Hauptdiagonale
Begrenzungen:
• Nur 1 Taste kann erkannt werden
• Schlafmodus geht nicht
2008 Jiri Spale, Programmierung eingebetteter Systeme
7
Bei zu wenig PIOs ohne Dioden
Zwischen jeder Kombination von Portpins
sowie nach Masse gibt es genau
1 Taste
Zustände:
1. Keine log.0 geschickt:
1 Taste der 1. Spalte kann erkannt w.
2. Log.0 auf die 1 Zeile geschickt:
1 Taste der 2. Spalte kann erkannt w.
3. usw.
Verzicht auf halbe Matrix
Begrenzungen:
• Nur 1 Taste kann erkannt werden
• Schlafmodus geht nicht
2008 Jiri Spale, Programmierung eingebetteter Systeme
8
Entprellung
Mechanische Schalter "prellen" beim Ein- und Ausschalten.
Zur Beseitigung gibt es unterschiedliche Ansätze
2008 Jiri Spale, Programmierung eingebetteter Systeme
9
Hardware-Entprellung
Möglichkeiten z.B.
• Tiefpassfilter mit nachgeschaltetem Schmitt-Trigger
• Umschaltkontakt + RS-Flipflops (aus zwei NAND-Gattern)
Der Schalter muss vom Typ "nicht kurzschließend" sein.
2008 Jiri Spale, Programmierung eingebetteter Systeme
10
Software-Entprellung:
Flankenerkennung#1
Bei einem Taster gibt es insgesamt 4 Zustände:
1. war nicht gedrückt und ist nicht gedrückt
2. war nicht gedrückt und ist gedrückt (steigende Flanke)
3. war gedrückt und ist immer noch gedrückt
4. war gedrückt und ist nicht mehr gedrückt (fallende Flanke)
Diese einzelnen Zustände lassen sich jetzt bequem abfragen/durchlaufen.
Die Entprellung geschieht dabei durch die ganze Laufzeit des Programms.
Taster als Active-Low angeschlossen, Pull-Ups genutzt.
2008 Jiri Spale, Programmierung eingebetteter Systeme
11
Flankenerkennung #2
für den Zustand "steigende Flanke" wird Wert "1" zurückgegeben, sonst "0"
char taster(void) {
static unsigned char zustand;
char rw = 0;
//Taster wird gedrueckt (steigende Flanke)
if(zustand == 0 && !(TASTERPORT & (1<<TASTERBIT))) {
zustand = 1; rw = 1;
}
//Taster wird gehalten
else if (zustand == 1 && !(TASTERPORT & (1<<TASTERBIT))) {
zustand = 2; rw = 0;
}
//Taster wird losgelassen (fallende Flanke)
else if (zustand == 2 && (TASTERPORT & (1<<TASTERBIT))) {
zustand = 3; rw = 0;
}
//Taster losgelassen
else if (zustand == 3 && (TASTERPORT & (1<<TASTERBIT))) {
zustand = 0; rw = 0;
}
return rw;
}
2008 Jiri Spale, Programmierung eingebetteter Systeme
12
SW-Entprellung: Warteschleifenverfahren
/* Einfache Funktion zum Entprellen eines Tasters */
UINT8 debounce(volatile UINT8 *port, UINT8 pin) {
if ( ! (*port & (1<<pin)) ){//Falls Pin auf Masse gezogen,100ms warten
_delay_ms(100);
if ( *port & (1 << pin) ){ //Falls Pin wieder high, warten
/* Anwender Zeit zum Loslassen des Tasters geben */
_delay_ms(100);
return 1;
}
}
return 0;
}
int main(void) {
PORTCONF &= ~( 1 << PB0 ); // PIN PB0 auf Eingang (Taster)
if (debounce(&PINB, PB0))
// Falls Taster an PIN PB0 gedrueckt..
PORTD = PIND ^ (1<<PD7);//..LED an Port PD7 an- bzw. ausschalten
}
2008 Jiri Spale, Programmierung eingebetteter Systeme
13
SW-Entprellung: Interruptverfahren
Schnell, kurzer Code, zuverlässig
ISR( TIMER0 )
// every 10ms {
static UINT8 ct0, ct1, rpt;
UINT8 i;
TCNT0 = ...
// preload for 10ms
i = key_state ^ ~KEY_PIN;
// key changed ? (^…XOR)
ct0 = ~( ct0 & i );
// reset or count ct0
ct1 = ct0 ^ (ct1 & i);
// reset or count ct1
i &= ct0 & ct1;
// count until roll over ?
key_state ^= i;
// then toggle debounced state
key_press |= key_state & i;
// 0->1: key press detect
if( (key_state & REPEAT_MASK) == 0 ) // check repeat function
rpt = REPEAT_START;
// start delay
if( --rpt == 0 ){
rpt = REPEAT_NEXT;
// repeat delay
key_rpt |= key_state & REPEAT_MASK;
}
}
2008 Jiri Spale, Programmierung eingebetteter Systeme
14
7-Segment-LEDs
Ziffernkodierung z.B.
00011000 // 0
11011110 // 1
00110010 // 2
01010010 // 3
11010100 // 4
01010001 // 5
00010001 // 6
11011010 // 7
00010000 // 8
01010000 // 9
• Zeitmultiplexverfahren via Warteschleifen oder Interrupts
• Ganze Ziffern mit log.0 aktiviert, einzelne Segmente ebenfalls mit log.0.
• Flackern vermeiden: ganze Zahl min. 50 mal pro Sekunde wiederholen
• Empfohlen: alle 4 ms zur nächsten Anzeigestelle weiterschalten
2008 Jiri Spale, Programmierung eingebetteter Systeme
15
Schrittmotoren
Arten:
• Bipolar
4 Anschlüsse
(mittlere Anschl. nicht vorhanden)
• Unipolar
6 Anschlüsse
• Im Bild: 1 Schritt=90°, 4 Vollschritte oder 8 Halbschritte für ganze Umdrehung
• Oft:
1 Schritt = 1,8°, 200 Vollschritte oder 400 Halbschritte pro Umdrehung
• Im Praktikum:
1 Schritt = 0,9°, 400 Vollschritte oder 800 Halbschritte pro Umdrehung
Oft eingesetzt: Robotik
2008 Jiri Spale, Programmierung eingebetteter Systeme
16
Schrittmotoren: Arten
2008 Jiri Spale, Programmierung eingebetteter Systeme
17
Bipolare Schrittmotoren: Ansteuerung
2008 Jiri Spale, Programmierung eingebetteter Systeme
Voll
A
B
C
D
Schritt 1
+
-
+
-
Schritt 2
-
+
+
-
Schritt 3
-
+
-
+
Schritt 4
+
-
-
+
Halb
A
B
C
D
Schritt 1
+
-
Schritt 2
+
-
+
-
Schritt 3
frei
frei
+
-
Schritt 4
-
+
+
-
Schritt 5
-
+
Schritt 6
-
+
-
+
Schritt 7
frei
frei
-
+
Schritt 8
+
-
-
+
18
frei frei
frei frei
Unipolare Schrittmotoren: Ansteuerung
Voll
A
B
common
C
D
common
Schritt 1
+
frei
-
frei
+
-
Schritt 2
+
frei
-
+
frei
-
Schritt 3
frei
+
-
+
frei
-
Schritt 4
frei
+
-
frei
+
-
2008 Jiri Spale, Programmierung eingebetteter Systeme
19
C-Spezialitäten für embedded Welt #1
Modifizierer volatile
Benutzung: volatile typ name;
Mitteilung an Compiler: Variable name kann durch Ereignisse außerhalb der
Kontrolle des Programms verändert werden kann, z.B. Lesen von Ports.
volatile-Variablen werden:
• vor jedem Zugriff neu aus dem Hauptspeicher eingelesen
• Compiler-Optimierung bei volatile abgeschaltet
• Zwischenspeicherung von volatile-Variablen in Registern (was sonst den
Ablauf beschleunigt) ist verboten
2008 Jiri Spale, Programmierung eingebetteter Systeme
20
C-Spezialitäten für embedded Welt #2
#define –Direktive mit Argumenten (genannt auch Makro)
#define POKE(addr, val)(*(volatile unsigned int *)(addr) = (val))
Bsp.
Präprozessorbefehl POKE (REG1, 0xFFEFU)
(U für unsigned)
wird ersetzt durch
*(volatile unsigned int *)REG1 = 0xFFEFU
Bedeutet:
• REG1 ist Zeiger, gecastet in volatile unsigned int *
• Die Dereferenz von diesem Zeiger erhält neuen Wert von 0xFFEFU
Ähnlich:
#define POKE_AND(addr,val)(*(volatile unsigned int*)(addr)&=(val))
#define POKE_OR(addr,val)(*(volatile unsigned int*)(addr)|=(val))
#define PEEK(addr)(*(volatile unsigned int*)(addr))
2008 Jiri Spale, Programmierung eingebetteter Systeme
21
C-Spezialitäten für embedded Welt #3
Datentypen benutzt vom StartEasy
Für Registeradressen:
#define REG8 (volatile unsigned char*)
#define REG16 (volatile unsigned short*)
#define REG32 (volatile unsigned int*)
Für Registerwerte:
#define UI32
unsigned int
2008 Jiri Spale, Programmierung eingebetteter Systeme
22
C-Spezialitäten für embedded Welt #4
Bitmanipulationen
i-tes Bit von rechts im Register REG löschen (andere Bits unverändert):
POKE_AND(REG, ~(1 << i));
oder
*REG &= ~(1 << i));
i-tes Bit von rechts im Register REG setzen (andere Bits unverändert):
POKE_OR(REG, 1 << i);
oder
*REG &= 1 << i;
2008 Jiri Spale, Programmierung eingebetteter Systeme
23