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
indem du in das datenblatt des Beschl. Sensors schausst und dann die richtigen werte in das Daten-Register des SPI schreibst.
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.
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
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?
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.
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
@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.
@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.
@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
ich habe am csb Pin vom Beschleunigungssensor 2,4 V anliegen. das ist doch nicht wirkliuch richtig oder?
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.
@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
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.
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.
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?
@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...
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
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
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
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
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.
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
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......
stimmt. hatte das ausprobiert, weil es sonst nicht geklappt hat. aber anscheint klappt es jetzt. recht herzlichen Dank!
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
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
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).
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.
im Link ist die Funktion spi_putc mit dem Rückgabewert uint8_t deklariert.
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
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?
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.
Hi, ich finde den Sensor ziemlich interessant, kann aber keine Bezugsquelle auftreiben! Wo habt ihr den denn her? Gruß, Nikias
@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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.