Hallo Leute, ich habe ein kleine Code gecshrieben für ein ATmega16. mit meiner Code will ich die Daten zwischen die PC und die Controller austauchen und es soll mit Hardware handshanke gemacht werden. für die Handshake habe ich die Pin 3 und 4 der PORTD der Controller als RTS und CTS gewählt die sind zur MAX232 verbunden. Die sache ist so: das Programm functionniert einigemasse ganz gut aber in der sende Richtung von Mikrocontroller zur PC, die Daten sind unendlich gesendet und das ist das Problem ich wollte gerne das die daten nur ein mal gesendet werden. hier ist meine Code bitte schauen Sie die und helfen Sie mir bitte das Problem zu lösen MFG Jano int main(void) { unsigned char c; DDRD = 0xFF; // PORT D als Ausgang PORTD = 0x08; // 4.Pin des PORTD eischalten um das CTS anzusprechen (empfangt Bedingung im seit der controller) uart_init(); sei(); // Freigabe aller Interrupt : Enable USART Interrupt //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) |(1<<RXCIE) |(1<<TXCIE)|(1<<UDRIE); // 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 } ISR(USART_RXC_vect) { for ( g_idx=0; g_idx < MAX_BUFFER_SIZE; g_idx++ ){ while (!(UCSRA & (1<<RXC))) // warten bis Zeichen verfuegbar { } c=UDR; if (c == '\r'){ return; } else Buf[g_idx]=c; //Daten im Puffer laden } PORTD=0x04; return; } ISR(USART_UDRE_vect) { int n; n = g_idx; g_idx = 0; for ( g_idx=0; g_idx < n; g_idx++ ) { c = Buf[g_idx]; while (!(UCSRA & (1<<UDRE)))// Warten bis senden möglich { } UDR=c; } UCSRB &= ~UDRIE; PORTD= 0X08; //Senden im seit der PC ein: die daten können von PC gesendet und im controller empfangen werden return; }
1 | ISR(USART_UDRE_vect) |
2 | {
|
3 | static int n = 0; |
4 | if (n<=g_idx) |
5 | {
|
6 | UDR = Buf[g_idx]; |
7 | }
|
8 | else
|
9 | {
|
10 | UCSRB &= ~UDRIE; |
11 | PORTD= 0X08; //Senden im seit der PC ein: die daten können von |
12 | PC gesendet und im controller empfangen werden |
13 | }
|
14 | }
|
So gehört das.
danke Rahul, mit deine Hilfe bin ich ein schritte weiter gekommen aber es ist noch nicht was ich genau wollte. das programm liefert mir nur ein byte zurrück und zwar das letzte eingegebene byte. Ich will gerne alle byte die ich eingegeben habe wieder zurrückt haben und in die selbe reihen folge (FIFO). kann jemand mir sagen wie ich das machen kann. danke MFG jano
Deine Empfangsroutine ist genauso Schwachsinn. Du hast anscheinend noch nicht verstanden, worum es in der ISR geht. Die ISR wird aufgerufen wenn ein Zeichen empfangen wurde. Es ist daher sinnlos in der ISR nochmal abzufragen, ob ein Zeichen empfangen wurde. Das wurde es nämlich, ansonsten wäre die ISR nie aufgerufen worden. In der ISR behandelst du dann dieses eine empfangene Zeichen und gehst wieder aus der ISR raus. Beim nächsten Zeichen, das empfangen wird, wird die ISR dann erneut aufgerufen. Es ist daher völliger Schwachsinn in der ISR in einer Schleife drauf zu warten, dass eine bestimmte Anzahl an Zeichen empfangen werden. Für jedes empfangene Zeichen wird deine ISR aufgerufen, die bearbeitet dieses eine Zeichen, zb. indem es das Zeichen an den Empfangsbuffer hinten dranhängt oder indem sie feststellt (weil das empfangene Zeichen ein '\n' war) dass damit die Eingabe abgeschlossen ist. Und damit hat sichs dann für die ISR, mehr tut sie nicht, insbesondere wartet die ISR nicht darauf, dass irgendwelche weitere Bedingungen eintreten.
Danke Karl für die Hinweisen. ich habe mein code nochmal geschrieben und ich dachte es sollte functionnieren aber es geht immer nicht. bitte schauen sie meine code und helfen sie mir mein programm im reihe zu kriegen bitte. MFG jano // // Datei uart.c // MCU: Atmega16 // #include <avr/io.h> #include <avr/interrupt.h> #include <avr/signal.h> /* ATmega with one USART */ #define ATMEGA_USART #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA #define UART0_STATUS UCSRA #define UART0_CONTROL UCSRB #define UART0_DATA UDR #define UART0_UDRIE UDRIE /*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 10 #endif /*high byte error return code of uart_getc()*/ #define UART_NO_DATA 0x0100 // CHECK F_CPU WITH HARDWARE OSZILLATOR SETTING !!!! #define F_CPU 1000000UL #define UART_BAUD 9600 /* * module global variables */ int g_idx; int p_idx; int MAX_BUFFER_SIZE; MAX_BUFFER_SIZE=UART_TX_BUFFER_SIZE; unsigned char Buf[UART_TX_BUFFER_SIZE]; //Empfang Buffer unsigned char TBuf[UART_TX_BUFFER_SIZE];// Sende Buffer int tmp = 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; DDRD = 0XFF; // PORT D als Ausgang PORTD = 0x08; // 4.Pin des PORTD eischalten um das CTS anzusprechen (empfangt Bedingung für die controller) uart_init(); sei(); uart_puts("hello world!\r\n\r\n"); while(1) { // Poll c = uart_getdata(); // Funny conversion /************************************************************ This converion ist only use to convert the alphabetic letter and they will be return als echo to the screen ************************************************************/ //if (c >= 'a' && c <= 'z') // c += 'A' - 'a'; //else if (c >= 'A' && c <= 'Z') // c += 'a' - 'A'; // 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) |(1<<RXCIE); // 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 } ISR(USART_RXC_vect) { c = UDR; } ISR(USART_UDRE_vect) { p_idx = tmp; if (p_idx <= g_idx) { UDR = TBuf[p_idx]; tmp++; } else { UCSRB &= ~UDRIE; } return; } void uart_putdata(unsigned char c) { int n = g_idx; g_idx = 0; while (g_idx == n); // fertig mit senden { PORTD = 0x08; // CTS Pin der controller ist wieder ein: sie kann wieder die Daten empfangen return; // zurrückt zur Hauptprogramm } /*************************************************************** Die Daten werden im Empfangt Puffer geholt und im Transmitter Puffer gespeichert damit das sie werden byte pro byte geholt und gesendet ****************************************************************/ c = Buf[g_idx]; TBuf[g_idx] = c; g_idx++; UCSRB |= (1<<UDRIE); } unsigned int uart_getdata(void) { g_idx = 0; while(g_idx != MAX_BUFFER_SIZE) //Das Empfang Puffer ist nicht voll { if(c == '\r') // letzte zeichen: zurrückt zur Hauptprogramm { return; } else { Buf[g_idx] = c; // Zeichen im Empfang puffer laden bis der Puffer voll ist g_idx++; } } PORTD = 0x04; // der Puffer ist voll die Controller kann keine daten mehr empfangen return; // also CTS ausschalten und RTS freischalten damit der Controller kann die daten senden }
Jano wrote: > ISR(USART_RXC_vect) > { > c = UDR; > } Das wiederrum ist nun wieder etwas zuwenig Arbeit für die ISR. Die ISR soll das Zeichen empfangen und zb. in den Buffer stellen. Gleichzeitig überwacht die ISR, welches Zeichen empfangen wurde, um der Hauptschleife in main() mitteilen zu können, dass eine Zeile empfangen wurde.
1 | volatile unsigned char LineReceived; |
2 | |
3 | ...
|
4 | |
5 | ISR( USART_RXC_vect ) |
6 | {
|
7 | char c; |
8 | |
9 | // Hole das Zeichen von der USART
|
10 | c = UDR; |
11 | |
12 | // war das ein '\n', wenn ja dann teile der main() mit,
|
13 | // das eine Zeile empfangen wurde und zur Bearbeitung ansteht
|
14 | if( c == '\n' ) { |
15 | Buf[g_idx] = '\0'; // Die Zeile für einen String korrekt abschliessen |
16 | LineReceived = 1; // Das gloable Flag setzen |
17 | g_idx = 0; // Beim nächsten empfangenen Zeichen wieder vorne |
18 | // im String speichern
|
19 | }
|
20 | |
21 | else { |
22 | // Die Zeile ist noch nicht zuende, speichere das Zeichen im
|
23 | // Buffer an der nächsten freien Stelle.
|
24 | // Hier fehlt noch die Fehlerbehandlung, was zu tun ist, wenn
|
25 | // der Buffer voll ist und nichts mehr Platz hat.
|
26 | Buf[g_idx] = c; |
27 | g_idx++; |
28 | }
|
29 | }
|
30 | |
31 | ...
|
32 | |
33 | void uart_puts( const char* OutText ) |
34 | {
|
35 | strcpy( TBuf, OutText ); |
36 | |
37 | ... gib die Zeichen aus TBuf Zeichen für Zeichen |
38 | aus. Dies kann zb. mit einer Interruptsteuerung |
39 | passieren. Das erste Zeichen wird hier ausgegeben. |
40 | Wenn es übertragen wurde, wird ein Interrupt ausgelöst, |
41 | welcher zum Aufruf einer ISR führt, in der dann die |
42 | weiteren Zeichen ausgegeben werden. |
43 | |
44 | ... Als Übung für den Leser absichtlich nicht implementiert, sondern |
45 | die einfachere Variante |
46 | |
47 | unsigned char i = 0; |
48 | while( TBuf[i] != '\0' ) |
49 | usart_putc( TBuf[i] ); |
50 | }
|
51 | |
52 | int main() |
53 | {
|
54 | ..
|
55 | |
56 | LineReceived = 0; |
57 | g_idx = 0; |
58 | |
59 | while( 1 ) { |
60 | |
61 | if( LineReceived ) { // Wenn eine Zeile komplett empfangen |
62 | // wurde, dann bearbeite sie ....
|
63 | |
64 | LineReceived = 0; |
65 | // zb. indem sie einfach zurückgeschickt
|
66 | // wird
|
67 | uart_puts( Buf ); |
68 | }
|
69 | }
|
70 | }
|
Jetzt brauchst du nur noch das Handshake einbauen: Wenn der Empfangsbuffer droht voll zu werden, dann teilst du mit der Handshake Leitung dem PC mit, mal kurzzeitig das Senden zu unterlassen. Jetzt musst du dir noch was überlegen, wann der PC wieder zu senden anfangen darf. Aber schau zu erst mal, dass du die Interruptsteuerung hinkriegst. Und kümmere dich erst dann um das Handshake.
Danke Karl für deine Hilfe, ich habe noch was zu fragen: wie sieht aus mit dem funktion ISR(USART_UDRE_vect) um die Daten zurrückt an der Hyperterminal zu schicken. MFG Jano
Jano wrote: > Danke Karl für deine Hilfe, > ich habe noch was zu fragen: wie sieht aus mit dem funktion > ISR(USART_UDRE_vect) um die Daten zurrückt an der Hyperterminal zu > schicken. Schick sie zurück. Ist doch nicht so schwer. Du weist doch wie man ein Zeichen ausgibt (bzw. hast eine Funktion dafür die das macht)
es ist so die zeichen sollen von Tastatur eigegeben und im Puffer der Controller gespeichert bis die letzte zeichen die wäre die Enter (cr) zeichen oder bis der Puffer voll nach diesem sollte die zeichen von Controller zu PC(Hyperterminal)geschickt. deswegen in deinem code verstehe ich nicht die Linereceived und die die function: void uart_puts( const char* OutText ) { strcpy( TBuf, OutText ); ... gib die Zeichen aus TBuf Zeichen für Zeichen aus. Dies kann zb. mit einer Interruptsteuerung passieren. Das erste Zeichen wird hier ausgegeben. Wenn es übertragen wurde, wird ein Interrupt ausgelöst, welcher zum Aufruf einer ISR führt, in der dann die weiteren Zeichen ausgegeben werden. ... Als Übung für den Leser absichtlich nicht implementiert, sondern die einfachere Variante unsigned char i = 0; while( TBuf[i] != '\0' ) usart_putc( TBuf[i] ); } MFG Jano
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.