Hallo liebe Forengemeinde, also vorab: ich bin ein totaler Anfänger! Aber ich gebe mir Mühe. Ich habe den Atmega8 und das STK500-Board. Dazu habe ich einen Code geschrieben, den ich dann auf den Atmega8 flashe. CODE: #include <avr/io.h> // Register Definition fuer ATmega8 #include <avr/interrupt.h> // Für Timer1 Overflow-Interrupt #include <util/delay.h> // Für Delay-Funktion #define FOSC 8000000 // Clock Speed = Oszillator-Freq. #define BAUD 9600 // Muss in Matlab übereinstimmen #define MYUBRR FOSC/16/BAUD-1 // Siehe Datenblatt unter USART /*------------------------------------------------------------------ globale Variablen ------------------------------------------------------------------*/ volatile uint16_t stepsTiH; volatile uint16_t stepsTiL; volatile uint16_t stepsTw; /*------------------------------------------------------------------ Funktionen zum USART - RS232 ------------------------------------------------------------------*/ // Initialisierung --> Einstellungen in Matlab MÜSSEN GLEICH SEIN void USART_Init( unsigned int ubrr) { /* Set baud rate */ UBRRH = (unsigned char)(ubrr>>8); UBRRL = (unsigned char)ubrr; /* Enable receiver and transmitter */ UCSRB = (1<<RXEN); /* Set frame format: 8data, 2stop bit */ UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0); } // 8-bit Wort empfangen uint16_t USART_Receive(void) { /* Wait for data to be received */ while(!(UCSRA & (1<<RXC))) { } /* Get and return received data from buffer */ return UDR; } /*------------------------------------------------------------------ Funktionen zum Timer1 ------------------------------------------------------------------*/ void Timer1_WriteTCNT1(void) { unsigned char sreg; /* Save Global Interrupt Flag */ sreg = SREG; /* Disable interrupts */ cli(); /* Set TCNT1 to i */ TCNT1H = stepsTiH; //Lade Timer1 mit Wert TCNT1L = stepsTiL; //Anzahl Schritte bis zum Overflow /* Restore Global Interrupt Flag */ SREG = sreg; } //Zeitpunkt des Aufrufs von Timer1_An() entspricht SOI void Timer1_AN(void) { Timer1_WriteTCNT1(); PORTB = 0b00000000; TCCR1B = (1<<CS10); //kein prescale verwenden TIMSK = (1<<TOIE1); //Interrupt für Timer1 enable sei(); //globale Interrupts enable SREG |= (1 << SREG_I); } void Timer1_AUS(uint16_t anzSchritte) { TCCR1B = (0<<CS10); //Timer1 aus PORTB = 0b11111111; //Ausgang PortB for(int i = 0; i < anzSchritte; i = i+1) { _delay_ms(10); //Wartezeit } } ISR(TIMER1_OVF_vect) { Timer1_AUS(stepsTw); //Warteroutine Timer1_AN(); } /*------------------------------------------------------------------ main ------------------------------------------------------------------*/ int main (void) { USART_Init(MYUBRR); //UART initialisieren DDRB = 0b11111111; //PORTB als Ausgang PORTB = 0b11111111; uint16_t checkSum = 0; uint16_t data1 = 0; uint16_t data2 = 0; uint16_t data3 = 0; while(1) { data1 = USART_Receive(); //Empfangene Daten1,ti(1..8) data2 = USART_Receive(); //Empfangene Daten2,ti(9..16) data3 = USART_Receive(); //Empfangene Daten3,tw(1..8) checkSum = data1+data2+data3; //Summe der 3 Daten(Urzustand) if(checkSum == 0) { TCCR1B = (0 << CS10); //Timer1 aus PORTB = 0b11111111; //Ausgang PortB } else { stepsTiH = data1; //Definieren stepsTiH stepsTiL = data2; //Definieren stepsTiL stepsTw = data3; //Definieren stepsTw Timer1_AN(); //Starten von Timer1 } } } Kurze Erläuterung: Ich übertrage 3 Variablen mit Matlab. Diese werden in data1,data2,data3 gespeichert. Die Variablen (data...) benötige ich für den Timer1_AN(). Im Grunde genommen liegt eine Spannung an, die für einen "Augenblick" (hier ist die Eingabe von data1 und data2 zuständig) unterbrochen wird. data3 ist eine Art "Wartezeit" bis zum nächsten Start. Nun habe ich auf dieser Seite http://www.mikrocontroller.net/articles/Interrupt gesehen, dass man neben senden auch empfangen kann. Hier wird sogar eine LED zum Morsen von Daten verwendet. Leider verstehe ich den Code nicht wirklich. Vor allem empfängt meine Funktion "uint16_t USART_Receive(void)" ein 8 Bit Wort, in dem Beispielcode ist aber nur von einem String die Rede. Meine Frage nun: Wie kann ich die 2 Sachen kombinieren? Endsituation sollte sein: Ich möchte Daten übertragen, die übertragenen Daten sollen zurückgesendet werden, am besten mit dieser Morseled, und dann sollten auch noch meine Timer1_AN() Funktion anlaufen. Gruß Joe
Johannes F. schrieb: > Nun habe ich auf dieser Seite > http://www.mikrocontroller.net/articles/Interrupt > gesehen, dass man neben senden auch empfangen kann. Hier wird sogar eine > LED zum Morsen von Daten verwendet. Leider verstehe ich den Code nicht > wirklich. Vor allem empfängt meine Funktion "uint16_t > USART_Receive(void)" ein 8 Bit Wort, in dem Beispielcode ist aber nur > von einem String die Rede. > > Meine Frage nun: Wie kann ich die 2 Sachen kombinieren? Hmm. Irgendwie verstehe ich die Fragestellung nicht wirklich. Denn auch die Sende-Funktionalität für Strings stützt sich letzten Endes auch auf eine Funktion die 1 Byte sendet. Du hast einzelne Bytes und eine Funktion die 1 Byte senden kann. Passt doch perfekt! Am besten siehst du dir den Artikel aus dem avr-gcc-tutorial näher an: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART Da wird dir UART senden auf die einfachere Variante (ohne Interrupt) näher gebracht. > Endsituation sollte sein: > Ich möchte Daten übertragen, die übertragenen Daten sollen > zurückgesendet werden, am besten mit dieser Morseled, zurückgesendet wohin? Und wozu brauchst du dann die Morseled? Diese LED ist doch nur 1 Beispiel, was man mit den Daten machen kann hat aber mit dem eigentlichen Thema UART senden/empfangen nichts zu tun.
Erstmal danke für die Antwort! Vorab: MorseLED sollte nur auf mein Board, wenn es möglich ist, also als ein kleiner Bonus. Wie man aus meinem Programm sieht, habe ich das Senden und Empfangen OHNE Interrupt erfolgreich hinbekommen. Problem ist halt, dass ich in der while- Schleife ständig im Zustand "data1 = USART_Receive();" mich befinde, erst wenn was gesendet wird, dann geht es weiter. Dies wollte ich nun umgehen, so dass ich mich ebend NICHT in diesem Zustand befinde. Ich SOLL erst in diesen Zustand, wenn auch wirklich ein Information geschickt wird, also ein Interrupt ausgelöst wird. Frage: Welche Funktion im Beispielcode entspricht meiner "USART_Receive()" Funktion? Gruß Joe
joe1234 schrieb: > Wie man aus meinem Programm sieht, habe ich das Senden und Empfangen > OHNE Interrupt erfolgreich hinbekommen. Problem ist halt, dass ich in > der while- Schleife ständig im Zustand "data1 = USART_Receive();" mich > befinde, erst wenn was gesendet wird, dann geht es weiter. Dann ändere das doch :-) Deine USART_Receive muss ja nicht in der while Schleife hängen, wenn nichts da ist. Du bist der Programmierer. Du bestimmst, was passieren soll. Die Funktion kann genau so gut auch zum Aufrufer zurückkehren und mitteilen: "War nichts da!" Und der Aufruf sagt sich dann: Na gut, wenn nichts da ist, dann mach ich auch nichts oder ich mach in der Zwischenzeit was anderes und schau in einer Hunderstelsekunde oder wann ich das nächste mal wieder Zeit habe, erneut nach. Das nennt sich dann Polling: in regelmässigen Zeitabständen nachsehen, ob es was zu tun gibt. > Welche Funktion im Beispielcode entspricht meiner "USART_Receive()" > Funktion? Das kann man so nicht vergleichen IM Beispielcode wird von der UART ein Interrupt ausgelöst, wenn ein Zeichen vollständig reinkommt und die ISR(USART_RXC_vect) aufgerufen. Die behandelt dann das eine Zeichen.
Hier habe ich nun einen Code geschrieben, leider OHNE Interrups. :-( Problem bei meinem Code ist, dass wenn ich z.B. ti und tw auf 10 setze, bruacht der Atmega8 fast 1:40 min um die Operation auszuführen. Danach geht die LED erst wieder an. Mache ich da was flasch??? Code: #include <avr/io.h> // Register Definition fuer ATmega8 #include <avr/interrupt.h> // Für Timer1 Overflow-Interrupt #include <util/delay.h> // Für Delay-Funktion #define FOSC 8000000 // Clock Speed = Oszillator-Freq. #define BAUD 9600 // Muss in Matlab übereinstimmen #define MYUBRR FOSC/16/BAUD-1 // Siehe Datenblatt unter USART /*------------------------------------------------------------------ globale Variablen ------------------------------------------------------------------*/ volatile uint16_t stepsTiH; volatile uint16_t stepsTiL; volatile uint16_t stepsTw; /*------------------------------------------------------------------ Funktionen zum USART - RS232 ------------------------------------------------------------------*/ // Initialisierung --> Einstellungen in Matlab MÜSSEN GLEICH SEIN void USART_Init(unsigned int ubrr) { /* Set baud rate */ UBRRH = (unsigned char)(ubrr>>8); UBRRL = (unsigned char)ubrr; /* Enable receiver and transmitter */ UCSRB = (1<<RXEN)|(1<<TXEN); /* Set frame format: 8data, 2stop bit */ UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0); } // 8-bit Wort empfangen uint16_t USART_Receive(void) { /* Wait for data to be received */ while(!(UCSRA & (1<<RXC))) { } /* Get and return received data from buffer */ return UDR; } // 8-bit Wort senden void USART_Transmit(unsigned char data) { /* Wait for empty transmit buffer */ while ( !( UCSRA & (1<<UDRE)) ) { } /* Put data into buffer, sends the data */ UDR = data; } /*------------------------------------------------------------------ Funktionen zum Timer1 ------------------------------------------------------------------*/ void Timer1_WriteTCNT1(void) { unsigned char sreg; /* Save Global Interrupt Flag */ sreg = SREG; /* Disable interrupts */ cli(); /* Set TCNT1 to i */ TCNT1H = stepsTiH; //Lade Timer1 mit Wert TCNT1L = stepsTiL; //Anzahl Schritte bis zum Overflow /* Restore Global Interrupt Flag */ SREG = sreg; } //Zeitpunkt des Aufrufs von Timer1_An() entspricht SOI void Timer1_AN(void) { Timer1_WriteTCNT1(); //PORTC = 0b00000000; PORTC = (0 << PC0); TCCR1B = (1<<CS10); //kein prescale verwenden TIMSK = (1<<TOIE1); //Interrupt für Timer1 enable sei(); //globale Interrupts enable SREG |= (1 << SREG_I); } void Timer1_AUS(uint16_t anzSchritte) { TCCR1B = (0<<CS10); //Timer1 aus //PORTC = 0b11111111; //Ausgang PortC PORTC = (1 << PC0); for(int i = 0; i < anzSchritte; i++) { _delay_ms(10); //Wartezeit midestens 10 ms } } ISR(TIMER1_OVF_vect) { Timer1_AUS(stepsTw); //Warteroutine Timer1_AN(); } /*------------------------------------------------------------------ main ------------------------------------------------------------------*/ int main (void) { USART_Init(MYUBRR); //UART initialisieren DDRC = (1 << PC0); // PC0 als Ausgang festlegen für Impuls PORTC = (1 << PC0); // PC0 aktivieren DDRB = (1 << PB1); // PB1 als Ausgang festlegen für Diode uint16_t checkSum = 0; uint16_t data1 = 0; uint16_t data2 = 0; uint16_t data3 = 0; while(1) { PORTB = (0 << PB1); //PB1 aktivieren, LED leuchtet data1 = USART_Receive(); //Empfangene Daten1,ti(1..8) data2 = USART_Receive(); //Empfangene Daten2,ti(9..16) data3 = USART_Receive(); //Empfangene Daten3,tw(1..8) checkSum = data1+data2+data3; //Summe der 3 Daten(Urzustand) if(checkSum == 0) { USART_Transmit(73); //I USART_Transmit(78); //N USART_Transmit(74); //J USART_Transmit(69); //E USART_Transmit(67); //C USART_Transmit(84); //T USART_Transmit(79); //O USART_Transmit(82); //R USART_Transmit(data1); //Übertragen data1 USART_Transmit(data2); //Übertragen data2 USART_Transmit(data3); //Übertragen data3 PORTB = (1 << PB1); //PB1 deaktivieren, LED geht aus TCCR1B = (0 << CS10); //Timer1 aus PORTC = (1<<PC0); //PC0 auf 1 legen, Ausgangszustand } else { stepsTiH = data1; //Definieren stepsTiH stepsTiL = data2; //Definieren stepsTiL stepsTw = data3; //Definieren stepsTw USART_Transmit(data1); //Übertragen data1 USART_Transmit(data2); //Übertragen data2 USART_Transmit(data3); //Übertragen data3 PORTB = (1 << PB1); //PB1 deaktivieren, LED geht aus Timer1_AN(); //Starten von Timer1 } } }
Ich bin schier am verzweifeln... Wenn ich die 2 Befehle mit LED aus der while- Schleife entferne, dann läuft alles rund. Sobald ich sie wieder benutze, zickt der Atmega8!!! Gruß Joe
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.