Forum: Mikrocontroller und Digitale Elektronik Atmega8 - ds1620 direkt ansprechen


von Itachi (Gast)


Lesenswert?

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?

von Itachi (Gast)


Lesenswert?

jo fein, weis keiner wie das geht oder hab ich mich schlecht ausgedrückt

:(

von Simon K. (simon) Benutzerseite


Lesenswert?

Ich blick irgndwie garnicht durch was du machen willst, und wo's
scheitert.

von itachi (Gast)


Angehängte Dateien:

Lesenswert?

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

von Simon K. (simon) Benutzerseite


Lesenswert?

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)

von itachi (Gast)


Lesenswert?

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?

von Simon K. (simon) Benutzerseite


Lesenswert?

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
}

von Simon K. (simon) Benutzerseite


Lesenswert?

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..

von A.K. (Gast)


Lesenswert?

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;
    }
}

von Simon K. (simon) Benutzerseite


Lesenswert?

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.

von A.K. (Gast)


Lesenswert?

PS: Die klassische Methode erzeugt deutlich kürzeren Code (11 statt 16
Befehle).

von A.K. (Gast)


Lesenswert?

"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.

von A.K. (Gast)


Lesenswert?

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.

von Simon K. (simon) Benutzerseite


Lesenswert?

Oder was ganz neues: Hardware-SPI zzz

von rkhb (Gast)


Lesenswert?

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

von Simon K. (simon) Benutzerseite


Lesenswert?

dabei wäre hardware-spi doch um einiges schneller

von Itachi (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Simon K. (simon) Benutzerseite


Lesenswert?

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.

von Profi (Gast)


Lesenswert?

@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.

von itachi (Gast)


Lesenswert?

@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

von itachi (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.