So verschieben Sie 16 Bit schnell auf einer Arduino-Karte

7

Ich codiere ein System, das 16 Bit schnell von einer Variablen uint16_t in zwei gepaarte 74HC595-Schieberegister verschieben muss. Ich führe den Code auf einem Arduino (atmega328 @ 16Mhz) aus und das shiftOut im Arduino ist viel zu langsam. Die digitalWrite-Funktion der Bibliothek ist ebenfalls langsam.

Die beste Idee, die ich mir ausgedacht habe, ist eine for-Schleife, die alle 16 Bits der Variablen durchläuft und 1/0 in den Daten-Pin schreibt, das Taktbit so kurz wie möglich hoch setzt und dann zum nächsten Bit der Variablen übergeht.

Ist dies die schnellste Lösung und wenn ja, wie durchlaufe ich die Bits der Variablen uint16_t in c ++?

tirithen
quelle
Ich habe einige Tests mit SRAM durchgeführt. Vielleicht finden Sie die Ergebnisse interessant: arduino.stackexchange.com/questions/36871/… Fazit: Ein digitalRead / WriteFast ist vernachlässigbar, ein ShiftOut kostet uns jedoch 120.
Michel Keijzers

Antworten:

8

Dies ist mit der SPI-Bibliothek einfach genug.

Verbinden Sie Ihren Schieberegister-Eingang mit dem MOSI-Pin (Master Out, Slave In) - Digital Pin 11 - und Sie erhalten schöne schnelle Übertragungen.

Es wird eine sehr geringe Verzögerung zwischen den oberen und unteren 8 Bits jedes übertragenen Wortes geben.

Zum Beispiel:

#include <SPI.h>

void begin()
{
    SPI.begin();
}

void loop()
{
    unsigned int val;

    val = rand()%0xFFFF; // Generate a random 16 bit number

    SPI.transfer(val >> 8);  // Output the MSB first
    SPI.transder(val & 0xFF); // Followed by the LSB

    delay(1000);  // Wait a sec...
}
Majenko
quelle
1
Was ist mit den Verriegelungsstiften? Dies scheint nur das Umschalten der seriellen Datenleitung zu sein, aber ich sehe nicht, wie etwas im Register verriegelt wird.
Captncraig
Ich habe noch nie eines der fraglichen Schieberegister verwendet, daher weiß ich nicht, was erforderlich ist. Normalerweise wickeln Sie den SPI in ein digitalWrite (x, LOW) und ein digitalWrite (x, HIGH) ein, um eine digitale E / A-Leitung Ihrer Wahl als "Chip Select" oder "Latch Toggle" oder was auch immer umzuschalten (offensichtlich den Umschalter für Active High umkehren) ). Verwenden Sie einen beliebigen Stift.
Majenko
8

Wenn Sie eine Software-Datenübertragung verwenden möchten, möchten Sie die Funktionen digitalWrite nicht verwenden. Sie sind sehr langsam, weil sie die Pin-Nummer durch eine Tabelle in ein tatsächliches Register (PORTx) übersetzen, das richtige Bit maskieren und es ändern müssen. Alle Pins in Arduino sind Zahlen zugeordnet, während sie darunter zu Port A, B, C und noch mehr der MEGA-Version des Arduino gehören können.

Es ist viel schneller, die AVR-Register direkt zu ändern. Wie PORTB und a-like. Sie müssen in der Tat jedes Bit durchgehen. Ich würde eine for-Schleife von 0 bis 15 erstellen und ein bisschen verschieben und maskieren.

Da ich die Pinning-Konfiguration nicht kenne, kann ich kein genaues Beispiel nennen. Allerdings wird es wahrscheinlich sehr ähnlich aussehen. Mit "sehr nah" meine ich, dass dies nicht getestet wurde.

void ShiftOut(UI16_t data)
{
 // Initialize (you may want to set CLK to low) - as we're toggling later on.

// step from bit 0 to 15 for(UI08_t i = 0; i < 15; i++) { // Check the content of this data bit // Shift data so this bit is LSB, and mask it with 1 so we only look at this bit. if ((data >> i) & 0x1 == 1) { // set data pin high, like PORTB |= 1<<4; // when pin 4 of portB is your data pin // Doing an OR will make pin B4 always high } else { // set data pin low, like PORTB &= ~(1<<4); // Doing an AND with the inverse means all pins except B4 will be unchanged }

// Generate clk to 'transfer' the bit: // This can likely be done by using PORTB ^= 1 << 5; (pin B5 in this example) // ^= toggle // Do this TWICE, so CLK goes high/low }

// as you're using a shift register, you may want to toggle LATCH pin as well.. }

Um herauszufinden, welche Hardware-Pin-Nummer (Pin 4 nicht Pin B4 oder A4!) Ist, müssen Sie sich das Schema von Arduino ansehen.

Ich habe einen ähnlichen Code auf einem PIC32 ausgeführt (läuft mit 80 MHz). Der PIC32 konnte dies bei etwa 1,5 MHz tun, aber in main () wurden einige zusätzliche Codezeilen ausgeführt, um eine neue Ausgabe zu berechnen. Trotzdem kann es sehr schnell gehen.

Hans
quelle
Vielen Dank für die ausführliche Antwort. Ich werde zuerst den SPI-Ansatz ausprobieren, da dieser schneller zu sein scheint. Ich fand auch weitere Beispiele für den Software-Ansatz unter bildr.org/2011/02/74hc595
tirithen
5

Sie müssen das SPI-Peripheriegerät verwenden, anstatt die Software zu verschieben. Ich habe noch nie ein Arduino verwendet, aber die Online- Referenz legt nahe, dass es eine SPI-Bibliothek gibt, die Sie verwenden können. Wenn dies nicht Ihren Anforderungen entspricht, können Sie das SPI-Peripheriegerät im ATMega-Datenblatt nachschlagen. SPI-Peripheriegeräte sind normalerweise recht einfach einzurichten und zu verwenden.

Markrages
quelle
1

Ich bin alte Schule, codiere seit 100 kHz Prozessoren. Verwenden Sie Inline-Code für die Bitmanipulation direkt am Port anstelle einer Schleife. Die Schleife erfordert Overhead, Inline ist schneller, benötigt jedoch mehr Programmplatz. Informationen zur Bitmanipulation der Ports finden Sie unter AVR035: Effiziente C-Codierung für AVR .

tomL
quelle