Wie kann man schnell Carry invertieren ? Eine Möglichkeit wäre ein Sprungbefehl z.B: brcc... und dann SEC brcs... und dann CLC Bernhard
Bernhard S. schrieb: > Wie kann man schnell Carry invertieren ? Leider garnicht. Aaaber: Laß mal was über den Kontext des Problems hören. Oft scheint es nur im ersten Anlauf so, als wenn man unbedingt an den Flags direkt rummachen müßte. Da bin ich auch schon mehrmals drauf reingefallen und habe erst im zweiten oder dritten Anlauf eine Lösung gefunden, mit der sich dann nachweislich herausgestellt hat, dass das auch eigentlich garnicht nötig war.
>Laß mal was über den Kontext des Problems hören. Es handelt sich um dieses Projekt, ich "fummle" es gerade von einem 16MHz auf einen 8MHz Takt um, alles ist sehr zeitkritisch: https://www.mikrocontroller.net/topic/241934 Eine Funktion liest mir ein entsprechendes BIT aus dem SRAM aus, der Rückgabewert ist Carry, welches später MATCH-ROM oder SEARCH-ROM oder Scratchpad read ermöglicht.
:
Bearbeitet durch User
Und warum musst du es bitweise umdrehen? Nach 8 Bits ist einfacher.
>Und warum musst du es bitweise umdrehen? Nach 8 Bits ist einfacher.
So einfach ist das nicht:
Weil der MASTER vom 1WIRE Datenbus mur einzelne Bits sendet bzw.
empfängt,
speziell im Search-Modus,
2 Bits empfangen, danach ein Bit senden und das ganze 64 Mal.
Ja und? Ob du die Adresse als Original oder dessen Komplement verarbeitest ist doch vom 1-Wire Verfahren her schnurz. Ansonsten zeig mal deinen Code. Den Asm. In dem Links steht zwar Asm im Titel aber in den Beträgen finde ich ulkigerweise bloss Basic-Files.
:
Bearbeitet durch User
Was mir jetzt auf die schnelle einfällt wäre folgendes:
1 | ror temp ; Inhalt egal |
2 | subi temp, 0x80 |
Schneller wird es wahrscheinlich nicht gehen.
Bernhard S. schrieb: > 2 Bits empfangen, danach ein Bit senden und das ganze 64 Mal. Bei 1-Wire??? Dann verstehst du unter einem Bit nicht das, was ich darunter verstehe.
Ich zweifle auch sehr stark am Ansatz. Trotzdem ... Carry ist ein Bit im status register invert carry => SREG = SREG XOR 0x01
> Was mir jetzt auf die schnelle einfällt wäre folgendes: > ror temp ; Inhalt egal > subi temp, 0x80 Dankeschöööön !!!! Es funktioniert, ich bin maximal begeistert ^^ >Ansonsten zeig mal deinen Code. Den Asm. In dem Links steht zwar Asm >im Titel aber in den Beträgen finde ich ulkigerweise bloss Basic-Files. Im oberen, findest Du z.B. meinen 16MHz-Assembler-Code, für die anderen Basic-Files fühle ich mich nicht verantwortlich. >> ich "fummle" es gerade von einem >> 16MHz auf einen 8MHz Takt um > Warum? Stromspargründe, seine Versorgungsspannung soll über den Datenbus zur Verfügung gestellt werden. >Bei 1-Wire??? Dann verstehst du unter einem Bit nicht das, was ich >darunter verstehe. Ich gehe davon aus, dass Du Dich etwas tiefgründiger mit OW beschäftigt hast?
:
Bearbeitet durch User
Bernhard S. schrieb: > Ich gehe davon aus, dass Du Dich etwas tiefgründiger mit OW beschäftigt > hast? Ja.
>> Ich gehe davon aus, dass Du Dich etwas tiefgründiger mit OW beschäftigt >> hast? >Ja. Wie würdest Du ROM-SEARCH im SLAVE (ATmega + Assembler) realisieren?
:
Bearbeitet durch User
Wie könnte man so schnell wie möglich feststellen, ob BIT6 und BIT7 in einem Register (R16) gleich sind? Variante: cpi temp,0b00000000 breq OK cpi temp,0b11000000 breq OK
Was c-hater oben schon angesprochen hat: einen völlig anderen Ansatz wählen. Es gibt ja nicht viele Möglichkeiten, was im zeitkritischen Teil der ISR zu tun wäre. Nämlich (1) den Pin auf out oder auf in setzen und sich (2) zum Sample-Punkt den Zustand merken. Die einzige Unbekannte darin ist in (1), und das kann man vorbereiten. Ob im nächsten 1-Wire Zyklus der Zustand nur gelesen werden soll, der Zyklus komplett ignorieren werden soll oder eine 1 geschrieben werden soll ist der exakt gleiche Ablauf auf dem Bus und muss sich folglich im kritischen Teil der ISR nicht unterscheiden. Wenn also vor dem Aufruf der ISR bereits in einem Register drinsteht, was darin sofort ins DDR geschrieben werden muss, dann hat man anschliessend in der Delay-Phase genug Zeit, den nächsten Zustand dieses Registers vorzubereiten. Sich den Zustand des Pins auch dann zu merken, wenn man ihn grad nicht braucht, stört dabei auch nicht.
:
Bearbeitet durch User
Weitere erhebliche Zeitersparnis: Da ausser dem Pin-Interrupt sonst keiner verwendet wird kann die ISR an der Stelle des Vektors anfangen. Ein dortiger Sprung ist dann unnötig.
Bernhard S. schrieb: > Wie könnte man so schnell wie möglich feststellen, ob BIT6 und > BIT7 in > einem Register (R16) gleich sind?
1 | lsl temp |
2 | brvc OK |
> lsl temp > brvc OK Es funktioniert... ich bin maximal hochgradig begeistert !!! Danke >Weitere erhebliche Zeitersparnis: Da ausser dem Pin-Interrupt sonst >keiner verwendet wird Gute Idee ! Es wird z.B. noch ein TIMER-INTERRUPT genutzt für eine interne UHR für einen DCF-Empfänger (SAMPLING-Verfahren), ein ext. Interrupt für Impulse eines Regenmessers auswerten usw. >Was c-hater oben schon angesprochen hat: einen völlig anderen Ansatz >wählen. Es gibt ja nicht viele Möglichkeiten, was im zeitkritischen Teil >der ISR zu tun wäre.... Danke für die Tipps. So einfach ist das alles nicht, zumal der MASTER sehr schnell hintereinander die Bits abrufen kann. Ich muss alles in die ISR reinpacken, arbeite schon mit verschachtelten Interrupts, nebenbei sollen noch TWI-Sensoren HYT939 bzw. HH10D mit Frequenzmessung realisiert werden, oder andere Aufgaben, die mehrere 100ms Zeit in Anpruch nehmen. Ziel ist es, einen SLAVE zu konzipieren incl. SLEEP, der mit wenig Strom auskommt, momentan bin ich bei 8MHz, von einer 1MHz Variante musste ich mich schnell trennen, da ein 0-SLOT nur unsauber generiert werden kann. Allein die Einsprung-Takte in die ISR dauern für diese Anwendung bei 1MHz zu lange. Wenn die 8-MHz Version optimiert ist versuche ich mich an die 4-MHz Variante heranzutasten. Momentan nutze ich dieses TOOL: Beitrag "TWI I2C USART RS232 - 1WIRE INTERFACE bridge device ATmega8 Assembler" Daher auch dieser Beitrag: Beitrag "Innenwiderstand Messung Goldcap Supercap 1F 5V"
:
Bearbeitet durch User
Bernhard S. schrieb: > So einfach ist das alles nicht, zumal der MASTER sehr schnell > hintereinander die Bits abrufen kann. Was ich beschrieb sorgt vor allem dafür, den zeitkritischen Teil der ISR zu entlasten. Im verlinkten Code hat an genau dieser Stelle die zeitraubende Abfrage einer Statemachine drin. Die kann dort weg. Ebenso wird die temporäre Aktivierung des Ausgangs am Anfang der ISR überflüssig, weil mein OUT DDRx,Ry das an genau dieser Stelle schon fertig erledigt, und nicht vor vorläufig. Und sogar noch einen Takt schneller ist als dein SBI DDRx,y. Mindestens dieser eine Befehl passt bestimmt noch in die Vektorleiste rein, da nur der nächste Interrupt dran glauben muss. Der Trick besteht darin, die Entscheidungen und Bitzustände nicht in der kritischen Phase durchzuführen, sondern davor. Also effektiv nach/während dem vorherigen Bit, dort wo im bisherigen Code Delays sitzen. Das kostet nicht mehr als bisher, sondern weniger, zumal ein Bit in einem Register zu ändern (dem für den OUT Befehl) billiger ist als eines im DDR. Aber was du sonst grad geschrieben hast, deutet leider an, dass dieser gezeigte in diesem Zusammenhang Code nur eine Nebelkerze ist und mit der Sache nichts mehr zu tun hat.
:
Bearbeitet durch User
Bernhard S. schrieb: > Allein die Einsprung-Takte in die ISR dauern für diese Anwendung bei > 1MHz zu lange. Ja. Ein 1-Wire Slave ist ohne etwas Hardware-Unterstützung eine arg knappe Angelegenheit. Wobei man wohl auch mit einem Timer tricksen könnte, wenn einer nebst Ausgang frei ist (*). Den würde man für 0-Bits vorher so dressieren, dass er bei einlaufender Flanke das 1-Wire Signal runterzieht (externer Transistor nötig). Dann ist die Reaktionszeit der ISR deutlich entspannter. *: Möglicherweise ginge auch mit I2C etwas (Idee dahinter: Start Condition als 1-Wire Interrupt, mit Ausnutzung vom Clock Stretching), oder vielleicht SPI. Halt alles was eine passende Hardware-Reaktion auslöst.
:
Bearbeitet durch User
> Wenn die 8-MHz Version optimiert ist versuche ich mich an die 4-MHz > Variante heranzutasten. Strom sparen durch Taktreduktion funktioniert nicht grundsätzlich. So ein AVR hat nämlich einen gewissen "Grundverbrauch", der immer ansteht, wenn er nicht schläft. Mit weniger Takt ist er aber länger wach. Also lieber mit 8MHz zum nächsten SLEEP sprinten, als mit 1MHz dahin trödeln. ATmega8 5V: 16MHz-> 20mA. -> 0,800mA/MHz -> 32% 8MHz -> 11mA -> 1,375mA/MHz -> 55% 1MHz -> 2,5mA -> 2,500mA/MHz -> 100% Von deinen Zeitproblemen mal ganz abgesehen.
:
Bearbeitet durch User
Apropos Strom: Der ATmega88PA braucht bei 16MHz nur ca. ein Drittel.
:
Bearbeitet durch User
Carl Drexler schrieb:
> 16MHz-> 20mA. -> 0,800mA/MHz -> 32%
?
Warum muß es unbedingt 1-wire kompatibel sein? Die Gegenseite programmierst Du doch auch. Es gibt außerdem deutlich bessere Busse für Busspeisung, z.B.: https://de.wikipedia.org/wiki/M-Bus_%28Feldbus%29
Carl D. schrieb: > Strom sparen durch Taktreduktion funktioniert nicht grundsätzlich. Doch, natürlich. Der Zusammenhang ist linear und man kann ihn sich in jedem AVR-Datenblatt als Diagramm ansehen. Und man erkennt anhand des Diagramms sofort, dass die Stromaufnahme bei 0 Hz sehr, sehr nahe bei 0 liegen muss. > So > ein AVR hat nämlich einen gewissen "Grundverbrauch" Ja, natürlich, durch die unvermeidlichen Leckströme der CMOS-Technologie. Aber: er liegt im µA-Bereich. > der immer ansteht, > wenn er nicht schläft. Schlafen ("PowerOff") bedeutet im Wesentlichen einfach nur: Takt=0. Und genau deswegen nimmt er dann halt auch nur die o.g. µA auf. Allerdings gibt es dabei ein Problem: Wenn der Takt durch den AVR selber erzeugt wird und er dabei als Quarz-Oszillator (mit extern angeschlossenem Quarz) arbeitet, dann wird natürlich auch der Oszillator beim Sleep angehalten. Das ist kein Problem. Ein Problem ist aber, dass durch die hohe Güte bedingt, es wirklich lange Zeit dauert, bis der Oszillator nach dem Restart wieder hinreichend stabil schwingt zum Betrieb der MCU. Und in dieser ganzen Zeit wird zwar schon kräftig Energie verbraucht, der Controller kann aber noch nix sinnvolles tun. Und weil das so ist, ist dein Ansatz zumindest für den Fall des Betriebs mit einem Quarz definitiv und leicht nachweisbar eine Milchmädchenrechnung. Deutlich komplizierter ist es für den Betrieb mit einem internen RC-Oszillator, da ist das nicht so leicht zu entscheiden. Dafür gibt es keine einfache Entscheidungshilfe, in aller Regel sind zum Erreichen des Optimums erst lange Messreihen statistisch hinreichend aussagefähig. Oder anders ausgedrückt: es ist dann fast völlig huppse, ob du kurz schnell rechnest oder länger langsamer. Das einzige, was garantiert positiv wirkt, ist die Reduktion der insgesamt benötigten Rechenleistung pro Zeiteinheit. Sprich: effizienter Code.
Wenn du meinst, dann muß es ja stimmen. Ist ja quasi ein Fakt. Hatten wir das nicht vor kurzen schon mal: die einzige Wahrheit.
@alle Ein ganz großes Dankeschön für die sehr hilfreichen Anregungen und Tipps. Die 4MHz 1-WIRE-Version: Beitrag "1-Wire OW-wire slave device <=4MHz low current AVR assembler ATmega8" Bernhard
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.