Forum: Mikrocontroller und Digitale Elektronik SPI ATmega8L Beschleunigungssenor


von Christoph (Gast)


Lesenswert?

Hallo zuammen,

da mir letzten ja so schnell geholfen wurde und ich völliger Anfänger
bin,habe ich noch eine Frage.

Ich benutze den Atmega8 und Code Vision zum Programmieren. An den
ATmega 8 habe ich über den SPI-Bus ein Beschleunigungs senor
angeschlossen. den Atmega8 habe ich über Code Wizard eingestellt.
ich möchte ich einzelen Bits des Beschleunigungssenors über den SPI-Bus
 setzen und einezelne Adressen abfragen.
Wie kann ich das realisieren.?
Schonmal vielen Dank für eure Hilfe.

MfG
Christoph

von Christoph (Gast)


Lesenswert?

kann mir keiner einen tipp geben?

von hans dieter (Gast)


Lesenswert?

indem du in das datenblatt des Beschl. Sensors schausst und dann die
richtigen werte in das Daten-Register des SPI schreibst.

von Christoph (Gast)


Lesenswert?

wie du sicher gelesenhast bin ich ein anfänger. könntest du mir das an
einem beispiel erklären.
ich muss beim Beschleunigungssenor in der Adresse 25h Bit 7 setzen und
Bit 5 und 6 nicht setzen.

von Dirk Doerr (Gast)


Lesenswert?

Wenn Du mal mehr Informationen liefern würdest, könnte man Dir auch
helfen.

Z. B. wäre es seeeehr hilfreich zu wissen welchen Sensor Du
verwendest.

--

   Dirk

von Christoph (Gast)


Angehängte Dateien:

Lesenswert?

ich benutze den Bosch SMB360.

von Rahul (Gast)


Lesenswert?

Im Datenblatt ist im Abschnitt 3.2 das Protokoll beschrieben.
Da der ATMega8 nur ein 8Bit-Controller ist, muß man die 16bit durch
2byte zusammensetzen, was aber auch kein Problem ist, da sich das
Datenpaket aus der Adresse (7bit), Schreib-lese-bit (1) und den 8Bit
Nutz-Daten zusammensetzt.
Im Abschnitt 4.2 sind dann sämtliche Register/Speicherpltze des Sensors
beschrieben.

Wo ist da das Problem? Auf der Sensor-Seite oder auf der AVR-Seite?

von Christoph (Gast)


Lesenswert?

die sachen habe ich schon gefunden.
das problem ist, dass ich noch nie so richtig programmiert habe. und
ich fetzt nicht weiß, wie ich das jetzt in c schreiben muss.

von Dirk Doerr (Gast)


Lesenswert?

Also auf den ersten Blick hast Du ein kleines Problem. Der Sensor
erwartetet ein 16 Bit SPI. D. h die CS-Leitung muß für 16 Zyklen low
bleiben. D. h. Du darfst nicht die automatische SPI Steuerung des CS
(bzw /SS Pins) verwenden.

D. h. Du mußt den SS Pin als Output konfigurieren und selbst
umschalten.

Um jetzt die den Wert an Adresse 0x25 zu ändern:

- SS auf low
- SPI-Write mit der Adress 0x25 (oberstes Bit muß 0 bleiben um ein
Schreiben zu kennzeichnen
- SPI-Write mit dem gewünschten Wert (Bei Adresse 0x25 kannst Du
sowieso nur das oberste Bit setzen). Also einfach den Wert 0x80
verwenden
- SS auf high

Damit solltest Du Bit 7 geändert haben

--

     Dirk

von Rahul (Gast)


Lesenswert?

@Dirk: Wo ist denn das Problem mit der /CS-Leitung beim AVR?
Wenn man ihn (wie in diesem Fall) als Master betreibt, obliegt es dem
Programmierer, die /CS-Leitung zu bedienen. Man könnte auch jeden
anderen Pin des AVR (Vcc etc ausgenommen) als /CS verwenden.
Die automatische CS-Steuerung tritt erst ein, wenn man den AVR als
Slave betreibt.

von Dirk Doerr (Gast)


Lesenswert?

@Rahul: Hmmm. Ich hatte noch irgenwie im Kopf, daß der AVR die CS
Leitung im Master-Mode kontrolliert, sprich vor dem Transfer auf low
und danach wieder auf high....

Aber ok. Kann mich auch irren.

von Christoph (Gast)


Lesenswert?

@Rahul
jetzt habe ich aber mal ne ganz blöde frage. welchen pin vom BeSe muss
denn mit dem SS verbunden werden?
ich habe da so eine befürchtung

von Christoph (Gast)


Lesenswert?

ich habe am csb Pin vom Beschleunigungssensor 2,4 V anliegen. das ist
doch nicht wirkliuch richtig oder?

von Rahul (Gast)


Lesenswert?

CSB sollte mit einem Pin (z.B. /SS) des Controllers verbunden sein.
Der muß natürlich als Ausgang im Datadirectionregister geschaltet
sein.
MOSI und MISO können übrigens 1:1 verdrahtet werden,also MOSI (AVR) auf
MOSI (BeSe) und MISO (AVR) auf MISO (BeSe).
Wann liegen da 2,4V am Pin? Im offenen Zustand, sprich ohne AVR dran?
Sonst hilft vielleicht noch ein Pull-up-Widerstand.

von Christoph (Gast)


Lesenswert?

schon mal danke.
blöden fehler gemacht. jetzt ist mein csb 0V

von Marian (Gast)


Lesenswert?

@Christoph: Wo hast du dieses Datenblatt her? Ich habe bis jetzt immer
nur die "verkürzte" Variante gefunden.

@Rahul: Wie kommst du darauf das MOSI und MISO direkt verdrahtet
werden? Hast du Bezugsquellen die das belegen?

Gruß

Marian

von Rahul (Gast)


Lesenswert?

Abbildung im Abschnitt 3.2 über MOSI werden Adresse und Daten an den
Sensor geschickt...

Heisst ja auch nicht um sonst MOSI Master Out Slave In bzw MISO Master
In Slave Out.
AVR ist Master und Sensor ist Slave.

Sonst solltest du einen Blick ins AVR-Datenblatt werfen. Da ist das
nämlich drin beschrieben.

von Christoph (Gast)


Lesenswert?

wenn ich jetzt programmieren könnte wäre ich glücklich.
wie heißen denn die befehle für ds schreiben und für das lesen des
SPI-Buses.
was im Datenblattsteht (ATmega8) funktioniert nicht.

das Daten baltt habe ich von bosch-sensortec.

von Dirk Doerr (Gast)


Lesenswert?

Vielleicht hilft Dir ja folgende Seite

http://www.kreatives-chaos.com/index.php?seite=mcp2515_reg

Dort wird ein anderes SPI device (ein CAN-Controller) mit einem AVR
angesteuert. Beispiel-Code in CD.

--
   Dirk

PS: Wie kommst Du in die Lage ohne programmieren zu können so etwas
machen zu müssen?

von Rahul (Gast)


Lesenswert?

@Christoph:
Als erstes mußt du die Schnittstelle initialisieren.
Sobald du Daten verschieben willst, senkst du den Portpin (CBS) auf
L-Pegel ab und schreibst die Daten in das SPDR (SPI-Datenregister).
Jetzt wartest du, dass die Daten gesendet wurden (Irgendson
Interrupt-Flag abfragen). Wenn das der Fall ist, dann kannst du
entweder neue Daten senden oder die CBS-Leitung wieder hochziehen.
Relativ simpel...

von Marian (Gast)


Lesenswert?

@Rahul: Sorry hatte mich bei deinem Thread verlesen ;)

von Christoph (Gast)


Lesenswert?

Hallo,
 hier mal ein mini programm. es soll bits vom BeSE setzen.
Wenn ich das Programm ohne die SPI anweisungen laufen lasse. hat liegt
an meiner csb leitung 0V. was Man ja benötigt um den BeSe zu
beschreiben.
wenn ich diefunktionen aber einbinde (wie es hier auch ist), habe ich
2,5V anliegen, was die Versorgungsspannung dees BeSe
entspricht.#include <mega8.h>
#include <spi.h>        // SPI functions
#include <stdio.h>      // Standard Input/Output functions
#include <delay.h>
#include <stdlib.h>
#include <string.h>

// DS1302 Real Time Clock functions
#asm
   .equ __ds1302_port=0x18 ;PORTB
   .equ __ds1302_io=1
   .equ __ds1302_sclk=0
   .equ __ds1302_rst=7
#endasm
#include <ds1302.h>

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here

}

/*********************************************************************** 
****************************/

#define SPIF 7
#define SS PORTB.2

#define LED_rot PORTC.3           // Output rote LED
#define LED_gelb PORTC.2          // Output gelbe LED
#define LED_gruen PORTC.1         // Output grüne LED
#define BUZZER PORTC.0            // Output Buzzer


#define CSB PORTB.6



/*********************************************************************** 
****************************/

// Declare your global variables here
char hour,min,sec,date,month,year;
char i;
eeprom struct
        {
        char stunde;
        char minute;
        char sekunde;
        }eeprom uhrzeit[15];
eeprom struct
        {
        char tag;
        char monat;
        char jahr;
        }eeprom datum[15];

/*********************************************************************** 
****************************************/

void spi_sende(char data )
{
  // Sendet ein Byte
  SPDR = data;

  // Wartet bis Byte gesendet wurde
  while( !( SPSR & (1<<SPIF) ) );

  return SPDR;
}

void bit_setzen (char adresse, char data)
{
        //CSB low setzen

        SS = 1;
        adresse = 0x19;
        data = (1<<7);

        spi_sende (adresse);
        spi_sende (data);
        delay_ms (2);
        SS = 1;
        LED_gruen = 1;

}

/*********************************************************************** 
****************************************/
void main(void)
{
bit_setzen (0x19, (1<<7));              // Bit setzen BeSe
bit_setzen (0x1A, (1<<6));              // Bit setzen BeSe
bit_setzen (0x1A, (1<<5));              // Bit setzen BeSe
bit_setzen (0x1B, (1<<6));              // Bit setzen BeSe
bit_setzen (0x1B, (1<<5));              // Bit setzen BeSe

// Declare your local variables here

// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=Out Func5=Out Func4=In Func3=Out Func2=Out Func1=In
Func0=In
// State7=T State6=0 State5=0 State4=T State3=0 State2=0 State1=T
State0=T
PORTB=0x00;
DDRB=0x6C;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=Out Func0=Out
// State6=T State5=T State4=T State3=0 State2=0 State1=0 State0=1
PORTC=0x01;
DDRC=0x0F;

// Port D initialization
// Func7=In Func6=Out Func5=In Func4=In Func3=In Func2=In Func1=Out
Func0=In
// State7=T State6=0 State5=T State4=T State3=T State2=T State1=0
State0=T
PORTD=0x00;
DDRD=0x42;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7,259 kHz
TCCR0=0x05;
TCNT0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Low level
// INT1: Off
GICR|=0x40;
MCUCR=0x00;
GIFR=0x40;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 9600
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x2F;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 2*1858,333 kHz
// SPI Clock Phase: Cycle Half
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=0x50;
SPSR=0x01;
SPCR |= (1<<3);
SPCR |= (1<<2);
SREG |= (1<<7);
SPCR |= (1<<7);
// spi_sende (bit_setzen);

// DS1302 Real Time Clock initialization
// Trickle charger: On
// Trickle charge resistor: 8K
// Trickle charge diode(s): 1
rtc_init(1,1,3);
// ds1302_write (0x54,~(1<<7));   // Auf 24 Stundenbetrieb setzen
// rtc_set_time (9,49,00);       // Uhrzeit einstellen
// rtc_set_date (9,3,06);       // Datum einstellen
LED_rot = 1;

//           delay_ms (10000);
//           rtc_get_time(&hour,&min,&sec);
//           uhrzeit.stunde=hour;
//           uhrzeit.minute=min;
//           uhrzeit.sekunde=sec;
//           delay_ms (10000);
//           rtc_get_date(&date,&month,&year);
//           datum.tag=date;
//           datum.monat=month;
//           datum.jahr=year;
//           delay_ms (15000);
//           LED_gelb = 1;
//           LED_gruen = 1;
//           delay_ms (20000);
//           LED_gelb = 0;
//           LED_gruen = 0;

// Global enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here

     };
}


Vielleicht kann mir ja jemand helfen.

schon mal vielen Dank!
Gruß
Christoph

von Christoph (Gast)


Lesenswert?

beim ersten SS muss es natürlich eine 0 sein

von Christoph (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
vielleicht kann mir ja doch noch jemand helfen. nachdem ich das
Programm  auf den ATmega( gespielt habe, bleibt es sofort hängen, die
rote LED geht erst gar nicht an.
Ich habe das Programm mit Code Vision erstellt.
Es soll die Bits in das das EEprom Verzeichnis des Beschleunigungssenor
schreiben.
Vielen Dank für die Hilfe!
Gruß
Christoph

von Dirk Doerr (Gast)


Lesenswert?

Hi!

Bist Du sicher, daß die LED mit 1 angeschaltet wird und nicht mit 0?

Dann noch etwas

bit_setzen (0x26,(1<<6));    // Bit setzen im eeprom vom
Beschleunigungssenor
bit_setzen (0x26,(1<<5));    // Bit setzen im eeprom vom
Beschleunigungssenor

So steht dann nur 0x20 im Register 0x26, sprich nur Bit 5 ist gesetzt.
Wenn Du beide Bits setzen willst solltest Du das ganze verknüpfen.
Also

bit_setzen(0x26,(1<<6)|(1<<5));

Viele Grüße

        Dirk

von Christoph (Gast)


Lesenswert?

Danek schon mal.
leider war es das nicht.

von Dirk Doerr (Gast)


Lesenswert?

Hi!

> leider war es das nicht.

Was meinst Du jetzt. Das Bit setzen oder die LED?

> [...] gespielt habe, bleibt es sofort hängen, die
> rote LED geht erst gar nicht an.

Daher nochmal die Frage, werde Deine LEDs mit 1 oder mit 0 geschaltet.


Und was natürlich auch auffällt. bit_setzen sind Deine ersten
Anweisungen in Main, noch bevor Du die SPI Schnittstelle konfigurierst.
Ich würde mal sagen, daß kann nicht gehen.

Viele Grüße

    Dirk

von Christoph (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

die LED wir mit 1 geschaltet. das habe ich schon probiert. ohne die SPI
Schnittstelle klappt das auch.
jetzt habe Bit_setzen hinter die die rote LED geschrieben.Die LED
leuchtet jetzt aber die Bits werden nicht geschrieben.

von Dirk Doerr (Gast)


Lesenswert?

Hi!

> // warten bis Übertragung beendet
>         while (SPSR |= (1<<7) );

So stand das aber nicht in den Beispielen (Datenblatt oder dem Link,
den ich Dir geschickt habe).

Das dürfte eine Endlosschleife sein.

Im Datenblatt des Controllers steht doch ein Beispiel:

SPI_MasterTransmit(char cData)
{
SPDR= CData;
while (!(SPSR!(1<<SPIF)));
}

Dort wird in der While Schleife solange das Status Register gelesen bis
das Bit SPIF gesetzt ist (=> die Übertragung beendet ist)



Viele Grüße

     Dirk

von Dirk Doerr (Gast)


Lesenswert?

Nachtrag:
Was Du gemacht hast:

Du versuchst im  Status Register das Bit 7 zu setzen. Genauer gesagt
liest Du das StatusRegister aus (grob gesprochen: das macht das =) Dann
veroderst Du das Ergebnis mit 0x80 (das macht das | und (1<<7)). Dann
schreibst Du dieses Ergebnis in das Statusregister.
 (!= besagt erst lesen, verodern und wieder zurückschreiben)

Dieser ganze Ausdruck wird von C als ungleich 0 gesehen. Damit bleibt
die While-Bedingung erfüllt und die Schleife wird noch einmal
durchlaufen. Und nocheinmal. Und noch einmal......

von Christoph (Gast)


Lesenswert?

stimmt. hatte das ausprobiert, weil es sonst nicht geklappt hat. aber
anscheint klappt es jetzt.
recht herzlichen Dank!

von Christoph (Gast)


Lesenswert?

Hallo,
ich nerv mal wieder.
Ich möchte jetzt die Daten auslesen und im eeprom speichern.

Jetzt bekomme ich wieder eine Fehlermeldung. und zwar incompatible
operand "=".
Was mach da denn schon wieder falsch?

Hier der Programmabschnitt:

void spi_lese (char adress)
{
        char data;
        // CSB low
        CSB = 0;
        spi_sende (adress);
        data = spi_sende(0xFF);     //Fehlermedung "incompatible
operand "="
        //CSB high
        delay_ms (2);
        CSB = 1;
}

Gruß
Christoph

von Dirk Doerr (Gast)


Lesenswert?

spi_sende hast Du in Deinem Programm als void deklariert. Gab das
eigentlich keine Warnung vom Compiler? Du lieferst trotz void einen
Wert mit return zurück.

Gruß

       Dirk

von Dirk Doerr (Gast)


Lesenswert?

Noch was:

Wozu soll das delay_ms(2) gut sein?


Wenn Du damit den Satz [...] the next SPI command should not occur
before a 2 ms delay [...] berücksichtigen willst, solltest auch
wirklich 20 ms warten und vor allem das delay nach dem CSB = 1
ausführen. (Wobei sich Dein AVR 20 ms langweilen wird in der er viele
andere Sachen machen könnte).

von Christoph (Gast)


Lesenswert?

Hatte das retuen vergessen, bekommen jetzt auch die Fehlermeldung (Void
functions may not return a value). jetzt hatte ich das aber so
übernommen, wie das in dem Link steht.

von Dirk Doerr (Gast)


Lesenswert?

im Link ist die Funktion spi_putc mit dem Rückgabewert uint8_t
deklariert.

von Christoph (Gast)


Angehängte Dateien:

Lesenswert?

hallo,

das setzen der bits hat funktioniert. (Wer lesen kann ich klar im
Vorteil!;-) )
Aber das auslesen habe ich noch nicht raus bekommen.
Ich möchte die Adressen 1Ah bis 1Fh abfragen und im eeprom speichern.
Später wollte ich eine Grenzwerte bestimmen und diese speichern.

Gruß
Christoph

von Dirk Doerr (Gast)


Lesenswert?

In welchem EEPROM willst Du was speichern?


> spi_lese ((0x1E)<<3);                   // Daten auslesen    ?
> spi_lese ((0x1C)<<3);                   // Daten auslesen    ?
> spi_lese ((0x1A)<<3);                   // Daten auslesen    ?
> beschl.y = ((0x1E)<<3);                 // Daten speichern   ?
> beschl.z = ((0x1C)<<3);                 // Daten speichern   ?
> beschl.x = ((0x1A)<<3);                 // Daten speichern   ?

Was soll das bewirken?

> spi_lese ((0x1E)<<3)

Damit liest Du die Adresse F0 aus (0x1E um 3 Stellen nach links
verschoben). Und das Ergebnis wirfst Du weg

> beschl.y = ((0x1E)<<3);

beschl.y wird der Wert 0xF0 zugewiesen.

Wäre es nicht besser Du lernst erst einmal auf einem PC in C
programmieren, bevor Du mit Mikrocontroller anfängst?

von Marian (Gast)


Lesenswert?

Hallo Christoph!
Hast du es denn nun endlich mal geschafft die Beschleunigungswerte
auszulesen? Wenn ja, was für Werte erhälst du im 2g Modus von deinem
Sensor?

Gruß
Marian

PS: Ich finde leider deinen anderen Thread nicht mehr, da habe ich dich
das schonmal gefragt.

von Nikias Klohr (Gast)


Lesenswert?

Hi,

ich finde den Sensor ziemlich interessant, kann aber keine Bezugsquelle
auftreiben! Wo habt ihr den denn her?
Gruß,
Nikias

von Marian (Gast)


Lesenswert?

@Nikias Klohr: Sorry das ich mich so spät melde aber ich hatte das Thema
leider vergessen.

Du kannst diese Bluetoothmodule bei www.stollmann.de ordern.

@Christoph: Wie weit bist du denn mittlerweile mit dem Programmieren
des Moduls? Beschäftigst du dich damit eigentlich noch?

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.