Aus RN-Wissen.de
Wechseln zu: Navigation, Suche
Rasenmaehroboter Test

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)
  
== Mit SPI-Hardware ==  
+
==Funktionen==
== Ohne SPI-Hardware ==
+
;<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, 23:50 Uhr

Baustelle.gif 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

Schaltplan

Portexpander 74595 an AVR.png

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);
}

LiFePO4 Speicher Test