UART - Zeichen empfangen

Gast #626343
Lesenswert?
• ▲
▼
Hi all,

ich fange an, mein atmel mega16 zu programmieren, und versuche dieses 
einfache programm, zu programmieren. aber es klappt bei der 
zeicheneingabe net. weist jemand vielleicht woran es liegt.

------------------------------------------------------------------------ 
---

#define FOSC 3686400 // Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1

#include <avr/io.h>

// USART initialisieren
void USART_Init(unsigned int ubrr)
{
  /* Set baud rate */
  UBRRH = (unsigned char) (ubrr >> 8);
  UBRRL = (unsigned char) ubrr;

  /* Enable receiver and transmitter */
  UCSRB = (1 << RXEN) | (1 << TXEN);

  /* Set frame format: 8data, 2stop bit */
  UCSRC = (1 << URSEL) | (1 << USBS) | (3 << UCSZ0);
}

// Zeichen senden
void USART_Transmit (unsigned char data)
{
  /* Wait for empty transmit buffer */
  while (! (UCSRA & (1 << UDRE) ) )
  ;
  /* Put data into buffer, sends the data */
  UDR = data;
}

// Zeichen empfangen
unsigned char USART_Receive (void)
{
  /* Wait for data to be received */
  while (! (UCSRA & (1 << RXC) ) )
  ;

  /* Get and return received data from buffer */
  return UDR;
}

int main (void)
{
  // Parameter definieren
  unsigned char temp;

  // Schnittstelle Initialisierung
  USART_Init (MYUBRR);

  // Hauptprogramm
  USART_Transmit ('>');

  temp = USART_Receive ();

  USART_Transmit (' ');

  USART_Transmit (temp);

  return 0;
}

------------------------------------------------------------------------ 
---
Gast #626346
Lesenswert?
• ▲
▼
1
#define FOSC 3686400L // Clock Speed  // das L ist wichtig
2
#define BAUD 9600
3
#define MYUBRR FOSC/16/BAUD-1
4
..
5
return 0;                              // wo springt er denn hier hin??

Sind die Einstellungen im Terminal auch korrekt?
Gast #626356
Lesenswert?
• ▲
▼
>nach "int main (void)" nicht die Schleife while(1){ ? Oder hab ich da was >falsch 
verstanden?

Naja ja.
Aber die muss nicht (gleich) hinter
1
int main (void)

deshalb ja meine Frage, wo er (der µC) bei
1
return 0;
 hinspringt
Gast #626358
Lesenswert?
• ▲
▼
Meiner Meinung nach müsste doch der Code so aufgebaut sein:
1
int main (void){
2
...
3
while(1){
4
//Was zu tun ist
5
}
6
return 0;

Der letzte Befehl meldet doch einfach 0 zurück und bricht dann main ab, 
oder?
Gast #626363
Lesenswert?
• ▲
▼
Hallo,

deine main wird exakt einmal durchlaufen. Also pack die USART Funktion 
in eine while (1) Schleife (oder eine for Endlosschleife), nicht jedoch 
die Initialisierung des USART. Mit return 0 im main springt der uC ins 
Nirvana, deine main darf das return also nie (!) erreichen!

Robert
Gast #626364
Lesenswert?
• ▲
▼
Konkret:
1
int main (void)
2
{
3
  // Parameter definieren
4
  unsigned char temp;
5

6
  // Schnittstelle Initialisierung
7
  USART_Init (MYUBRR);
8
while(1){
9
  // Hauptprogramm
10
  USART_Transmit ('>');
11

12
  temp = USART_Receive ();
13

14
  USART_Transmit (' ');
15

16
  USART_Transmit (temp);
17
}
18
  return 0;  //Never reached
19
}

Oder bin ich damit wirklich auf dem Holzweg?
Gast #626366
Lesenswert?
• ▲
▼
hallo beide.

--- Matthias L.
   wie so is der - UL - wichtig? wofür seht es? und den - return 0; 
anweisung - habe ich einfach eingebaut, da die main-fkt von typ int ist. 
das programm soll erstmal einmal durchlaufen, um die fkt zu testen, ob 
es richtig funktionert. deswegen gibst auch in diesem programm keine 
unendl. scheife.

---  Patrick
   ja. aber erst will ich nur alle fuktionen prüfen. später tue ich  die 
while-schleife ein.
Gast #626370
Lesenswert?
• ▲
▼
>wie so is der - UL - wichtig? wofür seht es?

Weil nach C-Standart der Compiler sonst mit 16bit arbeitet. Und wie 
lautet 3686400 in eine 16bit Zahl "gepresst"? Richtig: 16384.
Und du hast ja wohl kaum einen 16kHz Quartz dran, oder?

PS: die Quartzfrequenz von 3,6864MHz hab ich noch nie gehört..
(Muss aber nix heißen)
Gast #626375
Lesenswert?
• ▲
▼
>Oder bin ich damit wirklich auf dem Holzweg?

Nein. Passt schon. Da aber damit das return 0 NIE ausgeführt wird, kann 
man es auch weglassen, und das main als void deklarieren..

(Es folgt eine Warnung da nicht C-konform, die kann aber (als einzige 
Warnung) ignoriert werden)
Gast #626377
Lesenswert?
• ▲
▼
>aber das prob ist es, dass nach der ausgabe von > das programm net
>weiter läuft

Natürlich nciht, denn was macht dieses Programm:?
1
// Zeichen empfangen
2
unsigned char USART_Receive (void)
3
{
4
  /* Wait for data to be received */
5
  while (! (UCSRA & (1 << RXC) ) )
6
  ;
7

8
  /* Get and return received data from buffer */
9
  return UDR;
10
}
#626382
Lesenswert?
• ▲
▼
@ Robert (Gast)

>die Initialisierung des USART. Mit return 0 im main springt der uC ins
>Nirvana, deine main darf das return also nie (!) erreichen!

Quark. Sowohl der AVR mit GCC als auch z.B. der M16C mit Renesas 
Compiler springen aus Main in eine Endlosschleife. Also nix Nirvana!

MfG
Falk
Gast #626392
Lesenswert?
• ▲
▼
dieses programm soll einfach ein zeichen, das vom tastatur über 
hyperterminal eingegeben wird, nur empfangen zu ins programm 
zurückgeben.

>>>
// Zeichen empfangen
unsigned char USART_Receive (void)
{
  /* Wait for data to be received */
  while (! (UCSRA & (1 << RXC) ) )
  ;

  /* Get and return received data from buffer */
  return UDR;
}
Gast #626397
Lesenswert?
• ▲
▼
>dieses programm soll einfach ein zeichen, das vom tastatur über
>hyperterminal eingegeben wird, nur empfangen zu ins programm
>zurückgeben.

Soweit richtig. Aber ich meinte, das
1
  /* Wait for data to be received */
2
  while (! (UCSRA & (1 << RXC) ) );
sorgt dafür, dass du hier SOLANGE wartest, bis ein Zeichen KORREKT 
empfangen wurde..
(Deshalb kann er hier mehr oder weniger lange festhängen)
Gast #626423
Lesenswert?
• ▲
▼
hyperterminal von windows xp und die ausgabe vom zeichen > läuft alles 
in ordnung und dann hab ich versucht zeichen einzugeben. aber es ist nix 
passiert, wobei es so nur das gleiches zeichen auf dem terminal 
zurückgeben.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren