Hallo zusammen,
leider hat die Suche im Forum nichts erbracht.
Folgendes Problem: Ich möchte auf einem AT89C52 ein SPI Interface
realisieren. Entsprechende und für meine Anwendung funktionierende
Assembler-Routinen habe ich schon geschrieben. Allerdings muss ich mich
mit C beschäftigen, und davon hab ich leider nicht viel Ahnung.
1. Wie kann ich das Einlesen und Ausgeben realisieren?
2. Gibt es irgendwo eine Sammlung solcher Code-Schnipsel, damit sich
Anfänger nicht so schwer tun?
Danke
Gruß Ralf
In C ist es egal, ob 8051, MSP, ARM oder AVR.
Allerdings hat der 8051 spezielle Erweiterungen, um auf Portpins
zugreifen zu können. Damit kann man den Code noch etwas optimieren.
Funktionieren tuts aber auch ohne.
Wenn Du kein C kannst, solltest Du es zuerst lernen, z.B. mit
Borland-C.
Ein Bespiel zu schreiben und dann kapierst Du es nicht, dazu hat keiner
Lust.
Für SPI mußt Du for, if, &, |, <<, >> kennen.
Peter
doch, sicher.
Aber geh doch andersherum ran: wenn du verstanden hast, wie das
physikalisch funktioniert, klappt das auch mit der Programmierei. Wenn
du dich mit C beschäftigen willst, nutzt es dir doch nichts,
vorgekauten Kram zu bekommen. Nichts ist dafür besser als eigene
Erfolgserlebnisse.
@Peter:
Mach mir ein Beispiel, und ich sag dir, ob ich es verstanden habe ;-)
Nein, im Ernst, ich verstehe dich. FOR, IF, &, |(oder), sowie << und >>
(shiften bzw. rolieren), ist alles klar. Mein Problem war eher, dass ich
den Lösungsansatz suche, inzwischen habe ich eine der Routinen zum
laufen bekommen, aber auf diese Lösungsart bin ich nicht gekommen, weil
ich sie so nicht ERWARTET habe. Da hilft denke ich nur Input von denen,
die es können.
@Crazy Horse:
Wie ich Peter bereits sagte, auf den Lösungsansatz muss man gefasst
sein. Aber das mit den Erfolgserlebnissen, da hast du freilich recht.
Gruß Ralf
Welche Lösung hast Du denn gefunden ?
Es gibt ja so viele.
Hier z.B. eine, die die Bits nicht nur in auf- oder absteigender
Reihenfolge, sondern x-beliebig senden kann:
http://www.mikrocontroller.net/forum/read-4-22246.html
Das Beispiel von crazy horse ist auch eine, wenn auch nicht sehr
effektiv. Ehe man eine extra Maskenbyte schiebt, ist es schneller und
kürzer, wenn man das Datenbyte selbst schiebt. In der Regel braucht man
nämlich das Datenbyte danach nicht mehr bzw. kann damit gleichzeitig die
empfangenen Bits reinschieben.
Peter
Hi Crazy Horse,
also... Ist die Routine zum SPI-Schreiben nicht ein bisschen dick?
Meine sieht so aus:
SPI_OUT(unsigned char output) {
unsigned char i;
for (i = 8; i; i--) {
SCK = 0;
MOSI = output & 0x01;
output = output >> 1;
SCK = 1;
}
}
Oder übersehe ich irgendwo etwas in deiner Routine? Ich nehme an, du
machst weiche Ware für einen AVR oder so, vielleicht macht die Routine
da so mehr Sinn.
Gruß Ralf
"Das Beispiel von crazy horse ist auch eine, wenn auch nicht sehr
effektiv" - ich wusste, dass das von dir kommt :-)
weiss ich selbst, aber man versteht es eigentlich recht gut, wie es
funktioniert. Man braucht auch keinen extra loop-Zähler.
@Ralf: nicht immer ist ein einfacher aussehendes C-Programm auch die
optimale Lösung im Endergebnis, kommt natürlich auch auf den Compiler
an.
Konkret, (rein Interese halber habe mal beides compiliert) und siehe
da:
dein C-Code erzeugt 4 words mehr Maschinencode (absolut 19 zu 23) und
benötigt 271 Takte statt 193 bei meinem.
@crazy horse:
Ich wollte dir auch nicht auf die Hufe... äh... Füsse treten. Du hast
den Code jetzt für einen AVR generiert, oder? Ich werd bei Gelegenheit
mal deinen für den 8051 generieren, mal sehen, ob meiner da auch so
groß ist im Gegensatz zu deinem. In dem Fall würde ich deinen nehmen,
wenn da kein Copyright drauf ist :-)
Gruß Ralf
Noch ein Test, ohne extra loop-counter
void write_spi (unsigned char data_out){ //msb first
unsigned char mask;
for (mask=0x80; mask; mask=mask>>1)
{sclk=0;
if (data_out & mask) mosi=1;
else mosi=0;
sclk=1;
}
}
schlägt mit 16 words und 159 Takten (mit Aufruf und return) zu Buche.
Auch knuffig. Ich muss jetzt mal anfangen, die Sache real (sprich nicht
Simulator) auszutesten, und mal sehen was dabei rauskommt.
Hoffentlich tuts auch...
Gruß Ralf
Anbei mal der Code mit dem WINAVR (20 Byte) und mit dem Keil (17 Byte).
Der WINAVR gestattet leider keine Portpindefinitionen, daher die etwas
umständlichere Schreibweise mit Maskierung.
Ist aber alles nur ne Gewöhnungsfrage.
Peter
Kannst du mal das Listing anhängen?
Deine Lösung erzeugt bei mir das schlechteste Ergebnis (29 words, 439
Takte). Da besteht offensichtlich deutlicher Optimierungsbedarf am
Compiler.
Anbei das Listing für den WINAVR.
Er erkennt, wenn nur ein Portpin gesetzt oder gelöscht werden soll und
nimmt dann SBI/CBI.
Der Keil vertraut darauf, daß man Pins, die man einzeln benutzen will
auch als einzelne Bits definiert.
Warscheinlich der CodeVision auch.
Peter
>>1. Wie kann ich das Einlesen und Ausgeben realisieren?
Das Ausgeben habt Ihr hier super beschrieben, doch wie sieht es mit
Einlesen aus?
Brauche ich für meinen ATTiny13 Project, der ja kein SPI kann (nur ISP
über SPI seltsamerweise...steht auch im Datenblatt nix dazu...)
Ein Mega8 wird bei mir Soft- oder Hardware SPI benutzen (werde sehen,
was besser ist), um dem Tiny13 Befehle zur Steuerung einer RGB-LED zu
geben.
Der Tiny13 muss diese Befehle auslesen und interpretieren.
Danke in Voraus
Grüße, paul
Hallo,
habe für einen ATTiny2313 auch eine Software SPI Lösung gesucht und hier
gefunden. Danke vor allem an meinen Vorposter, der Code funktioniert
eiwandfrei. Habe ihn etwas angepasst, da ich CPHA=1 und CPOL=1 nicht
nutze.
Benötigte den Code für die Kommunikation mit einem SCA3000. Werde die
Bibliothek(en) in einem neuen Thread posten.
Grüße
Göck