K (→C-Code) |
(→C-Code) |
||
| Zeile 23: | Zeile 23: | ||
;CLR (X): Setzt Ausgang X auf LOW (PORT-Register) | ;CLR (X): Setzt Ausgang X auf LOW (PORT-Register) | ||
| − | == | + | ==Funktionen== |
| − | + | ;<tt>#define SERPA_SIZE</tt>: Define für Anzahl der auszugebenden Bytes | |
| + | ;<tt>extern unsigned char serpa[SERPA_SIZE]</tt>: Das Array, dessen Bytes ausgegeben werden. <tt>serpa[0]</tt> landet in dem Portexpander-IC, das direkt am Controller sitzt. Bit0 erscheint jeweils an Ausgang QA, Bit7 erscheint am Ausgang QH, etc. | ||
| + | ;<tt>void serpa_init()</tt>: Initialisiert die Schnittstelle bzw. die verwendeten Ports | ||
| + | ;<tt>void serpa_out()</tt>: Gibt die <tt>SERPA_SIZE</tt> Bytes aus dem Array <tt>serpa</tt> aus. | ||
'''serpa.h''' | '''serpa.h''' | ||
<pre> | <pre> | ||
| + | /* SERiell nach PArallel (serpa) im SPI-Protokoll */ | ||
#ifndef _SERPA_H_ | #ifndef _SERPA_H_ | ||
#define _SERPA_H_ | #define _SERPA_H_ | ||
| Zeile 40: | Zeile 44: | ||
#endif /* _SERPA_H_ */ | #endif /* _SERPA_H_ */ | ||
</pre> | </pre> | ||
| + | |||
| + | == Mit SPI-Hardware == | ||
| + | |||
| + | '''serpa.c''' | ||
| + | <pre> | ||
| + | /* 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 = _BV(SPE) | _BV(MSTR) | _BV(CPOL); | ||
| + | |||
| + | // pullup an MISO vermeidet Floaten | ||
| + | SET (PORT_MISO); | ||
| + | |||
| + | // maximale Geschwindigkeit: F_CPU / 2 | ||
| + | SPSR |= _BV(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); | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | == Ohne SPI-Hardware == | ||
'''serpa.c''' | '''serpa.c''' | ||
Version vom 9. Januar 2006, 22:50 Uhr
|
An diesem Artikel arbeitet gerade Mitglied SprinterSB.
Am besten momentan noch keine gravierenden Ergänzungen / Änderungen vornehmen. Dieser Hinweis verschwindet wenn der Autor soweit ist. Sollte dieser Hinweis länger als drei Tage auf einer Seite sein, bitte beim Autor SprinterSB per PM / Mail oder Forum nachfragen ob er vergessen wurde. |
- Vorteile
- schnell
- preiswert
- einfach anzusteuern (auch ohne Hardware-Unterstützung)
- modular aufgebaut und erweiterbar
- alle Ports können gleichzeitig geschaltet werden, auch 100 Stück
- SPI-Interface und ISP-Pins können verwendet werden
- Bus hat nur 3 Leitungen, dadurch kein kompliziertes Layout mit vielen Leitungen
- Nachteile
- bei dieser Version nur Ausgabe möglich
Inhaltsverzeichnis
Schaltplan
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)
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
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 = _BV(SPE) | _BV(MSTR) | _BV(CPOL);
// pullup an MISO vermeidet Floaten
SET (PORT_MISO);
// maximale Geschwindigkeit: F_CPU / 2
SPSR |= _BV(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
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);
}

