PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Über RS232 etwas senden



MechMac
14.08.2010, 21:07
Hallo,

ich habe ein Pollin Evaluationboard 2.01 mit einem ATMEGA 644.

Mein Problem:

Ich bekomme es nicht hin mit der RS232 Schnittstelle etwas zu senden.
Habe einige Beispiele ausprobiert, aber es klappt nichtmal das Init der Schnittstelle.

Hat jemand ein Beispielprogramm, mit dem ich einen String oder auch nur ein einzelnes Zeichen senden kann?

Mfg, Andreas

walterk
14.08.2010, 21:26
Hallo,

mit diesen Zeilen habe ich ein einzelnes Zeichen vom PC an den µC geschickt, den ASCII Code des Zeichens an den LEDs vom PortC ausgegeben und dann wieder auf den PC zurückgeschickt.

Hardware: RN-Board1.4, Atmega32
Baudrate 9600, 8N1

Hoffe, dir geholfen zu haben

Walter



#include <avr/io.h>
#define F_CPU 8000000UL
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>


int main(void){


UBRRH = 0;
UBRRL = 51;

UCSRB = (1<<RXEN) | (1<<TXEN);

UCSRC |= (1<<URSEL) | (3<<UCSZ0);



DDRC = 0xff;

unsigned char a;
_delay_ms(2000);



while(1){
while((UCSRA & (1<<RXC))){

a = UDR;
PORTC = ~a;
_delay_ms(3000);

UDR = a;
_delay_ms(3000);
}
}

}

MechMac
14.08.2010, 21:34
Leider gibt es wie auch schon bei den anderen Programmen unzählige Fehlermeldungen beim Compilieren.

../Test.c:23: error: 'UBRRH' undeclared (first use in this function)
../Test.c:24: error: 'UBRRL' undeclared (first use in this function)
...
...

Das geht dann so weiter. Als könne er damit nix anfangen. Irgendetwas fehlt ihm.


So sieht mein Kopf aus:



#include <avr/io.h>
#ifndef F_CPU
/* Definiere F_CPU, wenn F_CPU nicht bereits vorher definiert
(z.B. durch Übergabe als Parameter zum Compiler innerhalb
des Makefiles). Zusätzlich Ausgabe einer Warnung, die auf die
"nachträgliche" Definition hinweist */
#warning "F_CPU war noch nicht definiert, wird nun mit 16000000 definiert"
#define F_CPU 16000000UL /* Quarz mit 16.0000 Mhz */
#endif
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>



Fehlt da noch etwas?

Gruß, Andreas

walterk
14.08.2010, 21:47
Bin selber relativ neu hier.

Kannst du meinen Bespielcode fehlerfrei übersetzen?

mfg Walter

MechMac
14.08.2010, 21:52
Nein bei mir funktioniert dein Programm nicht, AVR kann es nicht kompilieren.

Zwei der Fehler habe ich in meinem letzten Post genannt.

Ich versuche gerade herauszufinden, woher diese Fehler kommen. Bisher hab ich noch nichts gefunden.

Gruß, Andreas



EDIT:
Da kommen noch zahlen zwischen.
also statt:



UCSRB = ( (1<<RXEN)|(1<<TXEN) );


muss ich schreiben:


UCSR0B = ( (1<<RXEN0)|(1<<TXEN0) );


So werden es schon mal weniger Fehler :-)
Aber alles habe ich noch nicht behoben...

walterk
14.08.2010, 22:16
Ok, der Atmega32 hat auch wie der 644 nur einen USART, will aber den einen nicht als Null addressiert haben.

Habe mich vor einem Jahr mit der seriellen Datenübertragung zwischen PC und µC beschäftigt und diese Seite hat mir dabei geholfen:

http://www.tschallener.net/info/index.php/usart-ohne-interrupt-atmega32-in-c.html

mfg Walter

Slein
15.08.2010, 10:06
Hi MechMac!

Das Problem ist, dass die bei Atmel die Namen einiger Register und Bits geändert haben beim 644 um mehrere Uart in einem Controller adressieren zu können.
Der 644p z.B. hat zwei davon. Daher auch die 0 am Ende oder mittendrin für die 1. Schnittstelle. Im Datenblatt sind die Register der einzelnen UART vollständig benannt.

Es gibt auch einen "migration guide" vom ATmega32 zum ATmega644.
Der ist allerdings auch nicht wirklich eindeutig an ein paar Stellen:
http://www.atmel.com/dyn/resources/prod_documents/doc8001.pdf

edit:
Die Schnittstelle muss in den asynchronen mode initialisert werden, weiß nicht mehr genau, ob der meg32 das auch so wollte.

Tabellen für die Baudraten bei diversen Taktfrequenzen, inkl. Fehler:
http://www.wormfood.net/avrbaudcalc.php



// ****** init debug serial output
void initDBGser(void) {
// --- set UART baud rate to 115200 @ 14,7456 MHz
unsigned int baud = 7;
UBRR0H = (unsigned char) (baud>>8);
UBRR0L = (unsigned char) baud;

// --- init
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);

return;
}

// ****** send byte
void DBGsertxbyte(uint8_t btmp) {
// --- wait for empty tx buffer
while ( !(UCSR0A & (1<<UDRE0)) );
// --- put data into UDR, starts transmission too
UDR0 = btmp;

return;
}

oberallgeier
15.08.2010, 11:09
... Atmel die Namen einiger Register und Bits geändert haben beim 644 ... 644p z.B. hat zwei davon ...Es gibt mehrere 644-Varianten. Das ist natürlich etwas gefährlich.

Ich habe mehrere docs zur "644"er Familie:
2593M–A VR–08/07 für den ATmega644/V (Preliminary) - 1 UART (UART0)
8011M–A VR–08/09 für ATmega164P/324P/644P - 2 USART’s, USART0 und USART1
8272A–A VR–01/10 für 164A/164PA/324A/324PA/644A/644PA/1284/1284P - das Neueste - 2 USART’s, USART0 und USART1

MechMac, Du musst unbedingt das für Deinen aktuell verwendeten Controller passende Datenblatt nehmen, und natürlich auch die entsprechende io.h - sonst gehts schief. Das hast Du ja schon gesehen.

MechMac
15.08.2010, 16:40
Danke für die Antworten, ich habe es nun hinbekommen.

Gruß, Andreas

oberallgeier
15.08.2010, 19:32
Hallo Andreas,

... ich habe es nun hinbekommen ...Bitte schreib doch kurz, woran es gelegen hat. Es gibt sicher Mitleser, die daraus lernen könnten.

MechMac
15.08.2010, 19:54
Nun ja, es lag an drei Dingen.

1. In meinen Bezeichnern fehlten die Nummern, welche bestimmen welche Schnittstelle ich nun ansteuern möchte.
Also statt UCSRB dann UCSR0B usw..

2. Ob das nun ein Fehler war oder nicht weiß ich nicht.
Ich habe aus


UCSR0C = (3<<UCSZ00); // 8-Bit character length

folgendes gemacht


UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);


Leider kenne ich mich mit C noch nicht so gut aus, als dass ich dazu etwas kluges sagen könnte. Aber ich vermute mal das es etwas mit der Konfiguration der Schnittstelle zu tun hat.


Und das dritte Problem bestand darin, dass die Baud-Rate nicht so ganz passte. Was wiederum wohl mit der Frequenz des Quarzes zu tun hat. Aus diversen Brocken habe ich mir dann etwas zusammenkopiert, welches die Werte für UBRR0H und UBRR0L berechnet:


#define UART_BAUD_RATE 19200L
#define UART_BAUD_CALC(UART_BAUD_RATE,F_CPU) ((F_CPU)/((UART_BAUD_RATE)*16L)-1L)

//[..]
//[..]
//[..]

int main(void){
UBRR0H = (uint8_t) (UART_BAUD_CALC(UART_BAUD_RATE,16000000)>>8);
UBRR0L = (uint8_t) UART_BAUD_CALC(UART_BAUD_RATE,16000000)
//[..]
//[..]
}


Gruß, Andreas