Hallo, habe ein Problem bei der Verwendung von SPI mit einem Attiny84. Der Code stammt von Atmel aus der Application note AVR319: Using the USI module for SPI communication - http://www.atmel.com/dyn/resources/prod_documents/AVR319.zip. Die einzigen Anpassungen die ich machen musste waren die Aufrufe für die ISR und die PORTS sowie PINS. Mein Problem ist das ich SPI im Master Mode laufen lassen möchte, aber egal welches Zeichen ich versende, der MOSI Pin (PA6) bleibt permanent auf low wärend das CLK Pin 8 mal toggelt (mit dem Oszi gesehen). Weiß nicht wo der Fehler liegt, da ich leider nicht debuggen kann und das AVR Studio kein USI bzw. SPI simulieren kann. Vielen Dank Christian
Hallo, ich weiß echt nicht mehr weiter, selbst dieser einfachere Code von Eric Toering funktioniert nicht auf meinem Attiny84V (125kHz interner Takt). Es ist genau das selbe Verhalten, wie schon im Post zuvor beschrieben, am Pin PA4 toggelt, wunderbar mit dem Oszi zu sehen, die Clock vor sich hin, PA5 (MISO) liegt auf high aber am PA6 (MOSI) rührt sich nix. Bin dankbar für jede Hilfe MfG Christian
Ich habe gerade keine Zeit, mir im Datenblatt anzugucken, was du da machst. Hier eine Routine, mit der ich erfolgreich via USI/SPI auf einem ATtiny44 mit einem AT86RF230 kommuniziere:
1 | #include <stdint.h> |
2 | #include <util/atomic.h> |
3 | |
4 | static uint8_t |
5 | SPITransfer(uint8_t d) |
6 | {
|
7 | USIDR = d; |
8 | USISR = _BV(USIOIF); |
9 | do { |
10 | USICR = _BV(USIWM0) | _BV(USICS1) | |
11 | _BV(USICLK) | _BV(USITC); |
12 | } while ((USISR & _BV(USIOIF)) == 0); |
13 | return USIDR; |
14 | }
|
15 | |
16 | uint8_t
|
17 | rf230_regrd(uint8_t regno) |
18 | {
|
19 | uint8_t rv; |
20 | |
21 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) |
22 | {
|
23 | PORTA &= ~_BV(7); |
24 | (void)SPITransfer(0x80 | regno); |
25 | rv = SPITransfer(0); |
26 | PORTA |= _BV(7); |
27 | }
|
28 | return rv; |
29 | }
|
(PORTA7 ist das chip select vom AT86RF230.)
Hallo Jörg, danke für den Code. Genau das habe ich auch vor, den AT86RF230 mit einem Attiny84 zu verbinden. Gab es bei deinem Projekt irgendwelche Schwierigkeiten? MfG Christian
Christian Moschner wrote: > Hallo Jörg, danke für den Code. Genau das habe ich auch vor, den > AT86RF230 mit einem Attiny84 zu verbinden. OK, ich hänge dir mal mein komplettes radioif.[ch] mit dran. Du kannst dir auch mal µracoli angucken: https://savannah.nongnu.org/projects/uracoli/ Axel wollte demnächst meine kleine ATtinyX4-basierte Plattform (die ich "tiny230" genannt habe) dort mit einbinden. > Gab es bei deinem Projekt > irgendwelche Schwierigkeiten? Die einzige nennenswerte Schwierigkeit habe ich, mit ISP zu programmieren, wenn die Firmware den AT86RF230 bereits aktiviert hat. Der blockiert dann das SPI-Interface. Ich habe noch nicht ganz rausgefunden, warum das so ist: ist habe am /SEL einen Pullup von ca. 1 MΩ dran, damit der Transceiver beim RESET des AVR (alle IOs hängen in der Luft) nicht selektiert wird. Aus irgendeinem mir noch nicht nachvollziehbaren Grund wird aber die /SEL-Leitung direkt beim RESET (vom Programmer aktiviert) aktiv. Der einzige Programmer, der es schafft, das ISP trotzdem noch zu übernehmen, ist ein AVRISP mkII. Ein JTAGICE mkII oder ein AVR Dragon (für debugWIRE) schaffen es nicht. Sinnvoller Weise sollte man also wohl in dieser Leitung eine Lötbrücke vorsehen, damit der AT86RF230 im Zweifelsfalle zum Schweigen gebracht werden kann.
Jörg Wunsch wrote: > übernehmen, ist ein AVRISP mkII. Ein JTAGICE mkII oder ein AVR > Dragon (für debugWIRE) schaffen es nicht. Oder einfach nen Bootloader nehmen, der schafft es auch. Für den Bootloader ist man nämlich nicht an bestimmte Pins gebunden, da geht jeder IO-Pin. Peter
Peter Dannegger wrote:
> Oder einfach nen Bootloader nehmen, der schafft es auch.
Dafür verbraucht man halt noch mindestens einen IO-Pin extra. Wenn
man nur noch 4 für die Applikation zur Verfügung hat, ist das schon
heftig.
Je nach Anwendung bleiben von einem 8pinner mit Bootloader 5 oder 6 Pins für die Anwendung übrig. Reset wird dann ja meist nicht benötigt und den Bootloader-Pin kann man u.U. mit einem Anwendungspin teilen.
Jörg Wunsch wrote: > Peter Dannegger wrote: > >> Oder einfach nen Bootloader nehmen, der schafft es auch. > > Dafür verbraucht man halt noch mindestens einen IO-Pin extra. Wenn > man nur noch 4 für die Applikation zur Verfügung hat, ist das schon > heftig. Wie kommst Du auf nur 4? Mit nem Bootloader hast Du natürlich alle 12 IOs zur Verfügung für die Applikation. Reset und SPI werden ja zum Proggen nicht mehr gebraucht. Und der Bootloaderpin lauscht nur ne Weile (~0,3s) nach dem Reset auf das Paßwort, danach ist er auch verfügbar. Peter
Peter Dannegger wrote: > Wie kommst Du auf nur 4? Weil ich davon ausgehe, dass man /RESET nicht für die Applikation hat -- sonst kann man kein debugWIRE mehr benutzen. Außerdem braucht der AT86RF230 eben auch seine Pins. Bleiben 4 GPIOs für die Applikation übrig. Da der das SPI-Interface ohnehin schon benutzt, kostet ISP nichts extra (es benutzt die gleichen Pins, auch wenn das bei mir gerade aus irgendeinem Grund nicht richtig klappt), während dein Bootloader ein Pin extra benötigen würde. Ein Pin vom SPI kann er sich nicht teilen, da der Bootloader (im Gegensatz zu ISP) nicht während Reset arbeiten kann, und zur Laufzeit ist das SPI halt durch den AT86RF230 belegt. Ergo bringt der Bootloader hier gar keinen Gewinn, sondern nur zusätzliche Umständlichkeit. (ISP ist im Großen und Ganzen ja recht einfach zu handhaben.) Was ich allerdings in meiner derzeitigen Applikation wirklich nicht verstehe ist, warum PORTA0 (was das /SEL für den AT86RF230 ist) zwar die ganze Zeit inaktiv ist, aber just mit dem /RESET plötzlich aktiv wird (sagt mein LA zumindest). Damit belegt der AT86RF230 den SPI- Bus genau in dem Moment, wo das ISP aktiv werden will, und es kommt zur Kollision. > Reset und SPI werden ja zum Proggen nicht mehr gebraucht. > Und der Bootloaderpin lauscht nur ne Weile (~0,3s) nach dem Reset auf > das Paßwort, danach ist er auch verfügbar. Nach welchem Reset denn, wenn du dafür kein Pin mehr spendieren willst...?
Jörg Wunsch wrote: > Nach welchem Reset denn, wenn du dafür kein Pin mehr spendieren > willst...? Dem Power-On-Reset.
Andreas Kaiser wrote: > Dem Power-On-Reset. Ick, jedesmal ein power-cycle. OK, mit debugWIRE isses natürlich auch nicht besser. Bye-bye, remote debugging. (Ich bin es gewohnt, den lieben langen Tag meine AVRs übers Netz zu debuggen, die im 200 m entfernten Labor werkeln, aber das sind alles ATmegas mit JTAG.)
Ich habe zwar debugWire und limitiertes JTAG rumliegen, aber JTAG habe ich bislang nur selten gebraucht und debugWire noch überhaupt nicht. Meistens tut's ein serieller Ausgang und/oder ein paar Statuspins. Und wenn man tatsächlich mal einem 8pinner sowiel Programm ohne freien Pin unterjubelt, dass die Debugsession kompliziert wird - nun ja, man muss diese Schritte nicht unbedingt mit dem 8pinner anfangen, es langt wenn das Endprodukt den verwendet. Am Anfang darf es auch ein anderes Modell sein, wenn dem keine grundsätzlichen Hardwareabhängigkeiten im Weg stehen.
Andreas Kaiser wrote: > Meistens tut's ein serieller Ausgang und/oder ein paar Statuspins. Naja, ist kein Vergleich zu richtigem Online-Debugging. > Und > wenn man tatsächlich mal einem 8pinner sowiel Programm ohne freien Pin > unterjubelt, dass die Debugsession kompliziert wird - nun ja, man muss > diese Schritte nicht unbedingt mit dem 8pinner anfangen, es langt wenn > das Endprodukt den verwendet. Hier ging's ja um 14-Pinner. > Am Anfang darf es auch ein anderes Modell > sein, wenn dem keine grundsätzlichen Hardwareabhängigkeiten im Weg > stehen. Das ist bei den HF-Teilen nicht ganz einfach. Du müsstest eine separate Platine für den größeren Controller entwerfen. Da der große Controller dann auch andere Hardware hat (z. B. richtiges SPI statt der USI), wird die Portierung zusätzlich erschwert. Es hat schon was für sich, wenn man die fertige Applikation auf der fertigen Platine auch noch online debuggen kann.
Jörg Wunsch wrote:
> müsstest eine separate Platine für den größeren Controller entwerfen.
Entwickelst du Software immer als homogenen quadratischen Block komplett
neu, ohne Module? Ich pflege eher das Baukastenverfahren zu verwenden,
und das kann auch mal heissen, dass ein solches Modul erst einmal mit
einem Testaufbau an einem Mega32 im STK500 hängt bis es läuft.
Ein Gutteil des Debuggings verlegt sich so auf angenehmere Plattformen.
Ok, HF ist ein anderes Thema. Und nicht meines.
Den HF-Krempel kannst du nicht als freifliegenden Drahthaufen testen. Dafür musst du schon irgendwas solides hinsetzen. Das kann natürlich ein anderer Modul sein mit einem größeren Controller, trotzdem bereitet die Portierung auf einen kleinen Controller danach einigen Aufwand, sodass der Debugger dafür ziemlich hilfreich ist. Ich habe nicht geschrieben, dass er unabdingbar sei, aber es spart eben einfach Zeit. Klar, wenn du ihn noch nie benutzt hast, ist dir diese Erfahrung bislang erspart geblieben. ;-)
Jörg Wunsch wrote: > dein Bootloader ein Pin extra benötigen würde. Ein Pin vom SPI kann > er sich nicht teilen, da der Bootloader (im Gegensatz zu ISP) nicht > während Reset arbeiten kann, und zur Laufzeit ist das SPI halt durch > den AT86RF230 belegt. Nö, wie schon gesagt, der Bootloader geht mit jedem Pin, also natürlich auch mit einem der SPI-Pins. Z.B. der MOSI wäre geeignet und würde auch Peripherie nicht beeinflussen, da ja SCK nicht getaktet wird, kann der ruhig zappeln. > (ISP ist im Großen und Ganzen ja recht > einfach zu handhaben.) Wenn man davon absieht, daß man extra Hardware oder nen echten LPT-Anschluß braucht. > Was ich allerdings in meiner derzeitigen Applikation wirklich nicht > verstehe ist, warum PORTA0 (was das /SEL für den AT86RF230 ist) zwar > die ganze Zeit inaktiv ist, aber just mit dem /RESET plötzlich aktiv > wird (sagt mein LA zumindest). Damit belegt der AT86RF230 den SPI- > Bus genau in dem Moment, wo das ISP aktiv werden will, und es kommt > zur Kollision. Ich würde mal den Pullup auf 10k verringern, 1M erscheint mir doch sehr hoch, da kann leicht eine Leitung übersprechen. Ich hab zwar ewig keine SPI-Programmierung mehr selber gemacht, aber bei den classic-AVRs war mir aufgefallen, daß nach dem Reset noch die interne Resetzeit (16ms) abgewartet werden mußte, ehe das Program-Enable geschickt werden konnte. Könnte gut sein, daß während dieser internen Resetzeit Pins zappeln. Ein Programmieralgorithmus, der nach Reset = Low noch 16ms wartet, sollte es daher packen. > Nach welchem Reset denn, wenn du dafür kein Pin mehr spendieren > willst...? Entweder Power-On oder Watchdog durch die Applikation. Peter
Peter Dannegger wrote: >> (ISP ist im Großen und Ganzen ja recht >> einfach zu handhaben.) > Wenn man davon absieht, daß man extra Hardware oder nen echten > LPT-Anschluß braucht. Ist aber erstens da und zweitens brauchst du für den Bootloader ja auch nicht nur Luft -- und sei's ein RS-232-Levelshifter. (Da wir über debugWIRE geredet haben, ist es eigentlich klar, dass das Programmiergerät verfügbar ist.) >> Was ich allerdings in meiner derzeitigen Applikation wirklich nicht >> verstehe ist, warum PORTA0 ... > Ich würde mal den Pullup auf 10k verringern, 1M erscheint mir doch sehr > hoch, da kann leicht eine Leitung übersprechen. Naja, die Applikation soll eigentlich sparsam mit Energie umgehen, es handelt sich ja um IEEE 802.15.4. ;-) Aber ich habe auch schon mal einen 10-kΩ-Widerstand drauf gepappt, hat keine Änderung ergeben: der Ausgang wird ganz offensichtlich im Moment des Reset aktiv nach unten gezogen. > Ich hab zwar ewig keine SPI-Programmierung mehr selber gemacht, aber bei > den classic-AVRs war mir aufgefallen, daß nach dem Reset noch die > interne Resetzeit (16ms) abgewartet werden mußte, ehe das Program-Enable > geschickt werden konnte. Das macht das JTAG ICE im ISP-Modus ohnehin. > Könnte gut sein, daß während dieser internen Resetzeit Pins zappeln. Nö, die sollten innerhalb weniger Takte normalerweise hochohmig werden. Ich habe mir die Abfolge bei einem Reset mal von Leuten erklären lassen, die es wissen sollten... Darum macht es mich ja ziemlich stutzig.
Christian schrieb: > Hallo, habe ein Problem bei der Verwendung von SPI mit einem > Attiny84. > Der Code stammt von Atmel aus der Application note AVR319: Using the USI > module for SPI communication - > http://www.atmel.com/dyn/resources/prod_documents/AVR319.zip. > > Die einzigen Anpassungen die ich machen musste waren die Aufrufe für die > ISR und die PORTS sowie PINS. Ich weiß, dieser Thread ist über 10 Jahre alt, aber eine Lösung für die ursprüngliche Frage war leider nicht dabei. Folgende Fehler sind mir aufgefallen: * beim ATTiny84 ist im Datenblatt A5 mit MISO und A6 mit MOSI beschriftet. Das ist leider sehr irreführend - bei Verwendung von USI muss man nämlich auf "DO" (Data Out) und "DI" (Data In) achten. Und das ist blöderweise genau anders herum als MOSI/MISO. DO (Data Out) liegt auf A5 und muss bei den Slaves an MOSI angeschlossen werden. DI liegt auf A6 und muss bei den Slaves an MISO angeschlossen werden:
1 | #if defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
2 | #define SPI_DDR_PORT DDRA
|
3 | #define USCK_DD_PIN DDA4
|
4 | #define DO_DD_PIN DDA5
|
5 | #define DI_DD_PIN DDA6
|
6 | #endif
|
* der Code zum Lesen vom Bus enthält einen Fehler. Wenn gelesen werden soll, muss man quasi irgendwas auf den Bus schreiben, die währenddessen gelesenen Daten stehen anschließend in einem Register bereit. I.d.R. sendet man also zuerst eine Registeradresse auf den Bus, und anschließend z.B. ein 0x00, um dem Slave die Gelegenheit zu geben, währenddessen seine Daten zurück zu schicken. Viele Grüße -klk
klk schrieb: > Das ist leider sehr irreführend Es entspricht einfach deren Funktion beim ISP. Bei vielen AVRs ist die Funktion des SPI-Blocks dann gleichlautend wie bei ISP, aber bei den USIs ist das nicht der Fall. > aber eine Lösung für die ursprüngliche Frage war leider nicht dabei. Das stimmt so nicht. Ich habe meine Lösung ganz oben vorgestellt, und diese funktioniert seit genauso vielen Jahren, wie der Thread alt ist.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.