hallo, mache eine versuche mit einem atmega16. empfangen + senden. es functionniert ohne interrupt jetzt moechte ich das epfangen und senden auf interrupt-gesteuert umstellen, kann jemand mir sagen wie ich das machen kann? hier ist meine code die richtig functionniert ohne interrupt Danke Jano #include <avr/io.h> #include <avr/interrupt.h> #include <avr/signal.h> /*Size of the circular receive buffer, must be power of 2*/ #ifndef UART_RX_BUFFER_SIZE #define UART_RX_BUFFER_SIZE 32 #endif /*Size of the circular Transmit buffer, must be power of 2*/ #ifndef UART_TX_BUFFER_SIZE #define UART_TX_BUFFER_SIZE 32 #endif // CHECK F_CPU WITH HARDWARE OSZILLATOR SETTING !!!! #define F_CPU 1000000UL #define UART_BAUD 9600 /* * module global variables */ int g_idx; int MAX_BUFFER_SIZE; MAX_BUFFER_SIZE=UART_TX_BUFFER_SIZE; unsigned char Buf[UART_TX_BUFFER_SIZE]; int bxoff = 0; unsigned char c; void uart_init(void); unsigned int uart_getdata(void); //unsigned char uart_getc(void); void uart_putdata(unsigned char c); //int uart_putc(unsigned char c); void uart_puts (char *s); int main(void) { unsigned char c; uart_init(); uart_puts("hello world!\r\n\r\n"); while(1) { // Poll c = uart_getdata(); // Echo uart_putdata(c); } return 0; } void uart_init(void) /****************************************************************** Function: Uart_init() Purpose: Initialise UART and set baudrate Input: baudrate Returns: none ******************************************************************/ { UCSRB |= (1<<TXEN) |(1<<RXEN); // tx/rx enable UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron 8N1 #if F_CPU < 2000000UL && defined(U2X) UCSRA |= (1<<U2X); /* improve baud rate error by using 2x clk */ UBRRL = (F_CPU / (8UL * UART_BAUD)) - 1; #else UBRRL = (F_CPU / (16UL * UART_BAUD)) - 1; #endif } void uart_putdata(unsigned char c) { int n; n = g_idx; g_idx = 0; while (n>0){ c = Buf[g_idx]; g_idx++; while (!(UCSRA & (1<<UDRE)))// Warten bis senden möglich { } UDR=c; n-=1; } bxoff=0; return UDR; } void uart_puts (char *s) /********************************************************************** Function: Uart_puts() Purpose: Transmit string to UART Input: String to be transmitted Returns: none **********************************************************************/ { while (*s) { /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */ uart_putdata(*s); s++; } } unsigned int uart_getdata(void) { if (bxoff == 0) { while (g_idx < MAX_BUFFER_SIZE){ while (!(UCSRA & (1<<RXC))) c=UDR; if (c == '\r'){ return c; } else Buf[g_idx]=c; g_idx++; } bxoff=1; return; } }
Hallo Jano, geht recht einfach: 1. IRQ's scharf machen Bit 7 (RXCIE Rx complete IRQ) in UCSRB setzen Bit 5 (USART Data register empty) in UCSRB setzen alterativ geht auch Bit 6, Transmit Complete, doch Data register empty hat den Vorteil, das sozusagen in den Zwischenspeicher geschrieben wird und damit ein kontinuierlicher Datenstrom auf der Leitung entsteht. 2. Routine erstellen ISR (USART_RXC_vect) ISR (USART_UDRE_vect) 3. IRQ's im Hauptprogramm freischalten mit sei(); Bitte daran denken, das Variablen die auch in den IRQ's genutzt werden als volatile gekennzeichnet sein müßen z.B. volatile unsigned short ms; // ms Zeitgeber Grüße Hans-Josef
danke hjm, noch einigen problemen: nach dem ich habe die IRQ mit sei() und die RXCIE und UDRIE im hauptprogramm freigeschaltet wie soll die Routinen aussehen? ich meine was soll in ISR(USART_RXC_Vect) und in ISR(USART_UDRE_Vect) stehen? gibt mir nur ein bsp um mir zu zeigen wie die routinen aussehen können. noch was soll ich etwa in meine vorherrige code ohne INterrupt ändern? danke vor die Hilfe Jano
Hallo Jano, was willst Du denn mit den Routinen machen? Soll was empfangen werden und gleichzeitig wieder gesendet werden, oder wie sieht Dein Ablauf aus? Dann kann man eher sagen wie man es am besten macht. In der Regel empfängt man mit Interrupt und sendet im Pollbetrieb, da das Prg, seine Daten erst los werden muß. Zu Deinem Prg, da gibts sicher ein paar Stellen die verbesserungswürdig sind, aber wenns funktioniert!!! Grüße Hans-Josef
mein Programm soll daten empfangen und im Puffer speicher und dannach hole ich wieder wieder die daten im puffer und senden die. grüße. ich bin offen für jeden verbesserung in meinem Programm Jano.
Hallo Jano, präzisiere bitte Deine Angaben. Denn: - wenn Du Daten in einem definierten Paket empfängst kann es bei hoher Baudrate passieren, das beim senden einige Daten im Empfangskanal verloren gehen, - wenn Du Daten mit definiertem Aussehen empfängst kann man genau einen Satz abwarten und lesen und diesen dann komplett versenden, Hast Du noch mehr Infos zu Datenrate, Telegramm- oder Datengröße, wie oft und wie diese versenden werden. Grüße Hans-Josef
>Zu Deinem Prg, da gibts sicher ein paar Stellen die verbesserungswürdig >sind,aber wenns funktioniert!!! Das ist eine Einstellung die geradewegs vor die Wand führt. @Jano: Du benutzt die Variable g_idx uninitialisiert. In uart_putdata weist du sie n zu und benutzt dann n um Schleifendurchläufe zu steuern. Die Anzahl der Schleifendurchläufe ist damit unbestimmt! Gewöhn dir eine derartige Programmierweise erst gar nicht an. Außerdem erhöhst du deinen Pufferzeiger g_idx immer wenn du sendest und empfängst. Beim Senden setzt du ihn am Anfang auf 0. Wenn ich das richtig sehe passiert folgendes: Angenommen du sendest 20 Zeichen. Damit steht g_idx auf 19. Damit kannst du im nachhinein nur noch Puffergröße - (Anzahl gesendete Zeichen beim letzten Aufruf von uart_putdata) empfangen. Erst durch erneutes Senden kannst du mehr Empfangen. Ich glaube kaum das du dies wolltest. Ich nehme mal an du wolltest den gesamten Puffer als Empfangspuffer benutzen. Schreib lieber dein jetziges Programm erstmal ordentlich, bevor du zum nächsten Schritt übergehst.
Hallo Wolfram, das ist schön das Du Dich hier mit einklinkst, aber der Ton macht die Musik. Jano möchte ein Prg mit dem er empfangen und senden kann im Interrupt. Sicherlich sind Deine Statements richtig, aber seine Frage zielte nicht auf die Prüfung der Korrektheit seines Progs hin, sondern wie sich so was mittels IRQ's realisieren läßt. Um einen Lerneffekt zu erzielen, wäre es daher gut wenn man (Du) im ein entsprechendes Prg-Gerüst aufzeigen könnte. Damit wäre Ihm sicherlich mehr geholfen als mit "6 Setzen" "Neumachen". Ist nicht böse gemeint und soll auch nicht so aufgefasset werden, hier im Forum wird teilweise schon genung gestritten. Grüße Hans-Josef
Hallo Josef, hallo Wolfram, zu erst ich bedanke mich das sie mir so helfen. du deinen fragen Josef kann ich nur sagen für eine esrte mal ich will daten von Pc zu den controller sendendie daten sind Tastatur Zeichen und sie werden ungefähr 100 zeichen. diesen danten soll der controller empfangen und danach mehr mal zum PC Zurrück schicken.das wäre das esrte test das ich machen will Aber später könnte sein das die Datenströme nicht begrenzt sind und damit das die daten nicht verloren gehen soll ich die Datenaustauscht mit Hardware handshake dirrigieren so das wenn mein Puffer voll ist signalisiere ich zu der sender das er keine daten mehr senden nach diese schritt leere ich mein puffer aus und schalte ich wieder das Senden frei. Die Datenrate in beide richtung ist 9600bps Danke im voraus Jano
@ Jano (Gast) >du deinen fragen Josef kann ich nur sagen für eine esrte mal ich will >daten von Pc zu den controller sendendie daten sind Tastatur Zeichen und >sie werden ungefähr 100 zeichen. diesen danten soll der controller >empfangen und danach mehr mal zum PC Zurrück schicken.das wäre das esrte >test das ich machen will Na da solltest du die Tutorials durcharbeiten und umsetzen. Von den Interrupts solltest du vorerst die Finger lassen, das ist was für die höheren Semester. Das kommt später. AVR-Tutorial: UART http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Der_UART >Die Datenrate in beide richtung ist 9600bps Schnarchlangsam für einen uC. MfG Falk
Hallo Jano, irgendwie habe ich das ganze schon einmal gelesen. Hier: Beitrag "receive und Transmit via dem UART (ATmega16)", gings ums gleiche Problem. Dort ist auch eine Lösung mittels Fleury-Lib, die übrigens gut dokumentiert ist. Schau Dir das einmal an und nutze das Demo "testuart.c" aus der Lib, dort wir mittes IRQ empfangen und gesendet, obwohl bei der angegebenen Baudrate das sicherlich nicht notwendig sein sollte. Grüße Hans-Josef
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.