hmm, ich sehe bei Dir tatsächlich keine main-Funktion, die muß aber in jedem Programm vorhanden sein..
MfG Volker
Hallo!
Ich habe hier ein Programm für die serielle Schnittstelle nur leider kann ich es nicht übersetzen, auch wenn ich allen code rauskommentiere. Es erscheint diese Fehlermeldung:
Meine Suchen im Forum ergaben, dass ich vergessen habe eine Datei im Makefile zu linken. Nur welche?Code:Linking: main.elf avr-gcc -mmcu=atmega32 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o -std=gnu99 -Wundef -MMD -MP -MF .dep/main.elf.d main.o --output main.elf -Wl,-Map=main.map,--cref -lm c:/programme/winavr-20070525/bin/../lib/gcc/avr/4.1.2/../../../../avr/lib/avr5/crtm32.o: In function `__vectors': ../../../../../avr-libc-1.4.6/crt1/gcrt1.S:51: undefined reference to `main' make: *** [main.elf] Error 1
Das ist mein Code:Danke,Code:///////////////////////////////////////////////////////////////////// // Arios: Serial Interface functions // ///////////////////////////////////////////////////////////////////// // Author: Johannes Neumann // // Date of completion: **.**.**** // ///////////////////////////////////////////////////////////////////// // Defines ////////////////////////////////////////////////////////// #include <avr/interrupt.h> #include <avr/io.h> //#include <avr/signal.h> #include <string.h> #define cReadBufferSize 32 #define cWriteBufferSize 512 #define cBlockung 1 #define cNonBlocking 0 #define cTXComplete 1; #define cTXNotComplete 0; // Variables //////////////////////////////////////////////////////// volatile unsigned int TXComplete; volatile unsigned int WritePointer0 = 0, WritePointer1 = 0; volatile unsigned int ReadPointer0 = 0, ReadPointer1 = 0; volatile unsigned char ReadBuffer[cReadBufferSize]; volatile unsigned char WriteBuffer[cWriteBufferSize]; // Init ///////////////////////////////////////////////////////////// void RS232_init(long unsigned int baudrate) { UCSRA = 0x00; UCSRB = (1 << RXCIE) | (1 << RXEN); UCSRC = (1 << UCSZ1) | (1 << UCSZ0) | (1 << URSEL); UBRRH = (((F_CPU/baudrate) >> 4) - 1) >> 8; UBRRL = (((F_CPU/baudrate) >> 4) - 1) & 0xFF; TXComplete = cTXComplete; } // Send ///////////////////////////////////////////////////////////// int RS232_send(char *c, int blocking) { int i; for (i=0; i< strlen(c);i++) { if ((cWriteBufferSize + WritePointer1 - WritePointer0) % cWriteBufferSize > (cWriteBufferSize - 2)) { if (blocking) { while((cWriteBufferSize + WritePointer1 - WritePointer0) % cWriteBufferSize > (cWriteBufferSize - 2)); } else return i; } TXComplete = cTXComplete; asm("cli"); WriteBuffer[WritePointer1++] = c[i]; if (WritePointer1 > cWriteBufferSize - 1) WritePointer1 = 0; asm("sei"); UCSRB = (1<<TXEN) | (1<<UDRIE); } return i; } // Receive ////////////////////////////////////////////////////////// int RS232_receive(char *c, int length, int blocking) { int i; for (i=0; i<length; i++) { if (ReadPointer0 == ReadPointer1) { if (blocking) while(ReadPointer0 == ReadPointer1); else return i; } c[i] = ReadBuffer[ReadPointer1++]; if (ReadPointer1 > cReadBufferSize - 1) ReadPointer1 = 0; } return length; } // Complete? //////////////////////////////////////////////////////// int RS232_WritingComplete(void) { return TXComplete; } // Count of Bytes in ReadBuffer ///////////////////////////////////// int RS232_GetBytesInReadBuffer(void) { return (cReadBufferSize + ReadPointer1-ReadPointer0) % cReadBufferSize; } // Count of Bytes in WriteBuffer //////////////////////////////////// int RS232_GetBytesInWriteBuffer(void) { return (cWriteBufferSize + WritePointer1-WritePointer0) % cWriteBufferSize; } // Interrupt for Reading //////////////////////////////////////////// SIGNAL (SIG_UART_RECV) { ReadBuffer[ReadPointer0++] = UDR; if (ReadPointer0 > cReadBufferSize) ReadPointer0 = 0; } // Interrupt for writing Data into UDR ////////////////////////////// SIGNAL (SIG_UART_DATA) { UDR = WriteBuffer[WritePointer0++]; if (WritePointer0 < cWriteBufferSize - 1) WritePointer0 = 0; if (WritePointer0 == WritePointer1) UCSRB = (1<<TXEN) | (1<<TXCIE); } // Interrupt for setting Complete-Flag ////////////////////////////// SIGNAL (SIG_UART_TRANS) { UCSRB = (1<<RXCIE) | (1<<RXEN); TXComplete = cTXComplete; }
Bääääär
hmm, ich sehe bei Dir tatsächlich keine main-Funktion, die muß aber in jedem Programm vorhanden sein..
MfG Volker
Meine kleine Seite
http://home.arcor.de/volker.klaffehn
http://vklaffehn.funpic.de/cms
neuer Avatar, meine geheime Identität
Hallo Bääääär,
danke für's abtippen. Bei Arexx gibt es nämlich immer noch keinen Code.
Im übrigen gibt es beim Empfang von Daten einen kleinen Schönheitsfehler mit evl. fatalen Folgen.
(Ich beziehe mich hier auf deine Funktionsnamen und nicht die aus Band II zum Asuro)
Wie stellt die Funktion RS232_receive() fest, dass der Buffer leer ist? Klar, mit "if (ReadPointer0 == ReadPointer1)"
Aber was passiert im Empfangs-Interrupt SIGNAL (SIG_UART_RECV)?
Dort wird der ReadPointer0 gandenlos mit ++ erhöht wenn ein Zeichen ankommt. "ReadBuffer[ReadPointer0++] = UDR;" (Natürlich wieder auf 0 wenn er zu groß wird.)
Wenn man nun genau so viele Zeichen empfängt wie der RX-Buffer groß ist, steht der ReadPointer0 also wieder an der gleichen Position wie der ReadPointer1.
Und was nun? Da ist doch der Buffer leer sagt die RS232_receive()-Funktion!!!
Wenn ich in deinem Code den auskommentierten #include wieder aufnehme und ein #define für F_CPU anlege und ein kleines main so wie:
int main (void)
{
while (1);
return 0;
}
reinschreibe, kann ich fehlerfrei übersetzen.
Hast du im Makefile dasCode:///////////////////////////////////////////////////////////////////// // Arios: Serial Interface functions // ///////////////////////////////////////////////////////////////////// // Author: Johannes Neumann // // Date of completion: **.**.**** // ///////////////////////////////////////////////////////////////////// #define F_CPU 8000000 // Defines ////////////////////////////////////////////////////////// #include <avr/interrupt.h> #include <avr/io.h> #include <avr/signal.h> #include <string.h> #define cReadBufferSize 32 #define cWriteBufferSize 512 #define cBlockung 1 #define cNonBlocking 0 #define cTXComplete 1; #define cTXNotComplete 0; // Variables //////////////////////////////////////////////////////// volatile unsigned int TXComplete; volatile unsigned int WritePointer0 = 0, WritePointer1 = 0; volatile unsigned int ReadPointer0 = 0, ReadPointer1 = 0; volatile unsigned char ReadBuffer[cReadBufferSize]; volatile unsigned char WriteBuffer[cWriteBufferSize]; // Init ///////////////////////////////////////////////////////////// void RS232_init(long unsigned int baudrate) { UCSRA = 0x00; UCSRB = (1 << RXCIE) | (1 << RXEN); UCSRC = (1 << UCSZ1) | (1 << UCSZ0) | (1 << URSEL); UBRRH = (((F_CPU/baudrate) >> 4) - 1) >> 8; UBRRL = (((F_CPU/baudrate) >> 4) - 1) & 0xFF; TXComplete = cTXComplete; } // Send ///////////////////////////////////////////////////////////// int RS232_send(char *c, int blocking) { int i; for (i=0; i< strlen(c);i++) { if ((cWriteBufferSize + WritePointer1 - WritePointer0) % cWriteBufferSize > (cWriteBufferSize - 2)) { if (blocking) { while((cWriteBufferSize + WritePointer1 - WritePointer0) % cWriteBufferSize > (cWriteBufferSize - 2)); } else return i; } TXComplete = cTXComplete; asm("cli"); WriteBuffer[WritePointer1++] = c[i]; if (WritePointer1 > cWriteBufferSize - 1) WritePointer1 = 0; asm("sei"); UCSRB = (1<<TXEN) | (1<<UDRIE); } return i; } // Receive ////////////////////////////////////////////////////////// int RS232_receive(char *c, int length, int blocking) { int i; for (i=0; i<length; i++) { if (ReadPointer0 == ReadPointer1) { if (blocking) while(ReadPointer0 == ReadPointer1); else return i; } c[i] = ReadBuffer[ReadPointer1++]; if (ReadPointer1 > cReadBufferSize - 1) ReadPointer1 = 0; } return length; } // Complete? //////////////////////////////////////////////////////// int RS232_WritingComplete(void) { return TXComplete; } // Count of Bytes in ReadBuffer ///////////////////////////////////// int RS232_GetBytesInReadBuffer(void) { return (cReadBufferSize + ReadPointer1-ReadPointer0) % cReadBufferSize; } // Count of Bytes in WriteBuffer //////////////////////////////////// int RS232_GetBytesInWriteBuffer(void) { return (cWriteBufferSize + WritePointer1-WritePointer0) % cWriteBufferSize; } // Interrupt for Reading //////////////////////////////////////////// SIGNAL (SIG_UART_RECV) { ReadBuffer[ReadPointer0++] = UDR; if (ReadPointer0 > cReadBufferSize) ReadPointer0 = 0; } // Interrupt for writing Data into UDR ////////////////////////////// SIGNAL (SIG_UART_DATA) { UDR = WriteBuffer[WritePointer0++]; if (WritePointer0 < cWriteBufferSize - 1) WritePointer0 = 0; if (WritePointer0 == WritePointer1) UCSRB = (1<<TXEN) | (1<<TXCIE); } // Interrupt for setting Complete-Flag ////////////////////////////// SIGNAL (SIG_UART_TRANS) { UCSRB = (1<<RXCIE) | (1<<RXEN); TXComplete = cTXComplete; } int main (void) { while (1); return 0; }
SRC += asuro.c
auskommentiert? Ist bei mir aber egal. Es geht in beiden Fällen.
Lieber Asuro programieren als arbeiten gehen.
Ich habe ein komplette neues Makefile gemacht.
Stimmt, du hast Recht. Er muss das Empfangen abbrechen, wenn blocking nicht ktiviert ist. Macht er aber bis jetzt nicht. Dann hat das Buch Band II aber auch diesen netten Fehler. Die Funktion sollte dann wohl so aussehen:
Damit nicht weiter empfangen wird, wird die Funktion abgebrochen. Fertsch. So sollte es doch gehen.Code:// Receive ////////////////////////////////////////////////////////// int RS232_receive(char *c, int length, int blocking) { int i; for (i=0; i<length; i++) { if (ReadPointer0 == ReadPointer1) { if (blocking) while(ReadPointer0 == ReadPointer1); else { return i; abort; } } c[i] = ReadBuffer[ReadPointer1++]; if (ReadPointer1 > cReadBufferSize - 1) ReadPointer1 = 0; } return length; }
Warum eine main Funktion? Das Macht doch keinen Sinn. Es handelt sich dabei um ein Modul. Und dafür braucht man doch keine Main Funktion. Einen Header muss ich noch machen, vielleicht gehts ja dann auch...
Danke,
Bääääär
//EDIT: Ich habe grade festgestellt, dass es kein abort; gibt. Was könnte man sonst nehmen?
Eventuell so?
Code:// Send ///////////////////////////////////////////////////////////// int RS232_send(char *c, int length, int blocking) { int i=0; for (i=0; i < length;i++) { if ((cWriteBufferSize + WritePointer1 - WritePointer0) % cWriteBufferSize > (cWriteBufferSize - 2)) { if (blocking) { while((cWriteBufferSize + WritePointer1 - WritePointer0) % cWriteBufferSize > (cWriteBufferSize - 2)); } else { goto End; } } TXComplete = cTXComplete; asm("cli"); WriteBuffer[WritePointer1++] = c[i]; if (WritePointer1 > cWriteBufferSize - 1) WritePointer1 = 0; asm("sei"); UCSRB = (1<<TXEN) | (1<<UDRIE); } End:return i; }
warum schmeisst du das "abort;" nicht einfach raus, nach return i; wird eh nix mehr aus dieser Funktion ausgefuehrt.
Und wo ist der Sinn anstatt return i; zu schreiben einen Sprung zu machen um dann return i; auszufuehren?
Hallo Bääääär,
oh je, du möchtest also nur ein Modul schreiben. Dann glaube ich, dass in deinem Makefile noch etwas nicht in Ordnung ist. Bis jetzt macht es auf alle Fälle ein 'normales' Hex-File, und das benötigt ein main() (ging ja bei mir). Genau dies wird auch im Band II beschrieben, aber tatsächlich mit mehreren C-Dateien. Wobei aber trotzdem in genau einer Datei das main() drinn stecken muss.
Möglicherweise hast du da einen 'kleinen' aber wichtigen Unterschied zum Muster aus dem Band II übersehen.
Wenn du so etwas wie die Forum-LIB zum Asuro machen möchtest sind 'etwas' andere Befehle im Makefile auszuführen.
Ob dein Code für eine funktionierende Empfangsfunktion gut ist, habe ich mir jetzt noch nicht genau angesehn.
Keine Aussage
Mit einem Goto geht es schon, aber da hat fluchtpunkt irgendwie recht, dass das nicht so schön ist.
Was (meiner Meinung) dafür spricht ist, dass eine 'Endebehandlung' dann aber nur genau einmal geschrieben werden muss. OK, hier ist nur das return vorhanden, aber manchmal muss da etwas mehr hin, und dann braucht man immer nur an genau einer Stelle Fehler zu korrigieren.
Im Übrigen kannst du ein break; benutzen. Dies bricht genau eine loopende Eben, also bei dir die For-Schleife ab.
Lieber Asuro programieren als arbeiten gehen.
@fluchtpunkt: Achso, mir war nicht klar, dass nach return; Schluss ist mit der entsprechenden Funktion. Dann hast du natürlich Recht.
@Sternthaler: Ja, mit Main() gehts auch. Vielleicht kannst du mir bei Gelegenheit erklären, wie man ein korrektes Modul macht. Für mich ist C eine komplette Neuheit, ich bin es von Borland Delphi gewöhnt, dass es reicht eine Quelltextdatei zu includieren und dass sich der Compiler dann um das Linken kümmert. Hier scheint das alles etwas verzweigter (+verzwickter) zu sein
@all: Bevor ich das jetzt korrekt machen kann, sollten aber erstmal die Funktionen gehen. Tun sie aber noch nicht. Meine RS232_send sendet immer nur das erste Zeichen eines Strings und die Empfangsfunktion kann ich noch nicht testen, solange das Senden nicht geht. Vielleicht findet jemand den Fehler, ich finde ihn nicht. K.A. ob es schon am Befüllen des Buffers liegt oder am Senden. Ich kann mir ja nichts ausgeben lassen...
hmm. Mal Sehen. Danke erstmal für eure Hilfe!
Bääääär
Hallo Bääääär,
da du die Sendefunktion RS232_send() ja (bestimmt) aus Band II hast, kann es auch noch am Aufruf dieser Funktion liegen.
Stellt du bitte nochmal das komplette Programm hier zur Verfügung.
Lieber Asuro programieren als arbeiten gehen.
Oki. Also ich glaube wir verstehen auch was verschiedenes unter "Modul" ich meinte eins wie es im Buch beschrieben ist, und das muss man ja auch gar nicht compillieren... .
Hier ist der Code von serial.h:
Das ist der Code von "Serial\serial.c":Code:#ifndef _SERIAL_H #define _SERIAL_H #define cReadBufferSize 32 // Size of ReadBuffer #define cWriteBufferSize 128 // Size of WriteBuffer #define cBlockung 1 #define cNonBlocking 0 #define cTXComplete 1 #define cTXNotComplete 0 #include "Serial\serial.c" void RS232_init(long unsigned int baudrate); int RS232_send(char *c, int length, int blocking); int RS232_receive(char *c, int length, int blocking); int RS232_WritingComplete(void); int RS232_GetBytesInReadBuffer(void); int RS232_GetBytesInWriteBuffer(void); int RS232_GetWriteBufferSize(void); int RS232_GetReadBufferSize(void); int RS232_ReadBufferClear(void); int RS232_WriteBufferClear(void); #endifUnd das ist mein Programm:Code:///////////////////////////////////////////////////////////////////// // Arios: Serial Interface functions // ///////////////////////////////////////////////////////////////////// // Author: Johannes Neumann // // Date of completion: **.**.**** // ///////////////////////////////////////////////////////////////////// // Defines ////////////////////////////////////////////////////////// #include <avr/interrupt.h> #include <avr/io.h> // Variables //////////////////////////////////////////////////////// volatile unsigned int TXComplete; volatile unsigned int WritePointer0 = 0, WritePointer1 = 0; volatile unsigned int ReadPointer0 = 0, ReadPointer1 = 0; volatile unsigned char ReadBuffer[cReadBufferSize]; volatile unsigned char WriteBuffer[cWriteBufferSize]; // Init ///////////////////////////////////////////////////////////// void RS232_init(long unsigned int baudrate) { UCSRA = 0x00; UCSRB = (1 << RXCIE) | (1 << RXEN); UCSRC = (1 << UCSZ1) | (1 << UCSZ0) | (1 << URSEL); UBRRH = (((F_CPU/baudrate) >> 4) - 1) >> 8; UBRRL = (((F_CPU/baudrate) >> 4) - 1) & 0xFF; TXComplete = cTXComplete; } // Send ///////////////////////////////////////////////////////////// int RS232_send(char *c, int length, int blocking) { int i=0; for (i=0; i < length; i++) { if ((cWriteBufferSize + WritePointer1 - WritePointer0) % cWriteBufferSize > (cWriteBufferSize - 2)) { if (blocking) { while((cWriteBufferSize + WritePointer1 - WritePointer0) % cWriteBufferSize > (cWriteBufferSize - 2)); } else return i; } TXComplete = cTXNotComplete; asm("cli"); WriteBuffer[WritePointer1++] = c[i]; if (WritePointer1 > cWriteBufferSize - 1) WritePointer1 = 0; asm("sei"); UCSRB = (1<<TXEN) | (1<<UDRIE); } return i; } // Receive ////////////////////////////////////////////////////////// int RS232_receive(char *c, int length, int blocking) { int i; TXComplete = cTXNotComplete; for (i=0; i<length; i++) { if (ReadPointer0 == ReadPointer1) { if (blocking) while(ReadPointer0 == ReadPointer1); else return i; } c[i] = ReadBuffer[ReadPointer1++]; if (ReadPointer1 > cReadBufferSize - 1) ReadPointer1 = 0; } return length; } // Complete? //////////////////////////////////////////////////////// int RS232_WritingComplete(void) { return TXComplete; } // Count of Bytes in ReadBuffer ///////////////////////////////////// int RS232_GetBytesInReadBuffer(void) { return (cReadBufferSize + ReadPointer1-ReadPointer0) % cReadBufferSize; } // Count of Bytes in WriteBuffer //////////////////////////////////// int RS232_GetBytesInWriteBuffer(void) { return (cWriteBufferSize + WritePointer1-WritePointer0) % cWriteBufferSize; } // Return WriteBufferSize /////////////////////////////////////////// int RS232_GetWriteBufferSize(void) { return cWriteBufferSize; } // Return ReadBufferSize //////////////////////////////////////////// int RS232_GetReadBufferSize(void) { return cReadBufferSize; } // Return if ReadBuffer ist Empty /////////////////////////////////// int RS232_ReadBufferClear(void) { // kommt noch... } // Return if WriteBuffer ist Empty ////////////////////////////////// int RS232_WriteBufferClear(void) { // kommt noch... } // Interrupt for Reading //////////////////////////////////////////// SIGNAL (SIG_USART_RECV) { ReadBuffer[ReadPointer0++] = UDR; if (ReadPointer0 > cReadBufferSize) ReadPointer0 = 0; } // Interrupt for writing Data into UDR ////////////////////////////// SIGNAL (SIG_USART_DATA) { UDR = WriteBuffer[WritePointer0++]; //printf(WriteBuffer[WritePointer0++]); if (WritePointer0 < cWriteBufferSize - 1) WritePointer0 = 0; if (WritePointer0 == WritePointer1) UCSRB = (1<<TXEN) | (1<<TXCIE); } // Interrupt for setting Complete-Flag ////////////////////////////// SIGNAL (SIG_USART_TRANS) { UCSRB = (1<<RXCIE) | (1<<RXEN); TXComplete = cTXComplete; }Obwohl ich nur einmal sende, wird unendlich mal ein "H" gesendet. (also der erste Buchstabe des Strings). Es muss also irgendwas mit den Interrupts zu tun haben.Code:#include <Arios\serial.h> #include <stdio.h> int main (void) { int i=0; RS232_init(9600); RS232_send("Hallo Welt!\n\r", 14, cNonBlocking); return 0; }
Sorry, ich hatte oben vergessen, den Code beizufügen...
Vielen Dank,
Bääääär
Lesezeichen