Hallo zusammen, Kann ich eigentlich eifach 4 normale Pin von einem Atmega128 als SPI emulieren. Respektive hat das jemand schonmal gemacht oder wie müsste ich da vorgehen? Oder ist dies schlichtweg unmöglich? gruss
Gast
#921007
Wenn es nicht so schnell sein muß, und der AVR Master ist, mag es gehen, das in Software zu emulieren. Aber warum willst Du das tun, der hat doch ne echte SPI? Hausaufgabe?
Besten dank für deine konstruktive Antwort. Problem ist das meine SPI schon für einen anderen Chip vergeben ist und diese somit blockiert. Das heisst müsste einen Timer initalisieren welcher den Clock darstellt und zusätzliche Ports wie MOSI und MISO welche die Daten synchron ausgeben oder?
Gast
#921023
Ja, so in der Richtung. Schau mal in die Sourcen von der FAT-Lub von Ulrich Radig. Dort kann man auch SW-SPI einstellen, mit anderen Worten es gibt eine Software-SPI Implementation, die Du als Vorlage benutzen kannst. http://www.ulrichradig.de/home/index.php/avr/mmc-sd
Gast
#921026
Du kannst problemlos mehrere Slaves an die SPI hängen. Ausgewählt werden die Geräte über den Chip Select Pin. Das kann ein beliebiger Controller Pin sein. Gruß Matthias
Gast
#921027
Also man kann oft mehrere SPI-Geräte an einen SPI-Anschluß anschließen, wenn man die Geräte einzeln per SS (Slave select) aktiviert. Timer brauchst Du nicht, denn die Clock muß kein bestimmtes Zeitschema einhalten. Allgemein (Master): MOSI setzen Clock auf HIGH MISO einlesen Clock auf low Das Ganze 8x für ein Byte. Wenn nur ein Gerät dranhängt, braucht man keine SS. Vorher die Doku vom Slave lesen, welche Clockpolarität, max. Geschwindigkeit etc. Einfach ausprobieren, sollte gehen.
Gast
#921029
Ich habe das auch schon gemacht. Das ist kein Problem. Nur habe ich damals eine etwas unregelmäßige Clock gehabt. War aber kein Problem. Wie oben geschrieben sollte es aber der Master sein.
Okay versuche es einmal so .... Problem ist das das Board keinen SS verwendet und somit der genutzte Chip die Leitungen MOSI und MISO immer auf High behält.
SPI-Master ist überhaupt kein Problem:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
Peter
Kann eigentlich eine SPI im 100Hz bereich laufen lassen ..... sofern ich als Master das so bestimme?
Gast
#921115
Hallo, ich hab in noch keinem Datenblatt eine Mindestfrequenz gesehen. Gruss dreg
Tanja Hofmann wrote: > Kann eigentlich eine SPI im 100Hz bereich laufen lassen ..... sofern ich > als Master das so bestimme? In Software und mit einem Timer ist das kein Problem, mit der Hardware-SPI geht maximal CLK/128. Problematisch kann es nur sein wenn einer der Slaves seine "normale" Arbeit stoppt während SlaveSelect aktiv ist.
langsamerer datentransfer geht immer. der slave syncronisiert sich immer auf die clock. ich würde nochmal über ein sauberes konzept mit CS leitungen nachdenken und das vorhandene SPI interface nutzen. das ist vermutlich wesentlich performanter. alle SPI slaves an einen SPI bus hängen und jedem chip seine CS leitung an einen I/O legen. oder die CS leitungen hinter ein SER-IN-PAR-OUT schieberegister (z.B. 74HC595) legen um I/O's zu sparen. wenn ein slave kein CS hat, helfen tri-stateable latches oder and-gatter zwischen cpu und slave.
Konnte also eine SPI ( SS, SCK, MOSI ) implementieren und dies über einen Pin ausgeben. Nun weiss ich nicht recht wie ich die MISO am einfachsten implementiere. Weiss jemand wie ich das am besten machen könnte? Besten dank.
Tanja Hofmann wrote: > Konnte also eine SPI ( SS, SCK, MOSI ) implementieren und dies über > einen Pin ausgeben. Nun weiss ich nicht recht wie ich die MISO am > einfachsten implementiere. Weiss jemand wie ich das am besten machen > könnte? Ganz normal, du toggelst die clock und liest den port und shiftest dir das in dein byte rein.
Wie Initalisiere ich den einen Pin als Interrupt. Irgendwie muss ich ja erkennen wenn die daten kommen oder?
Wenn dein Chip der Master ist setzt du die clock und damit steht fest wann die Daten zu kommen haben.
Ah ja genau so mach ich das. Aber um zu wissen wann ich die Daten holen will muss ich ein interrupt auf einen pin initalisieren. Unter Folgendenem File finde ich die Interruptvektoren: http://www.propox.com/download/edunet_doc/all/html/iom128_8h-source.html 00361 #define SIG_INTERRUPT0 _VECTOR(1) 00362 #define SIG_INTERRUPT1 _VECTOR(2) 00363 #define SIG_INTERRUPT2 _VECTOR(3) 00364 #define SIG_INTERRUPT3 _VECTOR(4) 00365 #define SIG_INTERRUPT4 _VECTOR(5) 00366 #define SIG_INTERRUPT5 _VECTOR(6) 00367 #define SIG_INTERRUPT6 _VECTOR(7) 00368 #define SIG_INTERRUPT7 _VECTOR(8) 00369 #define SIG_OUTPUT_COMPARE2 _VECTOR(9) 00370 #define SIG_OVERFLOW2 _VECTOR(10) 00371 #define SIG_INPUT_CAPTURE1 _VECTOR(11) 00372 #define SIG_OUTPUT_COMPARE1A _VECTOR(12) 00373 #define SIG_OUTPUT_COMPARE1B _VECTOR(13) ........ Wie weiss ich nun welcher Pin als Interrupt zu gebrauchen ist?
Tanja Hofmann wrote: > Ah ja genau so mach ich das. Aber um zu wissen wann ich die Daten holen > will muss ich ein interrupt auf einen pin initalisieren. Du meinst das der Slave erstmal signalisiert wenn er Daten hat, und du ihn dann abfrägst? Ja, dafür kannst du einen interrupt nehmen. > Wie weiss ich nun welcher Pin als Interrupt zu gebrauchen ist? Steht im Datenblatt.
Habe das im Datenblatt nachgeschaut ..... auf welche Ports sind dann diese Interrupts gelegt? 2 $0002 INT0 External Interrupt Request 0 3 $0004 INT1 External Interrupt Request 1 4 $0006 INT2 External Interrupt Request 2 5 $0008 INT3 External Interrupt Request 3 6 $000A INT4 External Interrupt Request 4 7 $000C INT5 External Interrupt Request 5 8 $000E INT6 External Interrupt Request 6 9 $0010 INT7 External Interrupt Request 7
.... steht im Datenblatt .... Du findest das beim Pinout oder auch bei den Alternate Port Functions. PD0-3 und PE4-7
Wie initalisiere ich den ein Pin PD1 als Interrupt. Muss ich ihn einfach als Input definieren und ist der dann auf positive flanke oder negative flanke getriggert? Ein Beispiel würde ansonsten sehr weiterhelfen.
RTFM "External Interrupts" oder http://www.gidf.de/AVR+External+Interrupts
Habe noch ein Problem mit der SPI. Die Emulation Funktioniert hervorragend wenn ich dies die Pin alleine am KO messe .... jedenfalls wenn ich die emulierte SPI an meinen IC hänge der die Wert sendet, habe ich auf allen vier Datenleitungen ein komisches rauschen drauf (SS, SCK, MOSI, MISO). Muss ich die Ausgäne evt über einen Widerstand auf Masse hängen? Hoffe es kann mir jemand helfen.
Gast
#927047
Ein Pull Up oder -down ist bei SPI eigentlich nicht nötig. Hast du die Massen verbunden? MW
Ja war ein Masse Problem. Das senden über die SPI funktioniert jetzt tipp top jedoch ist das konzept es empfangens noch nicht implementiert. Das Problem ist das ich den Bitstom schon einlesen kann jedoch möchte ich eigentlech das ganze als Hexzahl und nicht ein array mit 8 Bits füllen. Wie stelle ich das am besten an? Oder wie konvertiere ich ein array in eine Hexzahl?
Gast
#927751
bit array? hexzahl? haeh? also einlesen geht so speicherbyte |= inputpin (falls inputpin ein register ist muss man halt noch &1 machen, also: speicherbyte |= (inputpin&1) ) speicherbyte links shiften den ganzen prozess in jedem clock zyklus einmal (also 8* fuer ein ganzes byte) So empfaengst du ein byte ueber deine SPI. Das landet dann richtig in einem Register/Speicherstelle. (Programmierst du in C?)
Ja wenn ich über meine Emulierte SPI den MISO eingang einlese setzt in
einem Array 1 oder 0. Schlussendlich habe ich dann folgendes:
einArray = { 1,0,1,0,0,1,0,1 }
Wie mache jetzt aus diesem Array die ensprechende Hexzahl?
0011 = A
0101 = 5
Das ich den Wert einer variable mit A5 laden kann.
Gast
#927896
Die "Hexzahl" A5 ist nur eine mögliche Repräsentation eines Byte. Das einfachste, um aus dem Ausgangsarray ein Byte im Sinne des C-Datentyps char zu machen, wäre nacheinander das jeweils höherwertige Bit aus dem Array (also index von 0 bis 7 laufen lassen) zu einem auf 0 vorinitialisierten char dazu zu addieren und achließend das ganze nach links zu schieben.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
Menschen mit Vorliebe für unlesbaren Code können natürlich auch alles in einem Schritt erledigen.
1 | |
2 | |
3 | |
4 | |
Stilistisch wäre die erste Variante zu bevorzugen.
Folgender Befehl geht nicht wirklich .... was mache ich da falsch um das
Array in Hex umzwandeln?
int readarray8[] = {1,0,1,0,0,0,1,1};
char test;
for(int i=0;i<16;i++){
test |= readarray[i] << i;
}
Gast
#927933
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
so ziemlich alles... zum einen: das Array muss auch dimensioniert sein. also : readarray[8] statt readarray8[] der Index über das Array darf nur so groß sein wie das Array selbst, sonst fliegt's dir um die Ohren also: for(int i=0;i<8;i++) statt for(int i=0;i<16;i++) Die Varaible test ist zu Beginn uninitialisiert, also kann da alles mögliche an Blödsinn drinstehen. daher: char test = 0; statt char test;
Ja stimmt habe jetzt gerade ein paar flüchtigkeitsfehler gemacht, weil
ich sonst noch ein paar versuche gmeacht habe.
müsst natürlich so sein:
int readarray[8] = {1,0,1,0,0,0,1,1};
char test=0x00;
for(int i=0;i<8;i++){
test |= readarray[i] << i;
}
jedoch funktioniert es nicht ......
Gast
#927938
Die gerade aufgeführten Probleme sollte aber jemand mit C-Minimalverständnis sofort entdecken. Kann es sein, dass deine C-Künste noch etwa zu wünschen übrig lassen? In dem Fall wäre es besser, sich eingehend mit der Sprache zu beschäftigen und nicht nur Code zu kopieren.
Gast
#927942
Für das Array Integers zu nehmen ist auch ein wenig Overkill... char sollte reichen (je nach Compiler ist int auch auf einem 8bit-System 16bit breit und verschwendet daher dann viel Platz auf dem Stack). Wenn es nicht funktioniert versuch es mal mit unsigned Typen.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.