Hallo zusammen, Ich muss die CPU-platine einer uralten SPS ersetzen. Die I/O-Platinen werden über einen Bus angeschlossen. Als CPU nutze ich einen Arduino-Mega, der in Assembler programmiert wird. Den Logikteil des Programms habe ich fertig. Aber bei der I/O Anbindung habe ich einen Knoten im Hirn. Ich lege eine Adresse auf den Bus und erhalte den Zustand eines Eingangs auf einer Portleitung. Dann wird der Bus incrementiert und das nächste Bit abgefragt. Ausgabe dito. Wie kriege ich die einzelnen Bits jetzt in der richtigen Reihenfolge byteweise abgespeichert? Kann mir da jemand einen Tip geben? Wie gesagt, soll in Assembler sein. Bin für jeden Rat dankbar. Werner
>Den Logikteil des Programms habe ich fertig.
Bist Du Dir da sicher?
Im Übrigen: Die ATMegas haben's nicht so mit Speicher (RAM). Da ist sehr
schnell Schluss.
Werner, warum nimmst Du keine Hochsprache ? Ohne Schaltplan wird man dir, bzgl. der Hardware, nicht 100% antworten können! Und ohne Programm, Ablaufsteuerung etc. entsprechend auch nichts korrigieren.
Hm, ist den das ganz in irgendeiner Form sicherheitsrelavant? Wenn ja, würde ich da ganz schnell die Finger davon lassen... mfg Gast
Bin mir nicht ganz sicher, ob ich dich richtig verstanden habe, d. h. du bekommst an einem Port-Pin, z. B PA0 ein Bit geliefert, z. B. PA0=1, dann kommt PA0=0, dann PA0=1 usw. ...und du möchtest die einzelnen Bits in einem Byte zusammenfassen(?) Eigentlich ganz trivial, vor allem in Asm: Portzustand in ein Register einlesen, überprüfen ob das DatenBit 0 oder 1 ist, dieses ins Carry reinschreiben, dann das Carry ins Byteregister reinschieben. Dann das ganze noch sieben mal wiederholen, so dass alle Bits nacheinander ins Byteregister reingeschoben wurden. Beispiel:
1 | ;******************************************************************** |
2 | ;******* 8 Bits zu 1 Byte ******************************************* |
3 | ;******************************************************************** |
4 | ;***** Es wird angenommen, dass die Daten am Port A ankommen, ******* |
5 | ;***** am Pin PA0; der Zustand des Ports A wird nach DatenBit ******* |
6 | ;***** eingelesen; nur niedrigwerteste Bit des Port A ist hier ****** |
7 | ;***** von Bedeutung => PA0 kann nur 0 oder 1 annehmen, Pin 1 ******* |
8 | ;***** bis Pin 7 werden nicht beachtet; der Zustand von PA0 ********* |
9 | ;***** wird von links nach rechts ins DatenByte über das ************ |
10 | ;***** Carry Flag eingeschoben ************************************** |
11 | ;******************************************************************** |
12 | 8bit_1byte: |
13 | clr DatenByte |
14 | ldi tmp1,0x08 ;Zähler für 8 Bits |
15 | loop1:lds DatenBit,PortA_In ;Port A wird eingelesen |
16 | sbrc DatenBit,0 ;Prüfen ob PA0 1 oder 0 => Wenn PA0=0 nächstes Kommando überspringen |
17 | rjmp loop3 ;PA0=1 => daher zu sprinegn |
18 | clc ;Datenbit=0, dieses Bit ins Carry schreiben => Carry Flag löschen |
19 | loop2:ror DatenByte ;Carry ins Datenbyte reinschreiben (verschieben nach rechts) |
20 | dec tmp1 ;Zähler um 1 verkleinern |
21 | brne loop1 ;Nächstes Bit reinholen |
22 | ret ;...und Zurück zum Hauptprogramm |
23 | loop3:sec ;Datenbit=1, dieses Bit ins Carry schreiben => Carry Flag setzen |
24 | rjmp loop2 ; |
Code ist für XMEGA, muss also füe MEGA angepasst werden, d. h. Einlesen des Port A. BTW: Was für brillante Antworten hast du bis jetzt bekommen...
Werner J. schrieb: > Wie kriege ich die einzelnen Bits jetzt in der richtigen Reihenfolge > byteweise abgespeichert? Erstmal musst du die Bits zu einem Byte zusammen bauen. Zu Zeiten vom 6502 hat man dafür gesorgt, dass im Carry der Eingangszustand war und dann mit Rotate Right oder Left dieses Bit in den Akku rein geschoben. Falls dein Arduino das nicht kann, helfen natürlich Bitmanipulationen, um direkt das Bit durch maskieren zu löschen oder durch or zu setzen.
Ja, das macht immer noch so, sowohl beim 6502 als auch beim AVR :) Hochsprache... dass ich nicht lache ;) Ich müsste eigentlich mal wieder den Brotkasten rausholen :P
Norbert hat ja schon eine Lösung präsentiert. Wenn das Input-Bit an Bit 0 oder 7 steht geht auch noch: Per ROL oder ROR das eingelesene Bit erst mal ins Carry schieben. Gleich danach nochmal mit ROL oder ROR das Bit dann in das Datenregister schieben.
Hi
>Wenn das Input-Bit an Bit 0 oder 7 steht geht auch noch:
Mit bld/bst kann man beliebige Bits von beliebigen Registern hin und her
schieben.
MfG Spess
Sebastian S. schrieb: > Die ATMegas haben's nicht so mit Speicher (RAM). Da ist sehr > schnell Schluss. mega2560 -> 8k RAM mega1284 -> 16k RAM Nur mal so... Verallgemeinerte Aussagen sind allgemein scheisse.
Arudino DUE 512KB Flash....96KB SRAM. SRAM mit Arduino-IDE durchgehend nutzbar ohne eine 64KB-Grenze für den Nutzer als Hürde.
Werner J. schrieb: > Ich lege eine Adresse auf den Bus und erhalte den Zustand eines Eingangs > auf einer Portleitung. Dann wird der Bus incrementiert und das nächste > Bit abgefragt. Ausgabe dito. Du hast wirklich einen Bus mit z.B. 16 Adreßleitungen und nur einer Datenleitung? Wer kommt denn auf solche abstrusen Ideen? Zeig man den Schaltpan der IO-Anbindung. Dann müssen wir nicht mehr sinnlos rumrätseln.
Wozu braucht man 8k, 16k oder 96k RAM wenn man eine handvoll Bits einlesen will? Wo bleibt der Vorschlag doch gleich einen RPi2 zu nehmen?
Vielen Dank an Alle die sinnvolle Antworten gepostet haben, allen voran Norbert. Ist ja wirklich trivial (wie gesagt: Knoten im Hirn). Zu: Speicher zu klein Ich muss ja nur die 128 Ein- und 96 Ausgänge und ca. 100 Merkerbits als Prozessabbild im RAM halten. Das schafft selbst ein Arduino One. Den Mega brauche ich nur wegen des größeren Flash (für den Logikteil brauche ich ca. 10.000 Zeilen Assembler-Code). @Peter: Ja, ist ein 13Bit-Bus mit einer Datenleitung. Es handelt sich um eine Siemenssteuerung von 1980, steuert eine NC-Drehmaschine. @Karl: Keine Hochsprache wegen der Geschwindigkeit. Damit schaffe ich den Durchlauf des Logikteils in < 10ms.
Werner J. schrieb: > Keine Hochsprache wegen der Geschwindigkeit. Damit schaffe ich > den Durchlauf des Logikteils in < 10ms. Du hast falsche Vorstellungen von Hochsprachen, 10ms sind eine riesige Zeit. Norbert T. schrieb: > 8bit_1byte: > clr DatenByte > ldi tmp1,0x08 ;Zähler für 8 Bits > loop1:lds DatenBit,PortA_In ;Port A wird eingelesen > sbrc DatenBit,0 ;Prüfen ob PA0 1 oder 0 => Wenn PA0=0 > nächstes Kommando überspringen > rjmp loop3 ;PA0=1 => daher zu sprinegn > clc ;Datenbit=0, dieses Bit ins Carry schreiben => > Carry Flag löschen > loop2:ror DatenByte ;Carry ins Datenbyte reinschreiben > (verschieben nach rechts) > dec tmp1 ;Zähler um 1 verkleinern > brne loop1 ;Nächstes Bit reinholen > ret ;...und Zurück zum Hauptprogramm > loop3:sec ;Datenbit=1, dieses Bit ins Carry schreiben => > Carry Flag setzen > rjmp loop2 ; Schon das kann ein C-Compiler aber besser:
1 | uint8_t serin( void ) |
2 | {
|
3 | uint8_t val = 0; |
4 | for( uint8_t i = 8; i; i--){ |
5 | val >>= 1; |
6 | if( PIN_A0 ) |
7 | val |= 0x80; |
8 | }
|
9 | return val; |
10 | }
|
ergibt:
1 | 102: 98 e0 ldi r25, 0x08 ; 8 |
2 | 104: 80 e0 ldi r24, 0x00 ; 0 |
3 | 106: 86 95 lsr r24 |
4 | 108: 00 99 sbic 0x00, 0 ; 0 |
5 | 10a: 80 68 ori r24, 0x80 ; 128 |
6 | 10c: 91 50 subi r25, 0x01 ; 1 |
7 | 10e: d9 f7 brne .-10 ; 0x106 <serin+0x4> |
8 | 110: 08 95 ret |
Werner J. schrieb: > Ist ja wirklich trivial. Ja, ist es. > Zu: Speicher zu klein > Ich muss ja nur die 128 Ein- und 96 Ausgänge und ca. 100 Merkerbits als > Prozessabbild im RAM halten. Das schafft selbst ein Arduino One. Den > Mega brauche ich nur wegen des größeren Flash (für den Logikteil brauche > ich ca. 10.000 Zeilen Assembler-Code). Da könnte man sehr wahrscheinlich noch ganz erheblich "aufräumen". > @Karl: Keine Hochsprache wegen der Geschwindigkeit. Damit schaffe ich > den Durchlauf des Logikteils in < 10ms. Hmm. 10.000 Zeilen in 10ms bedeutet, dass du entweder den AVR nur mit ca. 1..2MHz laufen läßt oder EXTREMST ineffizienten Code schreibst. Im ersteren Fall fragt man sich dann, warum du diesen geringen Takt gewählt hast und im zweiteren Fall, warum du Assembler gewählt hast, beherrschen tust du die Sprache dann ja offensichtlich nicht, das kann nämlich jeder gängige AVR-C-Compiler offensichtlich weitaus besser als du... > @Peter: Ja, ist ein 13Bit-Bus mit einer Datenleitung. Diese Information hätte ganz selbstverständlich in's OP gehört, idealerweise sogar noch mehr Details über den Bus. Hier steckt nämlich sehr wahrscheinlich noch erhebliches Optimierungspotential bezüglich der Busanbindung drin. Insbesondere auch die Möglichkeit, die (De-)Serialisierung, an der sich dein Hirn verknotet hat, ganz oder teilweise in Hardware zu realisieren und damit die Dauer des IO-Zyklus auf einen Bruchteil der Zeit zu reduzieren, die mit Software-(De-)Serialisierung nötig ist.
> .. Ja, ist ein 13Bit-Bus mit einer Datenleitung. Für jedes einzelne Bit ein completter Zyklus. Ganz schön seltsam. Ob das so richtig übernommen wurde? Frequenz? >Hier steckt nämlich sehr wahrscheinlich noch erhebliches >Optimierungspotential bloss, dass da Optimierung keinen Sinn (mehr) macht. Die Steuerung hat ja so (wohl mit sehr wenigen bps) schon Jahre lang gelaufen.
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.