-         

Ergebnis 1 bis 1 von 1

Thema: AVR-->PC (RS232): Rx-Event kommt doppelt??

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    03.01.2004
    Ort
    Pottenstein
    Alter
    38
    Beiträge
    265

    AVR-->PC (RS232): Rx-Event kommt doppelt??

    Anzeige

    SMARTPHONES & TABLETS-bis zu 77% RABATT-Kostenlose Lieferung-Aktuell | Cool | Unentbehrlich
    Moin moin!

    Mal wieder das alte Thema: Kommunikation zwischen MC (in diesem Fall ATmega16) und PC (WinXP) über RS232.
    Dazu gab's hier schon einige Threads. In einem davon habe ich einen Code gefunden, der endlich mal keine zusätzlichen Treiberprogrämmchen, dlls oder sonstwelche Spielchen erfordert. Sondern einfach als Win32-Konsolenanwendung per MSDevStudio 6 kompiliert werden kann. Vor allem ohne den üblichen Overhead von Windowsprogrammen. Soweit so gut, der Code funktioniert und ich habe ihn der Übersicht halber auf das reduziert, was ich brauche, nämlich das Einlesen von Daten, die der ATmega16 per USART sendet (soll ein Datenlogger werden).

    Der AVR sendet testweise in seinem Programm nur einmal ein Telegramm von 10 bytes. Er hängt am STK500, benutzt also dessen 5V-Versorgung und den Spare-RS232-Port. Damit sendet er immer dann ein Telegramm, wenn ich den Resetknopf auf dem STK500 drücke.

    Jetzt zum Problem: Nachdem die 10 bytes empfangen worden sind, wird am COM-Port des PCs anscheinend das Event EV_RXCHAR noch einmal gesetzt. Aber ohne daß nochmal Daten empfangen worden wären. Die Ausgabe sieht so aus wie in dem angehängten Bild. Hier wurde zum Beispiel dreimal das Programm im AVR ausgeführt. Also wird dreimal das Telegramm empfangen, aber dann kommt immer noch eine Zeile, weil das Empfangsprogramm per Event nochmal in die ReadFile()-Schleife und damit auch zum printf() springt. Und ich habe keine Ahnung, wieso. Ich habe versucht, das Event an verschiedenen Stellen per ResetEvent() manuell zurückzusetzen (dazu auch beim Erzeugen des Events den Parameter MANUAL_RESET auf eins gesetzt), aber es kommt trotzdem wieder. COM_BUFFER_SIZE steht übrigens normalerweise auf 10, ich hatte es nur auf 11 gesetzt, um zu schauen, ob ich nicht versehentlich noch ein elftes Byte sende oder so... Aber mit 10 sieht es genauso aus.

    Hier ist der Code im AVR:

    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    volatile unsigned int auxcounter=0;
    
    unsigned char data[10]={0,1,2,3,4,5,6,7,8,9};
    
    void init(void) {
    	UBRRH=103>>8;
    	UBRRL=103;
    	UCSRB=(1<<TXEN);
    	UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
    }
    
    ISR(SIG_OVERFLOW0) {
    	auxcounter++;
    }
    
    void transmit(unsigned char *data) {
    	int k;
    	for(k=0;k<10;k++){
    		while(!(UCSRA & (1<<UDRE))) { };
    		UDR=data[k];
    	}
    }
    
    int main(void) {
    	
    	TIFR = (1<<TOV0);									//Enable timer overflow interrupt
    	TIMSK= (1<<TOIE0);									//Enable timer overflow interrupt
    	TCCR0= (1<<CS00)|(1<<CS02);							//Prescaler = 1024, Overflow 256
    	
    	init();
    	sei();
    	
    	//while(1) {
    	//	if (auxcounter>122) {							//305=5sec, 122=2sec
    			transmit(data);
    			//auxcounter=0;
    	//	}
    	//}
    	return 0;
    }

    Und hier der Code im PC (Win32-Konsolenprogramm in MSDevStudio6.0):

    Code:
    #include <windows.h>
    #include <stdio.h>
    
    #define COM_BUFFER_SIZE 11		// Read-Buffer-Size
    #define BD_RATE CBR_9600		// 9600 Baud
    
    int main (void)
    {
    	DCB           dcb;
    	BOOL          bRet      = true;
    	DWORD         dwRead    = 0;
    	DWORD         dwSetMask = EV_RXCHAR;
    	DWORD         dwEvtMask;
    	OVERLAPPED    o;
    	COMMTIMEOUTS  ct;
    	unsigned char data[COM_BUFFER_SIZE];
    
    	memset (&o, 0, sizeof (OVERLAPPED));								// Struktur mit 0en füllen
    	memset (&data, 0, sizeof (data));								// Struktur mit 0en füllen
    	o.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);					// einen Event setzten
    
    	HANDLE hCom = CreateFile ("COM5", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, &o);
    
    	dcb.DCBlength = sizeof(DCB);  // Laenge des Blockes MUSS gesetzt sein!
    	GetCommState (hCom, &dcb);    // COM-Einstellungen holen und aendern
    	dcb.BaudRate  = BD_RATE;      // Baudrate
    	dcb.ByteSize  = 8;            // Datenbits
    	dcb.Parity    = NOPARITY;     // Parität
    	dcb.StopBits  = ONESTOPBIT;   // Stopbits
    	SetCommState (hCom, &dcb);    // COM-Einstellungen speichern
    
    	GetCommTimeouts (hCom, &ct);
    	ct.ReadIntervalTimeout         = 2;		//1000 / BD_RATE * (dcb.ByteSize +(dcb.Parity == NOPARITY ? 0 : 1) + (dcb.StopBits == ONESTOPBIT ? 1 : 2)) * 2;
    	ct.ReadTotalTimeoutMultiplier  = 0;		// [ms] wird mit Read-Buffer-Size multipliziert
    	ct.ReadTotalTimeoutConstant    = 50;	// wird an ReadTotalTimeoutMultiplier angehängt
    	SetCommTimeouts (hCom, &ct);
    
    	SetupComm (hCom, 2*COM_BUFFER_SIZE, 2*COM_BUFFER_SIZE);						// Zwischenspeicher des serial-Drivers einstellen (für read und write):
    	SetCommMask (hCom, dwSetMask);															// Empfangssignale definieren
    
    	do {
    		WaitCommEvent (hCom, &dwEvtMask, &o);												// Event mit Empfangssignalen verknüpfen
    		if (WAIT_OBJECT_0 == WaitForSingleObject (o.hEvent, 2000)) {					// warten bis Event
    			bRet = ReadFile (hCom, &data, sizeof (data), &dwRead, NULL);
    			if (bRet) {
    				printf ("\nRxD %2d Byte(s):",dwRead);
    				for(int n=0;n<COM_BUFFER_SIZE;n++) printf("%4d",data[n]);
    				memset (&data, 0, sizeof (data));								// Struktur mit 0en füllen
    			}
    		}
    	}
    	while (1);
    
    	CloseHandle (hCom);     // COM schließen
    	CloseHandle (o.hEvent); // Event-Handle zurückgeben
    	return (0);
    }
    Hat jemand eine Idee, woran das liegen könnte? Ich komm einfach nicht drauf...

    Besten Dank,

    Nils
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken ausgabe.jpg  

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •