PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RS232 senden mit AtMega128



Mr Bean
22.11.2007, 18:38
Hallo

Ich habe schon einen Thread im Hardwareforum, denke aber dass es hier besser passt.
Und zwar hab möchte ich meinen Mega128 dazu bringen etwas auf der RS232 auszugeben. Ich hab die Schnittstelle 1 verwendet. Einen Pegelwandler hab ich auch auf meiner Platine. Hab die Schnittstelle auch schon einemal mit einem Mega8 zum laufen bekommen. Nur mit dem Mega 128 will Sie noch nicht richtig.
Kabel verwende ich ein 1 zu 1. Habe volgenden Code verwendet:


#include <avr/io.h>
#define F_CPU 12000000L
#include <util/delay.h>


#define BAUD 9600L
#define MYUBRR F_CPU/16/BAUD-1

void USART_Init(unsigned int UBRR)
{
UBRR1H = (unsigned char)(ubrr>>8);
UBRR1L = (unsigned char) ubrr;
UCSR1B = (1<<RXEN)|(1<<TXEN);
UCSR1C = 0b00000110;
}


int main(void)
{

USART_Init (MYUBRR);


while (!(UCSR1A & (1<<UDR1E))) //warten bis Senden möglich
{
}


UDR1 = 'H'; //schreibt das Zeichen x auf die Schnittstelle
_delay_ms(100);
UDR1 = 'A';
_delay_ms(100);
UDR1 = 'L';
_delay_ms(100);
UDR1 = 'L'; //schreibt das Zeichen x auf die Schnittstelle
_delay_ms(100);
UDR1 = 'O';
_delay_ms(100);

return 0;
}

Vielleicht hat mir ja einer noch einen guten Tipp mit dem ich die Schnittstelle schnell zum laufen bekomme.
Ach ja, wenn ich mit dem Multimeter (hab leider kein Speicheroszi) an Rxd und Txd messe dann hab ich -7 und -9V. Der Pegelwandler scheint also zu funktionieren. Beim Hyperterminal hab ich soweit denke ich alles richtig eingestellt (in diesem Fall 8N1 und 9600Baud).
Vielen Dank schon mal für eure Hilfe!

Grüße!!
Bean

Hubert.G
22.11.2007, 20:32
Bekommst du da keine Fehler beim compilieren, mit dem müsstest du den Fehler aber selbst auch finden.

Mr Bean
23.11.2007, 06:42
Nein hab da keinen Fehler bekommen (0 errors 0warnings). Welcher Satz sollte mir denn angezeigt werden?

MFG

Bean

sast
23.11.2007, 06:54
Woher kennt denn dein Kompiler "ubrr"?
Hast du nicht den ganzen Code geschickt?
Wenn du keine Fehler bekommst, könnte es vielleicht sein, dass du gar nicht das richtige File übersetzt?

sast

edit: C und C++ sind case sensitiv!!

Hubert.G
23.11.2007, 10:26
Wenn du die zwei Fehler ausbesserst funktioniert der Code, aber zuerst sollte dein Compiler richtig funktionieren.

Mr Bean
23.11.2007, 18:35
Hallo

Ich hab das jetzt gleich noch einmal getestet mi de selben Ergebniss. Ich hab folgenden Code (hab bei dem alten noch #include uart.h eingefügt):

#include <avr/io.h>
#define F_CPU 12000000L
#include <util/delay.h>
#include <uart.h>


#define BAUD 9600L
#define MYUBRR F_CPU/16/BAUD-1

void USART_Init(unsigned int UBRR)
{
UBRR1H = (unsigned char)(ubrr>>8);
UBRR1L = (unsigned char) ubrr;
UCSR1B = (1<<RXEN)|(1<<TXEN);
UCSR1C = 0b00000110;
}


int main(void)
{

USART_Init (MYUBRR);


while (!(UCSR1A & (1<<UDR1E))) //warten bis Senden möglich
{
}


UDR1 = 'H'; //schreibt das Zeichen x auf die Schnittstelle
_delay_ms(100);
UDR1 = 'A';
_delay_ms(100);
UDR1 = 'L';
_delay_ms(100);
UDR1 = 'L'; //schreibt das Zeichen x auf die Schnittstelle
_delay_ms(100);
UDR1 = 'O';
_delay_ms(100);

return 0;
}

Und bekomme nachdem ich auf Build gegangen bin folgende Meldungen:

Build started 23.11.2007 at 19:21:20
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex USART.elf USART.eep || exit 0
c:\WinAVR\bin\avr-objcopy.exe: there are no sections to be copied!

AVR Memory Usage
----------------
Device: atmega128

Program: 4316 bytes (3.3% Full)
(.text + .data + .bootloader)

Data: 8 bytes (0.2% Full)
(.data + .bss + .noinit)


Build succeeded with 0 Warnings...


An was liegt das? Wenn ihr sagt dass ich vielleicht nicht den richtigen File Compiliere, wei kann ich das kontrollieren? Was stimmt sonst noch nicht an dem Code? Also auf der seriellen Schnittstelle an meinem PC empfange ich noch nichts... 8-[

Vielen Dank schon mal!!

Grüße!!

Bean

izaseba
23.11.2007, 18:58
#define MYUBRR F_CPU/16/BAUD-1


Das ist irgendwie falsch


#define MYUBRR (F_CPU/(BAUD*16L))-1
So sieht es besser aus...

Mr Bean
23.11.2007, 19:22
Also hab nun noch ein paar Sachen verändert:


#include <avr/io.h>
#define F_CPU 12000000L
#include <util/delay.h>
#include <uart.h>


#define BAUD 9600L
#define UBRR (F_CPU/(BAUD*16L))-1

void USART_Init(unsigned int UBRR)
{
UBRR1H = (unsigned char)(UBRR>>8);
UBRR1L = (unsigned char) UBRR;
UCSR1B = (1<<RXEN)|(1<<TXEN);
UCSR1C = 0b00000110;
}


int main(void)
{

USART_Init (UBRR);


while (!(UCSR1A & (1<<UDR1E))) //warten bis Senden möglich
{
}


UDR1 = 'H'; //schreibt das Zeichen x auf die Schnittstelle
_delay_ms(100);
UDR1 = 'A';
_delay_ms(100);
UDR1 = 'L';
_delay_ms(100);
UDR1 = 'L'; //schreibt das Zeichen x auf die Schnittstelle
_delay_ms(100);
UDR1 = 'O';
_delay_ms(100);

return 0;
}



Nach wie vor wird das Programm ohne Fehler Compiliert und auch ohne zu murren vom Pony in den Controller geladen... Aber auf dem Hyper Terminal sehe ich leider noch nichts... :-(

Aber trotzdem Danke für die Hilfeversuche!!

Grüße!!

Bean

izaseba
23.11.2007, 19:53
Naja,
Dir ist hoffentlich aber klar, daß Du:
1.


while (!(UCSR1A & (1<<UDR1E)))
vor jedem Zeichen machen musst

2.


_delay_ms(100);
nicht unbedingt 100 ms sein muß

3. Keine Endloschleife in Deinem Programm vorhanden ist

Warum übergibst Du UBRR an die Initfunktion ?

Ich füge mal ein paar Schnipsel, die bei mir mit M128 100% Funktionieren, ist zwar für UART0 , sollte aber egal sein




#define BAUDSELECT (F_CPU/(BAUD*16L))-1

void init_uart(void){
UBRR0L = BAUDSELECT;
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
}

senden tue ich mit solcher Funktion


void sendmessage(Message *message){
uint8_t a;
for (a=0;a<message->laenge;a++){
while(!(UCSR0A&(1<<UDRE0)));
UDR0 = message->text[a];
}


Vielleicht hilft es Dir weiter.

Gruß Sebastian

P.S.


while (!(UCSR1A & (1<<UDR1E))) //warten bis Senden möglich
{
}

Hier stinkt was, UDR1E gibt es nicht, es heißt UDRE1, sicher, daß es keine Fehler gibt ?

Hubert.G
23.11.2007, 20:41
Mit was kompilierst du denn, bei deinem muss irgend was oberfaul sein. Meiner hat aufgeschrien beim ubrr und UDR1E.

Mr Bean
25.11.2007, 22:02
Nabend!

Also ich hab die serielle Schnittstelle jetzt mit diesem Code dazu gebracht das Zeichen "H" an meinen PC zu senden:

#include <avr/io.h>
#define F_CPU 12000000L
#include <util/delay.h>
#define BAUD 9600L
#define UBRR (F_CPU/(BAUD*16L))-1



int main(void)

{
UBRR1L = (unsigned char) UBRR;
UCSR1B = (1<<RXEN)|(1<<TXEN);
UCSR0C = (1<<UCSZ11)|(1<<UCSZ10);
//while (!(UCSR1A & (1<<UDRE))) //warten bis Senden möglich
//{
//}
UDR1 = 'H'; //schreibt das Zeichen x auf die Schnittstelle
_delay_ms (100);
return 0;
}
Ich hab aber immernoch ein paar offene Fragen. Ich hab die while Schleife jetzt weggelassen da im Debugger das Programm immer im zweiten Anlauf in dieser Schleife hängen geblieben ist. Meine Frage hierzu ist warum muss ich diese Schleife jedesmal aufrufen bevor ich ein Zeichen senden will? Es sollte doch eigentlich einmal zu Beginn des Sendevorgangs ausreichen oder? Könnt ihr mir das bitte erklären? Dann frage ich mich noch warum ich eine Pause (in meinem Fall jetzt 100ms) brauch damit das ganze funktioniert. Ich weiß dass diese Pause bestimmt nicht so groß sein muss, aber wenn ich die Pause komplett weg lass kommt keine Datenübertragung zustande. Wie kurz die Pause im besten Fall sein kann hab ich noch nicht ausprobiert. Wäre schön wenn ihr mir diese Fragen noch beantworten könntet. Ansonsten noch einmal vielen Dank für die Hilfestellungen!! Ist echt klasse wenn am Ende mal wieder was funktioniert.

Grüße!!

Bean

izaseba
25.11.2007, 22:24
Hallo,
Hast Du mein Post oben gelesen , scheinbar nicht :-(?
zu Deinem _delay_ms(100) ?
Du hast ein Quarz von 12 Mhz und laut avr-libc beträgt die maximale Delayzeit damit


262.14 ms / F_CPU in MHz.
bei Dir also 21 mS.

Der debugger unterstützt auch manche Sachen nicht, das ist u.a. UART das
kann man auch unter known issues nachlesen.
Vertraue hier also nicht auf den Debugger sondern auf uns.

Antwort auf warum man UDRE1 pollen muß ist wohl ganz einfach.
Uart kann ja nur byteweise übertragen und nachdem man ihm sagt, es soll was senden muß man halt warten, bis es damit fertig ist und das steht halt im UDRE drin.

Und eine Endlosschleife ist immer noch nicht drin.

Ich kopiere Dir nochmal von oben was


void sendchar(char message){
while(!(UCSR1A&(1<<UDRE1)));
UDR1 = message;
}

jetzt sendest Du aus Deinem main Zeichen an die Funktion, etwa so


sendchar('H');
sendchar('a');
sendchar('l');
sendchar('l');
sendchar('o');


Gruß Sebastian

Mr Bean
25.11.2007, 22:34
Hey das ging ja schnell mit der Antwort!

Ja hast recht, die Endlosschleife ist immernoch nicht drin. Ich hab Deinen Beitrag schon gelesen. Und hab wenn ich mich nicht irre sogar auch etwas aus Deinen Codeschnipsel verwendet.
Tut mir Leid dass ich nicht alles gleich verwendet hab So wie ihr gesagt hatte. Hatte eben meine eigene Vorstellung wie das fuunktionieren sollte. 8-[ 8-[
Sehe ich das richtig dass wenn ich zum senden jedes Zeichen die whileschleife verwende ich die Pause nach jedem gesendeten Zeichen nichtmehr brauche? Dann ist mir nämlich mal wieder einiges klar... :-) Vielen Dank dafür. Ich muss halt noch viel lernen. Aber dank eurer Hilfe hat man immerwieder ein Erfolgserlebniss. [-o< [-o< [-o<
Dachte ich arbeite halt auch mal etwas mit dem Debugger, weil jedes mal das Programm in den Controller laden ging mir zu lang... :-)

Also denn in diesem Sinne!!

Gute Nacht!!

Bean

izaseba
25.11.2007, 22:53
Hey das ging ja schnell mit der Antwort!

Naja, wenn man nicht pennen kann, kriegt man so manches mit ;-)

Ja, debugger ist schon ganz gut, wenn man nur bedenkt, daß manches damit halt nicht geht.
Und ja, wenn Du UDRE prüfst brauchst Du auch keine Wartezeiten ;-)
Die Funktion, wie ich die geschrieben habe will auch etwas ausgebaut werden
aber sehe selber Klick (http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Senden_mit_dem_UART)
Arbeite Dich da mal durch, ist eine sehr gute Seite.



weil jedes mal das Programm in den Controller laden ging mir zu lang...
Womit lädst Du das Programm denn 8-[ normalerweise spricht mal hier von ein paar Sekunden, bei dem Miniprogramm bruchteile einer Sekunde :-k
Ich mach mir eher Gedanken um die Flashhäufigkeit O:)

Auch gute Nacht

Sebastian

Hubert.G
26.11.2007, 09:12
Also um die Flashhäufigkeit braucht man sich keine Gedanken machen, wenn man den Controller drei mal am Tag neu flasht, kann man das fast 10 Jahre lang machen. Ich glaube nicht das ich in 10 Jahren noch den selben Controller bearbeite wie jetzt.

Mr Bean
26.11.2007, 11:16
Hallo

Ich programmiere meinen Controller mit dem PonyProg über einen sehr einfachen seriellen ISP Programmer (sind nur ein paar Dioden, Widerstände und ein Transistor drauf). Das Programmieren des Programmteils ist eigentlich auch recht schnell, aber das Verify geht ewig.
Um die Flashhäufigkeit mach ich mir auch eher weniger Gedanken.

Hab meinen Mega8 schon zig mal programmiert, da ist auch noch nie ein Problem aufgetreten oder es waren vorher die Beinchen verbogen... :-)

MFG

Bean