Verwendung von AVR Atmega32 SPI ohne SPI-Pins
-
21-12-2019 - |
Frage
Ich bin ziemlich neu in der Programmierung von Mikrocontrollern.Ich habe einige Erfahrung mit dem Arduino, aber nachdem ich mein Projekt fast abgeschlossen hatte, beschloss ich, mein aktuelles Projekt auf etwas günstigeres und kleineres umzustellen.Daher verwende ich jetzt den AVR ATmega32 mit Atmel Studio.
Ich versuche, den ATmega32 für die Kommunikation mit einem MAX7219-Chip zum Multiplexen mit einer LED-Matrix zu verwenden.Allerdings habe ich mehrere verschiedene Geräte, mit denen ich kommunizieren möchte.
Wie kann ich mit dem Gerät kommunizieren, ohne tatsächlich die auf dem Mikrocontroller bereitgestellten SPI-Pins zu verwenden?Ich habe ein Testprojekt erstellt, aber da scheint etwas nicht zu stimmen und ich kann nicht herausfinden, wo das Problem liegt.Ich glaube, ich habe es geschafft, es in den Testmodus zu bringen, weil alle LEDs leuchten, aber ich kann es danach nicht mehr dazu bringen, etwas zu tun.Ich kann nicht einmal das Display löschen/ausschalten.Ich habe die Verkabelung noch einmal überprüft.Ist meine Codierung möglicherweise falsch, was die Pinbelegung und Belegung der Pins angeht?Gibt es Vorschläge dafür oder eine bessere Möglichkeit, meinen Code zu schreiben?
Hier ist der Link zum Datenblatt MA7219
//test
#include <avr/io.h>
int main(void)
{
DDRB = 0b00000111; // pin 1(data), 2(clock) and 3(latch) are outputs
PORTB = 0 << PINB0; // data pin 1 is low
PORTB = 0 << PINB1; // clock pin 2 is low
PORTB = 0 << PINB2; // latch pin 3 is low
uint16_t data;
data = 0b0000110000000000; // data to shift out to the max7219
//read bit
uint16_t mask;
for (mask = 0b0000000000000001; mask>0; mask <<= 1)
{
//iterate through bit mask
if (data & mask)
{ // if bitwise AND resolves to true
// send one
PORTB = 1 << PINB0;
// tick
PORTB = 1 << PINB1;
// tock
PORTB = 0 << PINB1;
}
else{ //if bitwise and resolves to false
// send 0
// send one
PORTB = 0 << PINB0;
// tick
PORTB = 1 << PINB1;
// tock
PORTB = 0 << PINB1;
}
}
PORTB = 1 << PINB2; // latch all the data
PORTB = 1 << PINB0; // data pin 1 is high
PORTB = 0 << PINB1; // clock pin 2 is low
PORTB = 0 << PINB2; // latch pin 3 is low
}
Lösung
Ja, Ihr Bit-Bang-Code hat das Problem, dass Sie jedes Mal den gesamten Wert des Registers zuweisen, ohne den vorhandenen Wert beizubehalten.Daher löschen Sie Ihr Datensignal in dem Moment, in dem Sie Ihre Uhr steuern, wodurch die Haltezeit des Empfängers verletzt wird und es zu einem unvorhersehbaren Betrieb kommt.
Anstatt Pins mit zuzuweisen =
, sollten Sie sie mit einstellen |=
oder löschen Sie sie mit &= ~(value)
Zum Beispiel:
PORTB = 1 << PINB0; //drive data
// tick
PORTB |= 1 << PINB1; //clock high PRESERVING data
// tock
PORTB &= ~(1 << PINB1); //clock low
Möglicherweise müssen Sie auch eine leichte Verzögerung zwischen den Pin-Vorgängen einfügen.
Technisch gesehen, vorausgesetzt, Sie verwenden bereits eine if
Für den Datenstatus könnte man das Datensignal beispielsweise auch mit einem ODER in der Zuweisung neu ansteuern
if (data & mask)
{ // if bitwise AND resolves to true
// send one
PORTB = 1 << PINB0;
// tick
PORTB = (1 << PINB1) | (1 << PINB0);
// tock
PORTB = 0 << PINB1 | (1 << PINB0);
}
else{ //if bitwise and resolves to false
// send 0
// send one
PORTB = 0 << PINB0;
// tick
PORTB = 1 << PINB1;
// tock
PORTB = 0 << PINB1;
}