Hi ich wollte mal fragen, weis nicht ob ich das jetzt richtig ausdrücke bin nicht so ein Profi aber mal probieren: Ich möchte den oben erwähnten ds1620 Temperatursensor ala Memory Mapped I/O direkt ansprechen. PORTB ist im speicher auf der Adresse 0x38 gemapped somit könnte ich sowas wie das realisieren aber das ist mir zu unbequem: PORTB = 0xaa ...sag ich jetzt mal würde mir die register von PORTB auf 10101010 setzen. Jedoch möchte ich die einzelnen Pins auf diese Weise ansprechen sowas wie: #define DQ PORTB0 ja ich weis das is jez falsch da PORTB0 einfach als 0 definiert ist. Aber im Endeffekt ist glaub ich klar was ich will: SETBIT(PORTB,DQ) das is die normale Methode und ich hätte das gerne so: RST = 1; CLK = 0; DQ = 1; // so in etwa hab ich mir das vorgestellt! keine Ahnung ich nenn das jez mal "Bitwise memory mapped" hat jemand Erfahrung damit ob das möglich ist?
jo fein, weis keiner wie das geht oder hab ich mich schlecht ausgedrückt :(
Ich blick irgndwie garnicht durch was du machen willst, und wo's scheitert.
okok, kein Problem. Was ich will ist dass ich nicht immer auf den ganzen Port schreiben muss sondern direkt auf eine Leitung was schicken. sicher es gibt sbi/cbi womit ich ein bit setzen/löschen kann. Nur ich möchte eben zb. den Wert den ich in einem Register/variable usw. stehen hab auf einen Pin rausschicken ala DQ = <variablesoundso>(wobei da natürlich nur 1 oder 0 geschickt werden kann) und nicht wenn jetzt DQ zb auf PORTB Pin2 ist das: PORTB = 0x04 oder PORTB = b100 (wenn das so geht, aber egal) ich will quasi 1 Bit im Speicher in eine Variable "mappen" und nicht die ganze Row der Adresse 0x38 (8 Bit breit) Ich hab ein Image hinzugefügt in dem das hoffentlich anschaulich dargestellt ist was ich will
Wie wärs, wenn du einfach die eingebaute SPI Funktion nimmst? (Ich gehe jetzt mal von AVRs aus, da haben das die nicht zu alten chips)
Also ich weis nicht was daran so schwer zu verstehen ist dass ich das nicht will sondern direkt die Werte rausschreiben kann. mit spi kann ich auch nur arbeiten indem ich vorher das jeweilige zu sendende Bit mit ner if abfrage überprüf und dann dementsprechend sbi oder cbi verwend. Das is genau nicht das was ich will, herrgott wie oft soll ich das noch sagen ich will stattdessen wenn ich nen 8 bit wert hab das so rausschicken for(int i = 0; i < 8 ; i++) { DQ = data & 0x01; // wenn i mi jez ned geirrt hab data >> 1; } is doch viel einfacher als for (int i = 0; i < 8 ; i++) { if (data & (1 << i)) sbi(PORTB,PORTB2) else cbi(PORTB,PORTB2) } Das war von Anfang an mein Anliegen dass ich das nicht so machen will ...verstehst mich jetzt?
OOOH Ein codebeispiel applaus ! Jetzt weiß ich tatsächlich was du meinst. Was soll der C Compiler denn intern damit machen, selbst wenn du dieses einzelne Bit herausdefinieren könntest? zaubern? Nee, der MUSS das zwangsläufig in SBI/CBI umsetzen, weil wie soll das anders gehen? Nimm den Onboard SPI Controller, mensch! Der macht dir das alles alleine und viel schneller als deine Schleife. PS: Ich benutz lieber den Onboard SPI Master. damit sind fCLK/2 als SPI Frequenz Möglich. Das schaffst du mit deiner C-Schleife niemals lach PPS: Ist der aufgefallen dass du das Low-Bit zuerst schickst? Nur so. ist recht ungewöhnlich, weiß aber jetzt nicht was dein DS1620 da so verlangt.. Wenn ich das unbedingt so machen würde, und ich kein SPI benutzen könnte, dann würde ich das so machen:
1 | for(int i = 0; i < 8 ; i++) |
2 | {
|
3 | if(data & 0x01) |
4 | PORTB |= (1<<PB2); //SBI und CBI sind veraltet, so richtiger |
5 | else
|
6 | PORTB &= ~(1<<PB2); |
7 | |
8 | /*evtl noch Clock Handling o.ä.*/
|
9 | |
10 | data >> 1; |
11 | }
|
Achja ein SPI Beispiel
1 | /*Init vom SPI:*/
|
2 | SPCR = (1<<SPE)|(1<<MSTR) /*Master Betrieb, SPI Enable*/ |
3 | /*Prescaler fCLK/4*/
|
4 | |
5 | /*Senden von Daten:*/
|
6 | SPDR = b; /*Byte der SPI Einheit übergeben*/ |
7 | while(!(SPSR & (1<<SPIF))) nop(); /*Warten, dass fertig |
8 | übertragen wird*/
|
Nix SBI/CBI. Datenblatt lässt grüßen..
Weiss nicht ob das wirklich schöner ist, aber wenn's denn sein soll: struct Port { unsigned b0 : 1, b1 : 1, b2 : 1, b3 : 1, b4 : 1, b5 : 1, b6 : 1, b7 : 1; }; void f(unsigned char data) { volatile struct Port *PortB = (volatile struct Port *)&PORTB; unsigned char i; for (i = 0; i < 8; ++i) { PortB->b3 = data; data >>= 1; } }
müsste es nicht PortB->b3 = data & 0x01; sein? Aber ich bin davon überzeugt, dass der Compiler da auch was mit SBI/CBI machen wird. Oder vielleicht sogar komplizierter mit ein paar Logischen Operationen.
PS: Die klassische Methode erzeugt deutlich kürzeren Code (11 statt 16 Befehle).
"müsste es nicht PortB->b3 = data & 0x01; sein?" Läuft exakt auf's gleiche raus. Die Maskierung muss der Compiler sowieso machen, er darf ja nicht über die benachbarten Bits drüberbrezeln. "Aber ich bin davon überzeugt, dass der Compiler da auch was mit SBI/CBI machen wird" Deine Überzeugung in Ehren, aber schau halt man den erzeugten Code an. Bei Konstanten auf der rechten Seite von Bitfeld-Zuweisungen gibt es schon Optimierungen. Ansonsten darfst du schon froh sein, dass er keine 16bit-Operation draus gemacht hat.
Für Ästheten hätte ich noch folgendes anzubieten - das kommt immerhin komplett ohne if/else-Abfrage aus und ist mit 15 Befehlen einen Hauch kürzer: for (i = 0; i < 8; ++i) { PINB = (PORTB ^ ~((data & 1)-1)) & 1<<PB3; data >>= 1; } Funktioniert aber nur mit neueren Devices, ab Tiny2313 oder Mega88.
SPI ist doch langweilig. Ein echter Mann macht das mit Assembler: // PB1: CLK // PB2: DQ asm volatile ( "lds r24, data \n\t" "ldi r25, 8 \n\t" "loop:\n\t" "cbi 0x18, 1\n\t" "ror r24 \n\t" "brcs a \n\t" "cbi 0x18, 2\n\t" "rjmp b \n\t" "a:\n\t" "sbi 0x18, 2 \n\t" "b: \n\t" "sbi 0x18, 1 \n\t" "dec r25 \n\t" "brne loop \n\t" ); viele grüße ralph
so um wieder auf das leidige Thema ds1620 zurückzukommen ..was eh scho oft hier besprochen wurde ...konnte mir bei meinem Problem auch eben ned helfen deswegen frag ich das jez hier auch noch. Hab mir mal so die letzten Tage den Code zusammengeschraubt o_O ...einer wird hier sicher wieder aufschreien wieso ned hardware spi aber egal ..war zu faul mich mit spi weiter zu beschäftigen... so wie ichs gelöst hab so in der art haben wir das mal in der Schule gemacht nur jez krieg ichs auf dem atmega8 ned auf die Reihe ....hab mal den Code angehängt ..so vergleich mit anderen Beispielen is mir nix aufgefallen was noch falsch sein kann ...glaub alles was ich gesehen hab korrigiert ..bringt nix. Hab Testweise mal das Config Register ausgelesen und so wie schon andere das Prob hatten ...ich bekomm nur 1en zurück. Bitte schauts euch den Code an. Kanns ja ned sein... i2csw lösung bissal modifiziert und in 20min ghabt und Display ansteuerbar aber das ich das ned auf die Reihe krieg geht ma am sack.
schreib mal bitte mit punkt und komma, und schreibt nicht so einen stuss in deinen beitrag. danke vorab benutzt hardware spi (ja !). das ist viel einfacher. aber wenn du keine lust hast.... Was machst du da mit der Clock? Du ziehst die Clock vor jedem Bit auf 0 und danach auf 1. Das ist doch Unfug. Du musst erst das Bit anlegen, und dann Clock->0->1 machen. weiter hab ich jetzt keine zeit mehr, aber änder das mal.
@Itachi & @Simon data >> 1 muss data >>= 1 heißen! Es geht auch anders, indem Du die Maske auch als Zähler verwendest: unsigned char maske=0x80; do if(data&maske)PORTB |= (1<<PB2); else PORTB &=~(1<<PB2); while(maske/=2); oder andere Schiebe-Richtung: unsigned char maske=1; do if(data&maske)PORTB |= (1<<PB2); else PORTB &=~(1<<PB2); while(maske*=2); Ich weiß schon, wie Du es meinst: Zuweisung ist einfacher als Löschen oder Setzen. Da Du aber nicht auf ein einzelnes Bit schreiben kannst, ist es mit cbi/sbi einfacher, dafür gibt es diese Befehle ja. zip wäre einfacher zu lesen als rar.
@Profi: sry wegen Rar aber ich bin davon ausgegangen, dass jemand der Mikrocontroller programmiert sich auch so mit Pcs etwas auskennt und nicht auf die (nicht bös gemeint) dumme Idee kommt Winzip Winrar bzw. Ace vorzuziehen. @Simon Tut leid, habs zu dem Zeitpunkt etwas eilig gehabt und hab auf solche etwaige Details nicht geachtet. Das hat sich wohl damit erübrigt. Was du meinst mit Clock 0->1 hab ich zumindest so aus dem Datenblatt gelesen. Kann auch sein dass ich mich geirrt habe. Jedoch kann ich den von dir beschriebenen Fehler nicht nachvollziehen. Im Datenblatt kommt das aus dem Bild eindeutig so raus: CLK geht auf Low -> Daten werden auf die Leitung gelegt -> CLK geht auf High. Ich wüsste nicht was daran falsch ist. Wenn ich mich irre klär mich bitte auf, was ich aus dem Datenblatt falsch ablese, danke. @Profi: So wie du es machst gehts auch, nur wenn ich beim Debuggen nicht blind war, müsste er auf meine Methode auch richtig die einzelnen Bits schieben. thx
bitte schlagts mich ganz dolle. Dummheit tut weh. Nachdem ich beim Lesezyklus bit_is_set(PORTB,DQ) in bit_is_set(PINB,DQ) geändert hatte hats funktioniert.
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.