www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmega8 - ds1620 direkt ansprechen


Autor: Itachi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Itachi (Gast)
Datum:

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

:(

Autor: Simon K. (simon) Benutzerseite
Datum:

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

Autor: itachi (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: itachi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
for(int i = 0; i < 8 ; i++)
{
    if(data & 0x01)
        PORTB |= (1<<PB2);   //SBI und CBI sind veraltet, so richtiger
    else
        PORTB &= ~(1<<PB2);

    /*evtl noch Clock Handling o.ä.*/

    data >> 1;
}

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achja ein SPI Beispiel
       /*Init vom SPI:*/
       SPCR = (1<<SPE)|(1<<MSTR) /*Master Betrieb, SPI Enable*/
                                 /*Prescaler fCLK/4*/

       /*Senden von Daten:*/
       SPDR = b;                 /*Byte der SPI Einheit übergeben*/
       while(!(SPSR & (1<<SPIF))) nop(); /*Warten, dass fertig
übertragen wird*/

Nix SBI/CBI. Datenblatt lässt grüßen..

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
    }
}

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: A.K. (Gast)
Datum:

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

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder was ganz neues: Hardware-SPI zzz

Autor: rkhb (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dabei wäre hardware-spi doch um einiges schneller

Autor: Itachi (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Profi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: itachi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: itachi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.