Forum: Mikrocontroller und Digitale Elektronik UART - Zeichen empfangen


von tim (Gast)


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;
}

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

von Matthias L. (Gast)


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?

von Patrick (Gast)


Lesenswert?

Ich bin auch Anfänger, aber fehlt da nach "int main (void)" nicht die 
Schleife while(1){ ? Oder hab ich da was falsch verstanden?

von Matthias L. (Gast)


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

von Patrick (Gast)


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?

von Robert (Gast)


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

von Patrick (Gast)


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?

von tim (Gast)


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.

von Matthias L. (Gast)


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)

von tim (Gast)


Lesenswert?

aber das prob ist es, dass nach der ausgabe von > das programm net 
weiter läuft

von Matthias L. (Gast)


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)

von Matthias L. (Gast)


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
}

von Falk B. (falk)


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

von tim (Gast)


Lesenswert?

hmm verstehe. also diese zahl 3.6864 steht aufn quarzbauteil, die mit 
stk500 mitgeliefert wurde. das bedeutet doch quarzfrequenz von 3.6864 
MHz. hab ich recht?

von tim (Gast)


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;
}

von Johannes M. (johnny-m)


Lesenswert?

tim wrote:
> ...das bedeutet doch quarzfrequenz von 3.6864 MHz. hab ich recht?
Wenn das da drauf steht, dann ja. Allerdings läuft der Controller auch 
nur dann mit dem Quarztakt, wenn die Fusebits entsprechend gesetzt sind.

von Matthias L. (Gast)


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)

von tim (Gast)


Lesenswert?

ja, ich stecke hier noch fest. hab versuch zeichen einzugeben aber es 
passiert nix.

von Patrick (Gast)


Lesenswert?

Welchen Hyperterminal verwendest Du?
Wird denn das gesendete Zeichen ausgegeben?

von tim (Gast)


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.

von Patrick (Gast)


Angehängte Dateien:

Lesenswert?

Probier mal den im Anhang. Der ist viel Konfortabler.

Bei mir hat das mit dem Windows Terminal auch nie funktioniert.

von tim (Gast)


Lesenswert?

vielen dank. es hat geklappt. aber es ist wirklich kömisch dass mit dem 
hyperterminal net fkt.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.