Hallo Zusammen,
ich versuche schon seit geraumer Zeit per QSYS den NIOSII auf meinem
DE0Nano lauffähig zu bekomen, um den ADXL345 per SPI auszulesen.
Die Beispielprogramme auf der beiligenden CD des DE0Nano funktionieren,
allerdings mit "älteren" Versionen der QSYS Module.
Wenn ich versuche diese mit den von "Quartus II 13.0" standardmäßig
installierten Modulen aufzubauen/nachzubilden (und die gleichen
Bibliotheken in C verwende) funktioniert leider gar nichts...
Kann mir jemand weiterhelfen, wo evtl schon meine grundlegenden Fehler
in beiligenden Dateien sind?
Ich bin absoluter Anfänger was FPGAs / VHDL betrifft!
Grundlegende Frage:
Reicht mir das "SPI (3 WIRE SERIAL)" Modul in QSYS aus um als
NIOSII-Master auf den ADXL345 zuzugreifen oder benötige ich noch die
"SPI SLAVE TO AVALON MASTER BRIDGE"?
Wie gesagt, absoluter newbie :)
Gruß
zander
@ Sigi:
Danke für die Rückmeldung.
Das mit MISO/MOSI hab ich versucht so zu lösen, da der adxl345 per
3-wire-spi an den DE0Nano angebunden ist...
siehe hierzu das Datenblatt S.23
([[http://www.altera.com/literature/ug/DE0_Nano_User_Manual_v1.9.pdf]]).
Irgenwie muss ich wohl deklarieren, dass ich nur die "I2C_SDAT" Leitung
zur Kommunikation habe, aber wie?
CS_N ist active low während der Kommunikation. Zuvor muss er jedoch HIGH
sein, um die clock polarity und clock phase(?) einzustellen. Zumindest
verstehe ich das Datenblatt so auf S. 14
([[http://www.analog.com/static/imported-files/data_sheets/ADXL345.pdf]]).
Ich meine irgendwo gelesen zu haben, dass das SPI-Modul (wenn nur ein
Slave vorhanden ist) diesen automatisch anwählt, daher bin ich davon
ausgegangen, dass das automatisch funktioniert.
Ich habe mal kurz in die Schematics geschaut:
Dein DE0-Nano hat beim adxl345 SDO leider auf
3.3V hochgezogen, d.h. es ist leider nur
I2C möglich (sofern sich über mehrere Versionen
von DE0_Nano I2C/SPI nicht ändert).
SPI kann also nicht funktionieren. Lösch also
in deinem QSYS-Design da SPI und füge ein I2C-Modul
ein.
Und!: statt der Instantiierung
Ich habe mir mal den I2C-Core
[[http://www.alterawiki.com/wiki/I2C_%28OpenCores%29]] runtergeladen und
in QSYS eingebunden. Werde das morgen testen. Allerdings verwundert mich
doch, dass im Datenblatt zum DE0Nano steht, dass der adxl345 per SPI (3
wire) angesteuert werden kann. Und auf der CD ist auch ein
Beispielprogramm, worin in QSYS mit dem SPI-3-Wire Modul gearbeitet
wird...
Das mit der Instantiierung werde ich mir so angewöhnen!
Nachdem der I2C funktioniert hat, habe ich mich nochmal dem SPI
gewidmet.
Mit dem "SPI (3 WIRE SERIAL)" scheint der SPI auch zu funktionieren!
Wenn ich das DATA_FORMAT-Register (Adresse 0x31 - siehe obigen Link zum
ADXL345) mit 0x4B (Bit6 - SPI; Bit3 - FULL_RES; BIT1/0 - RANGE)
beschreibe und danach z.B. die Device ID aus Register 0x00 (0x80 =
Read-Befehl + 0x00) lesen möchte bekomme ich das angehängte Signal
zurück. Das Signal selbst stimmt (11100101 - 0xE5), nur leider die Pegel
nicht.
Ich vermute dass das irgendwie mit Pull up/down Widerständen
zusammenhängt...
Meine Versuche den Ausgang als Input/Output zu deklarieren brachten
leider keine Veränderung. Ausschließen würde ich, dass der ADXL einen
Defekt hat, da der I2C immer noch tadellos funktioniert.
Hat jemand eine "schnelle" Idee woran das liegen könnte?
Möchte vermeiden den ganzen Code zu posten. Wenn es jemand auf seinem
Board testen möchte, dann lade ich ihn allerdings gerne hoch.
Gruß
zander
Das meinte ich ja mit der "Pull up/down"-Geschichte.
Aber wie "inaktiviere" ich den FPGA während der ADXL das Signal treibt?
Datenblatt zur SPI (ab Seite 107):
[[www.altera.com/literature/ug/ug_embedded_ip.pdf]]
Zum Lesen/Senden steht der Befehl "alt_avalon_spi_command" zur
Verfügung, aber ich sehe nicht, wie ich darin den Master aktiv/inaktiv
schalte...
Ich mal wieder...
Leider hat sich das Problem noch nicht geklärt, es sind eher mehr Fragen
und Unklarheiten aufgekommen. :-(
Ich habe versucht meinen portpin (I2C_SDAT) tristate-fähig zu bekommen.
Allerdings scheitere ich an der Initialisierung gemäß dem Beispiel von
Herrn Miller:
> Ein Portpin wird so hochohmig geschaltet:>> -- ausgeben bzw. hochohmig schalten> portpin <= 'Z' when direction=input else dataout;>> -- einlesen> datain <= portpin;
Irgendwie müsste ich zuerst meinen portpin als bidirectionalen Pin
definieren, damit die Struktur dem Bild im Anhang entspricht (Quelle:
http://www.altera.com/literature/ug/ug_avalon_tc.pdf S. 13). Dann hätte
ich auch die Signale für direction(≙data_outen im Bild) und
datain(≙data_in im Bild).
Ein Beispiel für einen Tristate-Output in VHDL-Code habe ich auch hier
gefunden:
http://www.altera.com/support/examples/vhdl/v_prebus.html
Folgende Probleme:
1. Wie sind die Signale direction und datain zu deuten? Es sind ja keine
physischen Ausgänge sondern eine Art interne "Richtungsschalter". Wird
da nicht mein Pin-Planer meckern, weil ich die Signale keinem Ausgang
zuweise?
2. Wie weiß mein C-Programm (NIOSII), dass es ein Signal direction gibt,
über welches ich den Eingang am FPGA hochohmig setzen kann?
Dieses Zusammenspiel bzw. der Wissenstransfer vom VHDL-Code zum C-Code
ist mir völlig unklar.
I2C_SDAT wird ja dann im VHDL-Code auf '1', '0' oder 'Z' gesetzt. Für
mein Verständnis müsste ich im VHDL-Code abfragen, wann der FPGA im
C-Code bei der SPI-Kommunikation in den Lese-Modus geht!? Wie gesagt,
das ist mir völlig unklar.
3. Muss das Qsys Modell mit "Tri-State" Modulen erweitert werden?
- Generic Tri-State Controller
- Tri-State Conduit Bridge
- Tri-State Conduit Bridge Translator
- Tri-State Conduit Pin Sharer
(beschrieben in obiger Quelle)
Es wäre sehr nett, wenn mich jemand dazu aufschlauen könnte.
Ich hab noch mein aktuelles vhdl-file im Anhang, vielleicht liegt ja
auch noch mehr im Argen...
Gruß
zander
zander schrieb:> Folgende Probleme:> 1. Wie sind die Signale direction und datain zu deuten? Es sind ja keine> physischen Ausgänge sondern eine Art interne "Richtungsschalter". Wird> da nicht mein Pin-Planer meckern, weil ich die Signale keinem Ausgang> zuweise?
Nein, denn diese Signale beeinflussen ja einen Pin.
> 2. Wie weiß mein C-Programm (NIOSII), dass es ein Signal direction gibt,> über welches ich den Eingang am FPGA hochohmig setzen kann?
Das Programm interessiert sich nicht dafür. Sondern es gibt dem I2C
Modul Sendedaten und einen Startbefehl. Die Richtungsumschaltung und die
Verwaltung der Pins werden dann vom Sendemodul durchgeführt. So, wie es
in jedem uC eben auch geht...
zander schrieb:> um den ADXL345 per SPI auszulesen.
Der hat doch getrennte SDI und SDO (aka. MOSI und MISO), warum also
überhaupt eine Richtungsumschaltung?
Mir ist auch nicht klar, warum "dein" SPI-Modul da überhaupt kollidieren
kann, denn beim SPI sind die Richtungen alle glasklar definiert, und
bestenfalls, wenn 2 Slaves gleichzeitig selektiert werden, kann es zu
Kollisionen auf der MISO-Leitung kommen...
Und ich verstehe nicht, warum du da irgendwelche I2C-Leitungen an den
SPI anklemmst:
Das DE0Nano-Board unterstützt nur eine 3-wire-SPI, siehe Bild im Anhang
(Quelle:
ftp://ftp.altera.com/up/pub/Altera_Material/12.1/Boards/DE0-Nano/DE0_Nan
o_User_Manual.pdf S.22). Daher habe ich nur eine Datenleitung zur
Verfügung.
Ich verwende die vom Hersteller vorgegebenen Signalnamen, daher die
I2C-Namen für die SPI-Verbindung. Etwas unglücklich, gebe ich zu...
Ich verwende zudem das Qsys Modul zur 3-wire-SPI über welches ich dann
im C-Programm des NIOSII sende und empfange.
So Prüfungen erst mal rum, jetzt konnte ich mich wieder dem Thema
widmen...
Lothar, deinen Vorschlag habe ich so nicht 1:1 umgesetzt, aber als
Grundlage verwendet. Ich habe die C-Bibliotheksfunktion des "3-wire-spi"
(int alt_avalon_spi_command(...)) als separate Unterfunktion angelegt
und an der Stelle im Programmcode, an welcher GELESEN wird einen freien
Port im C-Programm auf HIGH gesetzt (in meinen Fall GPIO_0(31)), welchen
ich im VHDL-Programm wie von dir vorgeschlagen überwache.
Hier der Code:
1
spi_hardware_umschalter:process(GPIO_0(31))
2
3
begin
4
-- als Ausgang definieren
5
if(GPIO_0(31)='1')then
6
direction<='1';-- Input
7
8
-- auf HIGH Impedanz / Datenrichtung umschalten
9
else
10
direction<='0';-- Output
11
12
endif;
13
14
endprocessspi_hardware_umschalter;
15
16
Data_In<=I2C_SDAT;
17
I2C_SDAT<=Data_Outwhendirection='0'else'Z';
Und HURA!!! :-) es funktioniert endlich, wie man den Bildern entnehmen
kann.
Info zu den Bildern:
Kanal gelb - Takt
Kanal grün - Chip-Select
Kanal blau - Datenkanal
Kanal pink - Zustand von GPIO_0(31), meinem "Umschalter".
Jetzt verstehe ich auch warum der Master in Richtung des Slave selbst
beim Lesen etwas "schreiben" muss -> damit der Takt aufrechterhalten
wird! Hatte mich im Programm gewundert warum beim Lesen 1byte lang 0er
geschrieben werden, aber jetzt ist das auch klar!
Was ich abschließend nur nicht durchdringe ist, warum der Datenkanal
(blau) einmal nach dem Lesen der DeviceID auf HIGH bleibt, während er
beim Lesen des Registers wieder auf Low geht... Aber das betrifft ja
glücklicherweise nicht das Schreiben und Lesen auf dem SPI.
Somit ist das Thema für mich beendet und ich danke allen Beteiligten
vielmals für die Unterstützung!
zander
zander schrieb:> Was ich abschließend nur nicht durchdringe ist, warum der Datenkanal> (blau) einmal nach dem Lesen der DeviceID auf HIGH bleibt, während er> beim Lesen des Registers wieder auf Low geht
Villeicht, weil ganz zum Schluss nochmal das erste Bit ausgegeben wird?
Duke