Hat Jemand hier zufällig die Erfahrung gemacht dass der µC bei einfacher Flankenerkennung nicht bei kommt? Mein Programm fragt in ner Schleife den Zustand eines Ports im Takt eines Clocks ab. Leider schafft das der µC erst wenn ich die Taktfrequenz (Teilungsfaktor mainCLK/64) "niedrig" einstelle (281kHz). Ist für ne Datenübertragung von ADC zu µC und sollte bis zu 27MHz können... Mich wundert das ehrlich einwenig dass der Rechenknecht "so wenig" kann. :)
281kHz * 64 ergibt bei mir ca 18Mhz für die Mainclock. Wie sollen da dann 27MHz gehen? Code wäre hilfreich. Ansonsten habe ich diese Erfahrung noch nicht machen können.
Hmmm, mach man das nicht normalerweise umgekehrt? Man lässt einen Timer mit einer entsprechenden Frequenz laufen und holt sich nach einem Input-Capture-Interrupt den Wert, wann genau die Flanke war, aus dem Register. In der Zwischenzeit kann sich die CPU um andere Dinge kümmern.
ok ich hab wohl zu wenig informationen gesendet, tschuldigung schonmal danke für die antworten, ich wills versuchen weiter zu präzisieren. @stefan: ich will nicht wissen wann ne flanke war sondern will wissen welcher wert an einem pin anliegt wenn die flanke da ist. @hendrik: ein ad wandler (ADS1271) soll seine 24bit seriell an einen at91sam7 senden; mittels spi schnittstelle klappt das nicht da der atmel dafür nur ein datenEIN register von 16bit hat -> alternativ wärs per pdc möglich gewesen daten zu holen. ok ich bastel halt spi größer nach. ich mach aus den pck's zwei clock einen um den ADC zuclocken (CLK) und einen für den datentransfer (SCLK). laut datenblatt des ADC soll CLK und SLCK max. 27MHZ taktbar sein. mittels pck kann ich aus den 18MHZ mainclk des Controllers (1, 1/2, 1/4, 1/8, 1/16, 1/32, 1/64) beide clock bereitstellen. da mein ziel ist das ganze so schnell wie möglich laufen zulassen um die hohe abtastrate des ADC auszunutzen hab ich mit den teilungsfaktoren oben angefangen und langsam nach unten durch probiert. erst bei der langsamsten teilung hats dann ohne massiven daten verlust funktioniert. soll heissen bei DatenIn @ 281kHz kommt der µC hinterher jede flanke zu erkennen und mir daten auszulesen. hier auch n auszug aus der ausleseschleife (läuft 24mal durch weil 24bits daten kommen und gibt dann nen wert aus); der clk wird weiter oben konfiguriert(unkritisches hab ich weggelassen). (*(volatile unsigned int*)0xFFFFFC44) = 0x00000019; // pck2 (SCLK) : config. PMC_PCKR -> CSS=MainCLK, PRES=64 => 0,281MHz (*(volatile unsigned int*)0xFFFFFC00) = 0x00000301; // PMC_SCER,PMC enable -> SCLK an for (z=24;z>0;z--) { while (!((*(volatile unsigned int*)0xFFFFF63C) & 0x00000010)); // solange ungleich 0 nichts unternehmen AD_Wert |= ((*(volatile unsigned int*)0xFFFFF43C) & 0x00000040); // alles außer der ersten stelle (wert aus pa6) weglöschen AD_Wert <<= 1; // Wert um eins shiften while (((*(volatile unsigned int*)0xFFFFF63C) & 0x00000010)); // } ich denke man könnt die flankenerkennung mittels interrupts verbessern wogegen ich mich aber aus unerfahrung sträube. ich wollte es erstmal so versuchen und bin eigentlich davon ausggangen das der atmel schnell genug wäre um alles zu erkennen. vllt ein irrtum...
ich spinn mal ein bisschen rum: -2 mal 16 bit per spi einlesen und 8 bit verwerfen? -3 mal 8 bit per spi einlesen? -3 8-bit-sipo schieberegister und parallel in den sam7 einlesen? -cpld als 24bit sipo-schieberegister? -cpld + sram und die daten zwischenspeichern? -fpga?
dankedanke für die antworten aber ändert das die problematik? @andreas: ssc (hab ich mich noch nicht eingelesen) wird mir aber direkt nichts bringen da ich bereits in ein, beliebiges, 32bit register schreibe. die datenerfassung funktioniert ja auch aber halt "langsam". @alex: wird der clock (bei verwendung cpld, fpga oder aufteilung des datenworts) dann richtig und exakt erfasst? die geschwindigkeit des clock bleibt doch bestehen und die notwendigkeit ne flanke zu erkennen ebenfalls. also wird mir dieser vorschlag nicht weiter helfen.
also ich hab das datenblatt( http://focus.ti.com/lit/ds/symlink/ads1271.pdf ) grad mal schnell ueberflogen und versteh das problem nicht. du verwendest den spi-mode, startest die wandlung, wartest bis drdy auf low-pegel geht, und holst dir dann per spi die 24 bit ab. eine notwendigkeit da irgendwelche flanken abzufragen sehe ich nicht.
hmm ja das kommt im datenblatt des ti auch nicht rüber; problematisch wirds hauptsächlich mit dem atmel. und SPI ansich ist nun meiner meinung nach eher eine sehr sehr wage und unsichere aussage... wie frage ich denn per SPI das drdy signal ab? -> ich brauch eine weitere leitung die nicht im SPI ist. will mal kurz auf die porblematik spi und atmel eingehn ich ich erfahren hab... ich nutze den atmel api-befehlsatz, starte den spi-mode mit atmel als master und ti als slave... ok soweit in ordnung dann aber kein clock der spi schnittstelle (SCLK); der atmel sendet clock nur wenn er daten senden will! und nur solange wie die daten lang sind. da das datensende bzw -empfangsreg. 16 bit groß ist gibt der master ganze 16 takte aus und ist dann still. wenn ich dagegen 24bits auslesen will siehts schwarz aus für mich. daher hab ich den grundgedanken der spi schnittstelle übernommen, weitere leitungen hinzugefügt und halt programmtechnisch nachgebastelt dass es funzt.
Du konfigurierst die SPI Schnittstelle auf 8 Bit und manuelle Kontrolle der CS Leitung. Dann schreibst du 3 mal 8 bit und liest jeweils 8 bit ein. Anschließend ziehst du die CS Leitung wieder auf High (Indem Du ein Bit im Control-Register des SPI setzt) => 24 bit eingelesen Keine Zusätzlichen Leitungen nur CS, SClock und MISO (MOSI falls Du den ADC noch konfigurieren kannst/willst)
constantin wrote: > @andreas: ssc (hab ich mich noch nicht eingelesen) wird mir aber direkt > nichts bringen da ich bereits in ein, beliebiges, 32bit register > schreibe. die datenerfassung funktioniert ja auch aber halt "langsam". Wie so nichts bringen, ich denke dieses "langsam" war das Problem? Schau dir das Frame Sync Format deines ADC und den SSC des AT91 an, das passt wunderbar zusammen.
@ dirk: gute idee & werde ich ausprobieren; hatten wir selbst auch mal als möglichkeit erdacht aber wenn eventueller geschwindigkeitseinbussen wieder verworfen. das die aktuelle lösung jetzt langsamer ist, ist halt ironie :-) @ andreas: tschuldige wollt nur sagen dass ich mich eben noch nicht mit ssc beschäftig habe und bin davon ausgegangen das dies nur das problem mit dem 16bit datenregister lösen würde das geschwindigkeitsproblem aber bestehen bliebe. werd mich nun mal einlesen...
> und SPI ansich ist nun meiner meinung nach eher eine > sehr sehr wage und unsichere aussage... das mag daran liegen, dass ich mit den sam7 oder anderen arm noch nichts gemacht habe. scheint ja wirklich kompliziert zu sein, einfachste sachen damit zu bewerkstelligen. aber selbst eine (master-)softspi kommt ohne irgendwelche flanken aus. sclk 2 mal toggeln und naechstes bit einlesen. deswegen verstehe ich die problematik eigentlich immer noch nicht. naja, egal, ich will mich nicht zu weit aus dem fenster lehnen und lese mal gespannt mit.
constantin wrote:
> dass ich mich eben noch nicht mit ssc beschäftig habe
Mach das mal, dann kannst du dir all das mit der Flankenerkennung
sparen.
also erstma einen schönen wochenanfang =) ich hab mich leider noch nicht in SSC eingelesen; werd ich aber nun jetzt noch tun. ich hab dagegen versucht die per spi zu übertragenden werte in 3 etappen ein zulesen das aber nur mit mittelmäßigem erfolg. aus dem daten register für die empfangenen werte lese ich immer den selben wert. hier ein auszug aus der auslese schleife: if((DRDYSPI == 0) ) // wenn drdy low ist { AD_WertSPI=0; for (zaehlerSPI = 3;zaehlerSPI >= 1;zaehlerSPI--) { AT91F_SPI_Enable(AT91C_BASE_SPI0); // Einschalten des SPI0 AT91F_SPI_PutChar(AT91C_BASE_SPI0,SendeWert,0); // senden von Wert "SendeWert" = 255 (8bit)/ Dummy Wert AD_WertSPI |= (AT91F_SPI_GetChar(AT91C_BASE_SPI0) & 0xFF); // nur 8bit interessieren nicht die 16bit des Registers AD_WertSPI <<= 8; // Wert in AD_Wert verschieben rprintf("Ergebnis: %x\n",AD_WertSPI); // Textausgabe über Serielle Schnittstelle AT91F_SPI_Disable(AT91C_BASE_SPI0); } Wie speichert denn der Atmel die empfangenen Daten im Register ab? überschreibt der Controller die vorhandenen oder beginnt er an "leeren" stellen im Register zu schreiben? eins werd ich noch schnell ausprobiern bevor ich mich ans SSC mach; ich hab die SPI schnittstelle nicht rückgesetzt fällt mir grad auf...
Also ich würde als erstes das rprintf aus der Schleife entfernen. SPI muß auch so konfiguriert sein, daß die CS Leitung nicht automatisch auf high geht. Dazu muß das CSAAT Bit im CS-Control Register gesetzt sein. Dann machst Du die Schleife Nach dem PutChar mußt Du aber erst einmal warten bis das SPI zum Auslesen bereit ist. Wenn alle 3 Bytes übertragen sind mußt Du noch den Vorgang abschließen und CS freigeben. Dazu LASTXFER Bit im SPI Control Register setzen.
Vorschlag: Nimm mal diese Funktion zum Auslesen BYTE AT91_spi(BYTE outgoing) { BYTE incoming; while( !( pSPI->SPI_SR & AT91C_SPI_TDRE ) ); // transfer compl. wait pSPI->SPI_TDR = (WORD)( outgoing ); while( !( pSPI->SPI_SR & AT91C_SPI_RDRF ) ); // wait for char incoming = (BYTE)( pSPI->SPI_RDR ); return incoming; } Also AD_WertSPI = 0; for (zaehlerSPI = 3;zaehlerSPI >= 1;zaehlerSPI--) { AD_WertSPI |= AT91_spi (0xFF); // Send/Receive } pSPI->SPI_CR = AT91C_SPI_LASTXFER; // CS high rprintf("Ergebnis: %x\n",AD_WertSPI);
P. S.: Will mich nicht mit fremden Federn schmücken: Die Beispiele stammen von der WinARM Seite http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/efsl_arm/index.html
hmm das cs hab ich ganz weg gelassen weil es am adc nicht genutzt wird. um diesen bereit zum wandeln zu bekommen sendet man statt dessen eine synchronisierung. diese setzt den adc zurüch regelt filter und blabla und sobald werte gewandelt & zum abholen bereit sind geht DRDY low. da steig ich dann mit meiner ausleseschleife ein. dirk schrieb: >Nach dem PutChar mußt Du aber erst einmal warten bis das SPI zum >Auslesen bereit ist. laut datenblatt des ADC läuft das parallel ab; µC sendet ein bit und empfängt eins. ich muss also hoffen dass alle werte im data receive register sind. aber zu deiner zweiten antwort mit dem codebeispiel; leider kann mein compiler nichts mit byte oder word anfangen. in was wandle ich das am besten?
> hmm das cs hab ich ganz weg gelassen weil es am adc nicht genutzt wird. Hmm, ok. Dann vergiß LASTXFER. > laut datenblatt des ADC läuft das parallel ab Ja, das is bei SPI so. Trotzdem mußt Du warten bis Dein Byte gesendet wurde bevor Du lesen kannst. > compiler nichts mit byte oder word anfangen Das Beispiel war nur kopiert. Ich würde normalerweise uint8_t für Byte verwenden (uint8_t ist in stdint.h definiert). Die Typen sollten bei den meisten C-Compiler vorhanden sein.
ich weis nicht wie aber ich glaub die spi schnittstelle ist verstorben... egal was ich mach mit einfachsten progrämmchen...nix mehr aus den spi pins zu holen, gar nix.
freude, freude, auferstanden von den totgeglaubten =) nach langem suchen und neuprogrammieren hat sich die spi schnittstelle wieder gemeldet... freu weis nicht wo der fehler war und kann ihn nur in meinem programm vermuten was aber , weils schon lief, mich auch zweifeln lässt. naja egal. bin jetzt soweit dass die daten jetzt in zwei(!) durchgängen (je 12bit) aus dem data receive register gelesen werden. ich wollte zwar auf das überlaufbit RDRF warten aber das kommt erst wenn das receive data reg voll ist (bei 16bit) obwohl ich die größe der transferbits auf 12bit begrenzt habe. daher nochmal meine frage da ich zweimal den gleichen wert (pro durchlauf nacheinander) aus diesem register lese: wie werden die werte in diesem register gespeichert? a la stack bis das reg voll ist? wenn ja gibts da ne möglichkeit dieses receive reg rückzusetzen? gruß constantin
warum nimmst du nicht die ssc ???? sondern erstmal alle weniger geeigneten ports, usw. , willst dus besonders spannend gestalten?
nanana erstens bin ich noch anfänger auf dem gebiet µC insbesondere at91 und zweitens hab ich schon mal erwähnt das ich mich noch nicht in SSC eingelesen hab. das hatte ich gestern zwar vor da ist mir dann aber die spi schnittstelle vermeintlich flöten gegangen. und mir hatte das erstmal höhere priorität als einlesen in was neues (zumindest für mich scheint mir). und drittens ist das ssc script auch lockerflockige 36 seitenstark dass ich auch wieder ne zeit damit beschäftigt bin (was ich eigentlich gehofft hatte vermeiden zu können). also ich hab ssc jetzt vor mir liegen und werd versuchen damit zum laufen zubringen. hatte halt gehofft es nun per spi(weil ich mich jetzt darin halbwegs auskenne) "relativ" einfach hin zu kriegen.
Kannst Du mal wieder den Code posten (so wie Du in im Moment verwendest)? Nach Ansicht des ADC Datenblattes muß ich aber Andreas und alfsch Recht geben, daß SSC besser geeignet ist. Insbesondere, da Du das FrameSync Bit sowieso auswerten mußt.
hier der aktuelle Code der Datenauslesung aus dem RDR; im *.txt der gesamte (mit inits und so)... if((DRDY == 0) && (SW_abfrage == 1) ) // { EmpfangeWert = 0; stand=1; for (i=2;i>=1;i--) { AT91F_SPI_PutChar(AT91C_BASE_SPI0,SendeWert,0} // senden von Wert "SendeWert" über chipselect cs=0 EmpfangeWert |= (AT91F_SPI_GetChar(AT91C_BASE_SPI0) & 0x00000FFF); if (stand != 0) // damit der eingelesene Wert nur einmal geshiftet wird { EmpfangeWert = EmpfangeWert << 12; // um 12bit shiften stand=0; } } SW_abfrage = 0; rprintf("empfangener Wert: %x\n",EmpfangeWert); } } bin auch grad am lesen des ssc bin aber noch nicht soweit proggen zu können. fehlt noch der einstieg kmmt aber sicher noch =)
Du solltest auf jeden Fall for dem Senden und Lesen das Statusregister auswerten. Siehe mein Beispiel von gestern (In dem war aber noch ein Fehler, da ich das shiften des Ergebnisses vergessen hatte.)
hallo constantin, wenn dein statement aus deinem 1.posting halbwegs stimmt und der at91sam7s den adc mit max. geschwindigkei auslesen möchte/muß dann vergiss schnelle mal alle lösungen die nicht die pdc nutzen. du wirst sonst dank div. interrupt latenzzeiten nie auf eine vernünftige lösung kommen. btw: ich finde es immer wieder erstaunlich, dass arm anfänger (ich unterstelle dir mal diesen "zustand") sich gleich mal mit der anbindung eines solchen externen devices beschäftigen. vielleicht solltest du dir mal die interne peripherie ansehen und diese versuchen zu verstehen. das datenblatt des at91sam7s ist nicht ohne grund 600 seiten stark und darin steht noch fast nichts über den arm7. also wenn du wirklich vernünftig mit diesem prozessor arbeiten möchtest, würde ich dir empfehlen die allg. kapitel des datenblatts und danach die kapitel über die für dich interessante peripherie genau zu studieren und vielleicht anhand der beispiele von www.at91.com mal das ganze auch in der praxis zu nutzen. gruss gerhard
hallo constantin, und noch eine bitte: verwende beim nächsten posting einen betreff der dein problem beschreibt und nicht eine etwas unqualifizierte ausage beinhaltet. gruss gerhard
@gerhard: zu deinem ersten posting weswegen ich mich als anfänger (nicht nur im bereich arm auch im bereich programmierung, bin da mal ehrlich) gleich an die anbindung von externen bauteilen an einen controller wage? hmmm zwei antworten A.) weil beides gebraucht wird und weil's einer machen muss und B.) "Viel Feind, Viel Ehr' " =). Aber du hast schon recht damit das man sich richtig in so einen controller einlesen sollte aber unter "fertigwerd"-Zwang stehend und auch voller Ungeduld zuviel Lesen vermeinden wollend, hatte ich mir eben nur Bereiche heraus gepickt (->SPI) die schon vom ADC vorgegeben waren... zu deinem zweiten post: auch hier geb ich dir recht muss will mich auch bessern aber auch sagen dass ein etwas unspezifizierter titel nicht gleich abschreckt (mehr Leute (potentionielle Helfer) lesen den Thread). beim schreiben des ersten posting war das programm aber auch in einem relativ unbestimmten Status (die kommunikation hab ich damals per selbst erzeugten clocks gemacht und bin dann erst nach tipps aus dem forum wieder auf SPI zurück).
zu ssc und pdc habe ich nun je ne frage: A) ssc verstehe ich so dass ich damit nur mit einem einzelen bauteil kommunizieren kann. Richtig? B.)an die pdc kanäle (DBGU - TDES) kann ich je mit einem externes bauteil kommunizieren. Wie frei bin ich dabei mit den baudraten? Sind Sie von einander abhängig? Falls ich USO zB unbedingt bräuchte kann ich dennoch TDES als "einfache" PDC schnittstelle frei nutzen? Ich mein sie hängen doch alle am gleichen Periperhal DMA Controller (pdc). Und dann noch ne abschlussfrage zum pdc: kann jmd. den Unterschied in der übertragungsgeschwindigkeit zwischen einfacher SPI zur PDC schnittstelle vllt. in Zahlen oder zumindest ungefähr fest machen? da ich in meiner spi schleife keine interrupts nutze, verliere ich doch kaum zeit anders wie gerhard in einem vorherigen post meinte? >...der at91sam7s den mit adc max. geschwindigkei auslesen möchte/muß dann >vergiss schnelle mal alle lösungen die nicht die pdc nutzen. du wirst >sonst dank div. interrupt latenzzeiten nie auf eine vernünftige lösung >kommen. ausserdem: hab die sache mit der spi schnittstelle fertig und es läuft einwandfrei. muss zwar noch etwas optimiert werden aber läuft freu DANKE an alle die mich unterstützt oder zumindest tipps gegeben haben. war echt ne große hilfe. gruß constantin
Bei schnellem SPI-Takt kann es sein dass das "manuelle" Schreiben/Lesen der Daten aus dem SPI-Transfer-Register länger dauert als die eigentliche Übertragung. An diesem Punkt kann der PDC die Übertragung beschleunigen. Um wie viel - das kann man nicht allgemein in Zahlen angeben. Siehe auch http://www.mikrocontroller.net/articles/DMA
Die einzelnen PDC-Kanäle lassen sich unabhängig nutzen, der PDC hat mit Baudraten usw. selbst nichts zu schaffen, er kümmert sich nur ganz stupide um das Lesen/Schreiben der Transferregister sobald diese bereit sind.
> hab die sache mit der spi schnittstelle fertig und es läuft einwandfrei.
Woran lag es dann letztendlich?
weil ich einige probleme hatte undviele gelöst bzw umgangen worden sind vermute ich du (dirk) meinst das letzte problem; das zweimalige auslesen des gleichen wertes ausm RDR. gelöst hab ich mit ner warteschleife um sicher zusein dass alle zu sendenden werte verschickt wurden -> while (((*(volatile unsigned int*)0xFFFE0010) & 0x00000002) == 0); //solange TDRE gleich null ist sind nicht alle Daten gesendet worden und passend dazu natürlich auch auf das ende vom schreiben ins RDR warten, nachdem ich wieder einen 12bit dummy wert weg ins nirvana geschickt habe ->AT91F_SPI_PutChar(AT91C_BASE_SPI0,SendeWert,0); ->while (((*(volatile unsigned int*)0xFFFE0010) & 0x00000001) == 0); damit hats dann einwandfrei funktioiert den 24bit wert in zwei etappen einzulesen; verglichen mit der oszilloscop-darstellung war dann auch alles in ordnung. der ganze code dazu oben im *txt file falls den jmd interessiert. nochmal an alle danke Ich werd versuchen das ganze auch noch über den pdc laufen zu lassen; nach einlesen und grade auch dem link von andreas bin ich restlos überzeugt worden =) so nun wünsch ich allen noch schöne tage & gute party's constantin
hallo constantin, wen ndu mehr über den pdc wissen möchtes dann würde ich dir empfehlen das sog. self training von www.at91.com mal anzusehen. www.at91.com => support => training => Introduction to Atmel AT91SAM7A,S,X Microcontroller Series => pdc. dort findest du reichlich infos übner den pdc (und auch die restl. peripherie) gruss gerhard
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.