K |
K |
||
| Zeile 1: | Zeile 1: | ||
| − | Bietet ein Controller nicht genügend I/O-Leitungen, dann kann man Portexpander werwenden. Dadurch hat man zusätzliche Ports zur Verfügung. Neben [[I2C Chip-Übersicht|Portexpandern der I²C-Klasse]] oder SPI-Klasse bietet sich an, 8-Bit-Schieberegister zu kaskadieren und als Expander zu verwenden. Das ist oft ausreichend, weil mehr Ausgänge begraucht werden als Eingänge. Dabei verwendet man Schieberegister mit Ausgangs-Latch, d.h. die Daten werden erst dann an die Ausgänge geschaltet, wenn sie an Ort und Stelle sind. | + | Bietet ein Controller nicht genügend I/O-Leitungen, dann kann man Portexpander werwenden. Dadurch hat man zusätzliche Ports zur Verfügung. Neben [[I2C Chip-Übersicht|Portexpandern der I²C-Klasse]] oder [[SPI]]-Klasse bietet sich an, 8-Bit-Schieberegister zu kaskadieren und als Expander zu verwenden. Das ist oft ausreichend, weil mehr Ausgänge begraucht werden als Eingänge. Dabei verwendet man Schieberegister mit Ausgangs-Latch, d.h. die Daten werden erst dann an die Ausgänge geschaltet, wenn sie an Ort und Stelle sind. |
Falls man Eingänge benötigt, können auch Schieberegister mit Input-Latches ankaskadiert werden, welche die Eingänge von parallel nach seriell umsetzen (in diesem Artikel nicht näher beschrieben). | Falls man Eingänge benötigt, können auch Schieberegister mit Input-Latches ankaskadiert werden, welche die Eingänge von parallel nach seriell umsetzen (in diesem Artikel nicht näher beschrieben). | ||
| Zeile 12: | Zeile 12: | ||
* modular aufgebaut und erweiterbar | * modular aufgebaut und erweiterbar | ||
* '''alle''' Ports können '''gleichzeitig''' geschaltet werden, auch 100 Stück | * '''alle''' Ports können '''gleichzeitig''' geschaltet werden, auch 100 Stück | ||
| − | * SPI-Interface und ISP-Pins (die oft ungenutzt bleiben) können verwendet werden | + | * SPI-Interface und [[In System Programming|ISP-Pins]] (die oft ungenutzt bleiben) können verwendet werden |
* Bus hat nur 3 Leitungen, dadurch kein kompliziertes Layout mit vielen Leitungen | * Bus hat nur 3 Leitungen, dadurch kein kompliziertes Layout mit vielen Leitungen | ||
| Zeile 18: | Zeile 18: | ||
* bei dieser Version nur Ausgabe möglich | * bei dieser Version nur Ausgabe möglich | ||
* soll ein Ausgangs-Port geändert werden müssen ''alle'' Daten neu gesendet werden | * soll ein Ausgangs-Port geändert werden müssen ''alle'' Daten neu gesendet werden | ||
| − | * bei der Variante mit SPI-Hardware liegt MISO brach | + | * bei der Variante mit SPI-Hardware liegt MISO brach bzw ist nicht so einfach nutzbar zu machen |
=Resourcen= | =Resourcen= | ||
| Zeile 43: | Zeile 43: | ||
* Widerstände zum Entkoppeln vom ISP: einige kΩ | * Widerstände zum Entkoppeln vom ISP: einige kΩ | ||
* evtl. Kondensatoren von 100pF zum Entstören der Dateinleitungen | * evtl. Kondensatoren von 100pF zum Entstören der Dateinleitungen | ||
| − | * Strom für die Versorgung im Bereich von µA bis wenige mA (je nach Typ, Anzahl und Frequenz) | + | * Strom für die Versorgung im Bereich von µA bis wenige mA (je nach Expander-Typ, Anzahl und Frequenz) |
| + | |||
=Schaltplan= | =Schaltplan= | ||
| Zeile 54: | Zeile 55: | ||
;Das umstrichelte Modul: kann einfach so oft nach rechts wiederholt werden bis man so viele Ausgänge hat wie gewünscht. | ;Das umstrichelte Modul: kann einfach so oft nach rechts wiederholt werden bis man so viele Ausgänge hat wie gewünscht. | ||
;R1: ist ein Pullup-Widerstand, der während des ISP-Programmierens dafür sorgt, daß RCK nicht floatet, denn während der Programmierung sind die AVR I/O-Leitungen hochohmig. Dadurch bleiben die Ausgänge der Expander stabil (MOSI und SCK wackeln natürlich beim Programmierern). | ;R1: ist ein Pullup-Widerstand, der während des ISP-Programmierens dafür sorgt, daß RCK nicht floatet, denn während der Programmierung sind die AVR I/O-Leitungen hochohmig. Dadurch bleiben die Ausgänge der Expander stabil (MOSI und SCK wackeln natürlich beim Programmierern). | ||
| − | ;R2, R3: entkoppeln den ISP-Adapter | + | ;R2, R3: entkoppeln den ISP-Adapter. Ansonsten stören sie nicht weiter, denn beim Proggen muss praktisch kein Strom fliessen – abgesehen vom minimalen Leckstrom der Ports und Füllen der Portkapazität von ein paar pF. |
; Eingang G (Pin13): ist hier auf LOW verdrahtet. Falls gewünscht, kann er verwendet werden, um die Ausgänge der Expander hochohmig zu schalten (high-Z). Dann braucht man natürlich einen weiteren µC-Port, um das zu tun. | ; Eingang G (Pin13): ist hier auf LOW verdrahtet. Falls gewünscht, kann er verwendet werden, um die Ausgänge der Expander hochohmig zu schalten (high-Z). Dann braucht man natürlich einen weiteren µC-Port, um das zu tun. | ||
| Zeile 111: | Zeile 112: | ||
'''serpa.c''' | '''serpa.c''' | ||
<pre> | <pre> | ||
| − | / | + | // SERiell nach PArallel (serpa) mit Hardware-Unterstützung |
#include <avr/io.h> | #include <avr/io.h> | ||
#include "serpa.h" | #include "serpa.h" | ||
| Zeile 160: | Zeile 161: | ||
while (--anz > 0); | while (--anz > 0); | ||
| − | + | // Strobe an RCK bringt die Daten von den Schieberegistern in die Latches | |
CLR (PORT_RCK); | CLR (PORT_RCK); | ||
SET (PORT_RCK); | SET (PORT_RCK); | ||
| Zeile 167: | Zeile 168: | ||
== Ohne SPI-Hardware == | == Ohne SPI-Hardware == | ||
| + | |||
| + | Dieser Code funktioniert auch für jeden anderen µC-Typ, der mindestend 3 digitale I/O-AUsgangsports hat, und mit einem Compiler für Standard-C übersetzt wird. | ||
'''serpa.c''' | '''serpa.c''' | ||
| Zeile 173: | Zeile 176: | ||
#include "serpa.h" | #include "serpa.h" | ||
| − | / | + | /* Array für die Daten */ |
unsigned char serpa[SERPA_SIZE]; | unsigned char serpa[SERPA_SIZE]; | ||
void serpa_init () | void serpa_init () | ||
{ | { | ||
| − | / | + | /* Verwendete Ports auf OUT */ |
MAKE_OUT (PORT_SER); | MAKE_OUT (PORT_SER); | ||
MAKE_OUT (PORT_SCK); | MAKE_OUT (PORT_SCK); | ||
MAKE_OUT (PORT_RCK); | MAKE_OUT (PORT_RCK); | ||
| − | / | + | /* SCR und RCK auf definierten Level HIGH */ |
SET (PORT_SCK); | SET (PORT_SCK); | ||
SET (PORT_RCK); | SET (PORT_RCK); | ||
| Zeile 198: | Zeile 201: | ||
unsigned char data = *--serp; | unsigned char data = *--serp; | ||
| − | / | + | /* 8 Bits pro Byte rausschieben */ |
for (bits = 8; bits > 0; bits--) | for (bits = 8; bits > 0; bits--) | ||
{ | { | ||
| Zeile 208: | Zeile 211: | ||
data <<= 1; | data <<= 1; | ||
| − | / | + | /* Strobe an SCK schiebt Daten im Gänsemarsch */ |
| − | / | + | /* um 1 Position weiter durch alle Schieberegister */ |
CLR (PORT_SCK); | CLR (PORT_SCK); | ||
SET (PORT_SCK); | SET (PORT_SCK); | ||
| Zeile 216: | Zeile 219: | ||
while (--anz > 0); | while (--anz > 0); | ||
| − | / | + | /* Strobe an RCK bringt die Daten von den Schieberegistern in die Latches */ |
CLR (PORT_RCK); | CLR (PORT_RCK); | ||
SET (PORT_RCK); | SET (PORT_RCK); | ||
| Zeile 224: | Zeile 227: | ||
=Expander= | =Expander= | ||
| − | Von den meisten Expandern gibt es auch | + | Von den meisten Expandern gibt es auch Unterversionen, wie 74HC (Highspeed CMOS), 74HTC (Highspeed CMOS, TTL-Compatible), etc. Hier tut's z.B. 74HC. Pro Expander fallen Kosten von ca 30-40 Cent an ([[Bezugsquellen#Elektronikbauteile|Reichelt]]). Ungelatchte Register wie 74*164 sind übrigens nicht zu empfehlen, weil bei deren Verwendung wäherend des Schiebens die Ausgänge flattern. |
Die Verwendete SPI-Frequenz ist unkritisch und kann natürlich auch langsamer eingestellt werden. Taktfrequenzen von 100MHz sind für die ICs normalerweise kein Problem. | Die Verwendete SPI-Frequenz ist unkritisch und kann natürlich auch langsamer eingestellt werden. Taktfrequenzen von 100MHz sind für die ICs normalerweise kein Problem. | ||
;8-Bit Schieberegister mit Ausgangs-Latch: | ;8-Bit Schieberegister mit Ausgangs-Latch: | ||
| − | + | ;74*594: Shift Clear, Latch Clear, Tri-State | |
| − | + | ;74*595: Shift Clear, Tri-State | |
| − | + | ;74*596: Shift Clear, [[Open Collector]]/high-Z | |
| − | ; | + | ;CD4094, 74*4094: Tri-State |
=Siehe auch= | =Siehe auch= | ||
Version vom 11. Januar 2006, 10:01 Uhr
Bietet ein Controller nicht genügend I/O-Leitungen, dann kann man Portexpander werwenden. Dadurch hat man zusätzliche Ports zur Verfügung. Neben Portexpandern der I²C-Klasse oder SPI-Klasse bietet sich an, 8-Bit-Schieberegister zu kaskadieren und als Expander zu verwenden. Das ist oft ausreichend, weil mehr Ausgänge begraucht werden als Eingänge. Dabei verwendet man Schieberegister mit Ausgangs-Latch, d.h. die Daten werden erst dann an die Ausgänge geschaltet, wenn sie an Ort und Stelle sind.
Falls man Eingänge benötigt, können auch Schieberegister mit Input-Latches ankaskadiert werden, welche die Eingänge von parallel nach seriell umsetzen (in diesem Artikel nicht näher beschrieben).
Inhaltsverzeichnis
Pro & Contra
- Vorteile
- schnell
- preiswert
- einfach anzusteuern (auch ohne Hardware-Unterstützung)
- Ansteuerung ohne Interrupt-Programmierung
- modular aufgebaut und erweiterbar
- alle Ports können gleichzeitig geschaltet werden, auch 100 Stück
- SPI-Interface und ISP-Pins (die oft ungenutzt bleiben) können verwendet werden
- Bus hat nur 3 Leitungen, dadurch kein kompliziertes Layout mit vielen Leitungen
- Nachteile
- bei dieser Version nur Ausgabe möglich
- soll ein Ausgangs-Port geändert werden müssen alle Daten neu gesendet werden
- bei der Variante mit SPI-Hardware liegt MISO brach bzw ist nicht so einfach nutzbar zu machen
Resourcen
| Resource | ohne SPI | mit SPI |
|---|---|---|
| AVR-Peripherie | 3 I/O-Ports | SPI + 1 I/O-Port |
| Expander 74*595, CD4094, ... | N | |
| maximaler Datendurchsatz in kByte pro Sekunde und MHz |
10 | 37 |
Mit einer CPU-Frequenz von 16MHz hat man also mit der Hardware-Variante einen maximalen Durchsatz von ca. 590 kByte/Sekunde, und 160kByte/Sekunde mit der reinen Software-Variante.
Kleinkram:
- evtl. Pullup/Pulldown-Widerstand: 20kΩ
- Widerstände zum Entkoppeln vom ISP: einige kΩ
- evtl. Kondensatoren von 100pF zum Entstören der Dateinleitungen
- Strom für die Versorgung im Bereich von µA bis wenige mA (je nach Expander-Typ, Anzahl und Frequenz)
Schaltplan
|
- Das umstrichelte Modul
- kann einfach so oft nach rechts wiederholt werden bis man so viele Ausgänge hat wie gewünscht.
- R1
- ist ein Pullup-Widerstand, der während des ISP-Programmierens dafür sorgt, daß RCK nicht floatet, denn während der Programmierung sind die AVR I/O-Leitungen hochohmig. Dadurch bleiben die Ausgänge der Expander stabil (MOSI und SCK wackeln natürlich beim Programmierern).
- R2, R3
- entkoppeln den ISP-Adapter. Ansonsten stören sie nicht weiter, denn beim Proggen muss praktisch kein Strom fliessen – abgesehen vom minimalen Leckstrom der Ports und Füllen der Portkapazität von ein paar pF.
- Eingang G (Pin13)
- ist hier auf LOW verdrahtet. Falls gewünscht, kann er verwendet werden, um die Ausgänge der Expander hochohmig zu schalten (high-Z). Dann braucht man natürlich einen weiteren µC-Port, um das zu tun.
C-Code
Der folgende C-Code ist Pseudocode, was Setzen der Ports angeht. Die entsprechenden Befehle sind durch die richtigen C-Befehle für diese Ports zu ersetzen.
- MAKE_OUT (X)
- Schaltet X als Ausgang (DDR-Register)
- SET (X)
- Setzt Ausgang X auf HIGH (PORT-Register)
- CLR (X)
- Setzt Ausgang X auf LOW (PORT-Register)
| Resource | ohne SPI | mit SPI |
|---|---|---|
| Interrupts | keine | |
| Flash (Bytes mit -Os) | 52 | 44 |
| SRAM (statisch) | N | |
| SRAM (Stack) | 2 | |
| Laufzeit serpa_out() | 19 + 101*N | 16 + 27*N |
| SCK-Frequenz | ~fcpu/9 | fcpu/2 |
Makros, Datenstrukturen, Funktionen
- #define SERPA_SIZE
- Define für Anzahl der auszugebenden Bytes
- extern unsigned char serpa[SERPA_SIZE]
- Das Array, dessen Bytes ausgegeben werden. serpa[0] landet in dem Portexpander-IC, das direkt am Controller sitzt. Bit0 erscheint jeweils an Ausgang QA, Bit7 erscheint am Ausgang QH, etc.
- void serpa_init()
- Initialisiert die Schnittstelle bzw. die verwendeten Ports
- void serpa_out()
- Gibt die SERPA_SIZE Bytes aus dem Array serpa aus.
serpa.h
/* SERiell nach PArallel (serpa) im SPI-Protokoll */ #ifndef _SERPA_H_ #define _SERPA_H_ /* 4 Bytes (32 Ports) */ #define SERPA_SIZE 4 extern unsigned char serpa[]; extern void serpa_out(); extern void serpa_init(); #endif /* _SERPA_H_ */
Mit SPI-Hardware
Das Senden erfolgt ohne den SPI-Interrupt zu nutzen. Allein der ISR-Prolog/Epilog dauert schon so lange wie ein Schleifendurchlauf.
serpa.c
// SERiell nach PArallel (serpa) mit Hardware-Unterstützung
#include <avr/io.h>
#include "serpa.h"
// Array für die Daten
unsigned char serpa[SERPA_SIZE];
void serpa_init()
{
MAKE_OUT (PORT_MOSI);
MAKE_OUT (PORT_SCK);
MAKE_OUT (PORT_RCK); SET (PORT_RCK);
// !!! SS muss OUT sein, damit SPI nicht in Slave-Mode wechselt !!!
// entfällt, falls PORT_RCK = PORT_SS
MAKE_OUT (PORT_SS);
// SPI als Master
// High-Bits zuerst
// SCK ist HIGH wenn inaktiv
SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPOL);
// pullup an MISO vermeidet Floaten
SET (PORT_MISO);
// maximale Geschwindigkeit: F_CPU / 2
SPSR |= (1 << SPI2X);
}
void serpa_out ()
{
unsigned char anz = SERPA_SIZE;
unsigned char* serp = serpa+SERPA_SIZE;
do
{
unsigned char data = *--serp;
// SPDR schreiben startet Übertragung
SPDR = data;
// warten auf Ende der Übertragung für dieses Byte
while (!(SPSR & (1 << SPIF)));
// clear SPIF
data = SPDR;
}
while (--anz > 0);
// Strobe an RCK bringt die Daten von den Schieberegistern in die Latches
CLR (PORT_RCK);
SET (PORT_RCK);
}
Ohne SPI-Hardware
Dieser Code funktioniert auch für jeden anderen µC-Typ, der mindestend 3 digitale I/O-AUsgangsports hat, und mit einem Compiler für Standard-C übersetzt wird.
serpa.c
/* SERiell nach PArallel (serpa) via Software */
#include "serpa.h"
/* Array für die Daten */
unsigned char serpa[SERPA_SIZE];
void serpa_init ()
{
/* Verwendete Ports auf OUT */
MAKE_OUT (PORT_SER);
MAKE_OUT (PORT_SCK);
MAKE_OUT (PORT_RCK);
/* SCR und RCK auf definierten Level HIGH */
SET (PORT_SCK);
SET (PORT_RCK);
}
void serpa_out ()
{
unsigned char anz = SERPA_SIZE;
unsigned char* serp = serpa+SERPA_SIZE;
do
{
unsigned char bits;
unsigned char data = *--serp;
/* 8 Bits pro Byte rausschieben */
for (bits = 8; bits > 0; bits--)
{
CLR (PORT_SER);
if (data & 0x80)
{
SET (PORT_SER);
}
data <<= 1;
/* Strobe an SCK schiebt Daten im Gänsemarsch */
/* um 1 Position weiter durch alle Schieberegister */
CLR (PORT_SCK);
SET (PORT_SCK);
}
}
while (--anz > 0);
/* Strobe an RCK bringt die Daten von den Schieberegistern in die Latches */
CLR (PORT_RCK);
SET (PORT_RCK);
}
Expander
Von den meisten Expandern gibt es auch Unterversionen, wie 74HC (Highspeed CMOS), 74HTC (Highspeed CMOS, TTL-Compatible), etc. Hier tut's z.B. 74HC. Pro Expander fallen Kosten von ca 30-40 Cent an (Reichelt). Ungelatchte Register wie 74*164 sind übrigens nicht zu empfehlen, weil bei deren Verwendung wäherend des Schiebens die Ausgänge flattern.
Die Verwendete SPI-Frequenz ist unkritisch und kann natürlich auch langsamer eingestellt werden. Taktfrequenzen von 100MHz sind für die ICs normalerweise kein Problem.
- 8-Bit Schieberegister mit Ausgangs-Latch
- 74*594
- Shift Clear, Latch Clear, Tri-State
- 74*595
- Shift Clear, Tri-State
- 74*596
- Shift Clear, Open Collector/high-Z
- CD4094, 74*4094
- Tri-State
Siehe auch
