Hallo liebes Forum, da ich mich erst mit dem Thema Mikrocontroller am einarbeiten bin, bitte ich schon mal um Nachsicht wegen evtl "einfacher" Fragen. Ich haben einen Atmega 8515L (auf dem STK500), welchen ich nutzen will um einen IC ltc6802-2 zu konfigurieren und später auch auszulesen. Zunächst will ich einige Bytes vom Master (Atmega) zum Slave senden. Gleichzeitig will ich die gesendeten Bytes auf dem UART am Rechner zur Kontrolle (über uart_puts(comData);) ausgeben. Die Initialisierung des Uart sollte stimmen, da ich einen "Hello World" String normal ausgeben kann. Die LED on/off dienen lediglich zur eigenen Kontrolle, wo ich mich gerade befinde. Momentan werden die Bytes nicht sauber gesendet. Auch an der Uart Schnittstelle sehe ich ein anderes Ergebnis als erwartet. Wäre toll, wenn mir jemand weiterhelfen könnte. Hier ist mein verwendeter Code: #include <avr/io.h> #include <avr/interrupt.h> #include <avr/signal.h> #ifndef F_CPU #define F_CPU 1000000L // Systemtakt in Hz #endif #define BAUD 4800L // Baudrate // Berechnungen #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) // Fehler in Promille #if ((BAUD_ERROR>10) || (BAUD_ERROR<-10)) #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! #endif #include <util/delay.h> /* in der aktuellen Version in util/ */ // UART Interface void uart_init(void) //Init Uart { //UCSRB |= (1<<RXEN) | (1<<TXEN); // UART TX einschalten UCSRB |= (1<<TXEN); // UART TX einschalten UCSRC = (1<<URSEL)| (1<<UCSZ1) | (1<<UCSZ0); // 8 Datenb , 1Stb UBRRH = UBRR_VAL >> 8; UBRRL = UBRR_VAL & 0xFF; } void uart_putch(char c) { while(!(UCSRA & (1<<UDRE))); UDR = c; } void uart_puts(char * str) { while (*str) { uart_putch(*str++); } } //////////// Test LED 3 on off //////////// void led3_on(void) { DDRB |= (1 << PB3); //Port 3 Out PORTB |= (1 << PB3); //LED on _delay_ms(1000); } void led3_off(void) { DDRB |= (1 << PB3); //Port 3 Out PORTB &= ~(1 << PB3); //LED off _delay_ms(1000); } // SPI Interface void spi_init (void) //Init SPI { DDRB |= (1<<PB4)|(1<<PB5)|(1<<PB7); // MOSI,SCK,SS als Output PORTB |= (1<<PB4); //SS auf High SPCR |= (1<<SPE)|(1<<MSTR); // SPI enable, Master Mode } void spi_senden (unsigned comData, unsigned CFGR0, unsigned CFGR1, unsigned CFGR2, unsigned CFGR3, unsigned CFGR4, unsigned CFGR5) { PORTB &= ~(1 << PB4); //START SENDEN SS auf Low SPDR = comData; //Command Byte while (!(SPSR & (1 << SPIF))); //warten bis gesendet while (!(UCSRA & (1<<UDRE))) //ist die Sendestufe bereit? { } uart_puts(comData); led3_on(); SPDR = CFGR0; while (!(SPSR & (1 << SPIF))); //warten bis gesendet SPDR = CFGR1; while (!(SPSR & (1 << SPIF))); //warten bis gesendet SPDR = CFGR2; while (!(SPSR & (1 << SPIF))); //warten bis gesendet SPDR = CFGR3; while (!(SPSR & (1 << SPIF))); //warten bis gesendet SPDR = CFGR4; while (!(SPSR & (1 << SPIF))); //warten bis gesendet SPDR = CFGR5; while (!(SPSR & (1 << SPIF))); //warten bis gesendet while (!(UCSRA & (1<<UDRE))) //ist die Sendestufe bereit? { } uart_puts(CFGR5); //led3_off(); PORTB |= (1 << PB4); //ENDE SS auf high } int main(void) { uart_init(); spi_init(); spi_senden(0x01, 0xE1, 0x04, 0x00, 0xFF, 0x73, 0xAF); // Write Config while(1) { led3_off(); } return 0; }
>Momentan werden die Bytes nicht sauber gesendet. Woher weisst du das? Auf dem Osci nachgesehen? Dann liegt es an deiner Schaltung. > Auch an der Uart >Schnittstelle sehe ich ein anderes Ergebnis als erwartet. Das ist so weil du nicht weisst was ein String ist. Ich rate dir dringend zu einem C-Buch oder Lehrgang.
1 | uart_puts(comData); |
Das ist Unsinn und sendet daher auch Unsinn. comData ist nun mal kein Pointer auf einen String. Du solltest dir gleich von Anfang an angewöhnen, alle Warnungen des Compilers ernst zu nehmen. PS: Für "uart_puts(CFGR5);" gilt natürlich das gleiche. ;-) PPS: Und verwende bitte beim nächsten Mal die vom Forum angebotene Möglichkeit der Source-Code-Formatierung.
Danke , mit
1 | uart_putch[comData); |
stimmt auch die Ausgabe im Terminal. Die Daten werden laut Oszi verschickt. Aber eigentlich will ich den Befehl nur einmal senden. Momentan habe ich bei SPI_Senden() eine Endlos-Schleife und ich sehe nicht warum? In die While(1) Schleife komme ich gar nicht hinein.
WDTON Haken ist nicht gesetzt und Atmega8515 ist eingestellt. Wenn ich die Funktion innerhalb von main() aufrufe, dann wird die Schleife genau einmal durchlaufen und geht weiter zur while(1).
>>Aber eigentlich will ich den Befehl nur einmal senden. Momentan habe ich >>bei SPI_Senden() eine Endlos-Schleife und ich sehe nicht warum? >>In die While(1) Schleife komme ich gar nicht hinein. >Wenn ich die Funktion innerhalb von main() aufrufe, dann wird die >Schleife genau einmal durchlaufen und geht weiter zur while(1). Fällt dir auf das sich deine Aussagen widersprechen?
Hmm vielleicht habe ich mich ja falsch ausgedrückt. Ich will die Byte-folge einmal senden. Wenn ich die Funktion zum senden der Bytes spi_senden() außerhalb von main verwende, dann wiederholt sich diese Funktion immer wieder. Wenn ich die Funktion innerhalb von main() setze und überhalb der while(1) Schleife, dann wird die Byte-Folge genau einmal gesendet.
Gibt es eigentlich eine fertige Funktion,um per SPI Strings zu senden? oder müsste man sich die aus der Bytesenden-Routine selber zaubern und die Routine mehrmals aufrufen, solange das zeichen != '\0' ist? Danke und Gruß jo
Ich kenne keine fertige Funktion, da ja auch jede SPI Kommunikation von Datenblatt abhängt.
Hey Micha, was genau machst du denn mit dem Balancer ? Laden und samplen und balancen? oder nur als ADC benutzen? ich hab das teil auch mal eingesetzt, allerdings habe ich keine Ahnung wo der Quellcode ist... gruß Elko
füg mal ein
1 | #include <avr/wdt.h> |
ein und ruf direkt als erstes in der main
1 | wdt_disable(); |
auf. Der 8515L hat keine Fuse für den WatchDogTimer (aus), da du ihn nicht deaktiviert startet der Mikrocontroller permanent neu. WDTON mach ihn nur permanent an. Ausschalten muss du den WDT trotzdem. Für später um die Initialisierungen immer ein
1 | cli(); |
2 | //Initialisierungen ...
|
3 | sei(); |
packen. Die DDRX Register für die Pins muss du auch nur einmal einstellen. Braucht nicht vor jeden ändern der LED nochmal stehen.
Zu deiner Frage (String per SPI senden): Schau dir doch den Code zu senden von String über UART, an der greift auch auf das Senden einzelner Zeichen zurück. Dasselbe muss du mit SPI machen (-> Copy&Paste).
Micha schrieb: > Ich will die Byte-folge einmal senden. Wenn ich die Funktion zum senden > der Bytes spi_senden() außerhalb von main verwende, dann wiederholt sich > diese Funktion immer wieder. Dann zeige uns den Code zu diesem "außerhalb von main verwende", denn in dem Code oben wird die Funktion in main aufgerufen. Wie sollen wir dir sagen, was dort schief läuft, wenn wir den Code dazu nicht kennen?
Dieser Code macht zumindest das, was ich will. Einmalig eine Bytefolge aussenden und dauern eine kürzere Byte-folge aussenden. Der Quellcode ist als Anhang beigefügt @Elko ich will zunächst die Spannung über ADC auslesen und ausgeben. Wäre toll, wenn Du den Quellcode nochmal findest (?) und mal posten kannst.
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.