mikrocontroller.net

Forum: Compiler & IDEs Handshake problem


Autor: Jano (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,
ich habe ein kleine Code gecshrieben für ein ATmega16. mit meiner Code 
will ich die Daten  zwischen die PC und die Controller austauchen und es 
soll mit Hardware handshanke gemacht werden. für die Handshake habe ich 
die Pin 3 und 4 der PORTD der Controller als RTS und CTS gewählt die 
sind zur MAX232 verbunden.

Die sache ist so: das Programm functionniert einigemasse ganz gut aber 
in der sende Richtung von Mikrocontroller zur PC, die Daten sind 
unendlich gesendet und das ist das Problem ich wollte gerne das die 
daten nur ein mal gesendet werden.

hier ist meine Code bitte schauen Sie die und helfen Sie mir bitte das 
Problem zu lösen
MFG
Jano

int main(void)
{
   unsigned char c;

   DDRD = 0xFF;          // PORT D als Ausgang
   PORTD = 0x08;         // 4.Pin des PORTD eischalten um das CTS 
anzusprechen (empfangt Bedingung im seit der controller)
   uart_init();
   sei();               // Freigabe aller Interrupt : Enable USART 
Interrupt

   //uart_puts("hello world!\r\n\r\n");

   /*while(1)
   {
      // Poll
      //c = uart_getdata();



      // Echo
      //uart_putdata(c);
   }*/

   return 0;
}

void uart_init(void)

/******************************************************************
 Function: Uart_init()
 Purpose: Initialise UART and set baudrate
 Input: baudrate
 Returns: none
 ******************************************************************/

{


  UCSRB |= (1<<TXEN) |(1<<RXEN) |(1<<RXCIE) |(1<<TXCIE)|(1<<UDRIE);  // 
tx/rx enable
    UCSRC |= (1<<URSEL)|(3<<UCSZ0); 
// Asynchron 8N1

#if F_CPU < 2000000UL && defined(U2X)
    UCSRA |= (1<<U2X);   /* improve baud rate error by using 2x clk */
    UBRRL = (F_CPU / (8UL * UART_BAUD)) - 1;
#else
    UBRRL = (F_CPU / (16UL * UART_BAUD)) - 1;
#endif
}




ISR(USART_RXC_vect)
{
  for ( g_idx=0; g_idx < MAX_BUFFER_SIZE; g_idx++ ){

  while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
    {
  }
    c=UDR;
   if (c == '\r'){
   return;
   }
   else
   Buf[g_idx]=c;    //Daten im Puffer laden
}
  PORTD=0x04;
  return;
}


ISR(USART_UDRE_vect)
{
  int n;
  n = g_idx;
  g_idx = 0;
  for ( g_idx=0; g_idx < n; g_idx++ )
  {
  c = Buf[g_idx];

  while (!(UCSRA & (1<<UDRE)))// Warten bis senden möglich
  {

  }

  UDR=c;


  }
   UCSRB &= ~UDRIE;


  PORTD= 0X08;         //Senden im seit der PC ein: die daten können von 
PC gesendet und im controller empfangen werden
  return;
}

Autor: Rahul Der trollige (rahul)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ISR(USART_UDRE_vect)
{
  static int n = 0;
  if (n<=g_idx)
  {
    UDR = Buf[g_idx];
  }
  else 
  {
    UCSRB &= ~UDRIE;
    PORTD= 0X08;         //Senden im seit der PC ein: die daten können von
PC gesendet und im controller empfangen werden
  }
}

So gehört das.

Autor: Jano (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke Rahul,
mit deine Hilfe bin ich ein schritte weiter gekommen aber es ist noch 
nicht was ich genau wollte. das programm liefert mir nur ein byte 
zurrück und zwar das letzte eingegebene byte. Ich will gerne alle byte 
die ich eingegeben habe wieder zurrückt haben und in die selbe reihen 
folge (FIFO).
kann jemand mir sagen wie ich das machen kann.
danke
MFG
jano

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deine Empfangsroutine ist genauso Schwachsinn.

Du hast anscheinend noch nicht verstanden, worum es in
der ISR geht.
Die ISR wird aufgerufen wenn ein Zeichen empfangen wurde.
Es ist daher sinnlos in der ISR nochmal abzufragen, ob ein
Zeichen empfangen wurde. Das wurde es nämlich, ansonsten wäre
die ISR nie aufgerufen worden.
In der ISR behandelst du dann dieses eine empfangene Zeichen
und gehst wieder aus der ISR raus. Beim nächsten Zeichen, das
empfangen wird, wird die ISR dann erneut aufgerufen.
Es ist daher völliger Schwachsinn in der ISR in einer Schleife
drauf zu warten, dass eine bestimmte Anzahl an Zeichen empfangen
werden. Für jedes empfangene Zeichen wird deine ISR aufgerufen,
die bearbeitet dieses eine Zeichen, zb. indem es das Zeichen
an den Empfangsbuffer hinten dranhängt oder indem sie feststellt
(weil das empfangene Zeichen ein '\n' war) dass damit die
Eingabe abgeschlossen ist. Und damit hat sichs dann für die ISR,
mehr tut sie nicht, insbesondere wartet die ISR nicht darauf, dass
irgendwelche weitere Bedingungen eintreten.

Autor: Jano (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Karl für die Hinweisen.
ich habe mein code nochmal geschrieben und ich dachte es sollte 
functionnieren
aber es geht immer nicht.
bitte schauen sie meine code und helfen sie mir mein programm im reihe 
zu kriegen bitte.
MFG
jano


//
// Datei uart.c
// MCU: Atmega16
//
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>


  /* ATmega with one USART */
 #define ATMEGA_USART
 #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
 #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
 #define UART0_STATUS   UCSRA
 #define UART0_CONTROL  UCSRB
 #define UART0_DATA     UDR
 #define UART0_UDRIE    UDRIE

 /*Size of the circular receive buffer, must be power of 2*/
 #ifndef UART_RX_BUFFER_SIZE
 #define UART_RX_BUFFER_SIZE 32
 #endif

/*Size of the circular Transmit buffer, must be power of 2*/
 #ifndef UART_TX_BUFFER_SIZE
 #define UART_TX_BUFFER_SIZE 10
 #endif

 /*high byte error return code of uart_getc()*/
 #define UART_NO_DATA     0x0100

// CHECK F_CPU WITH HARDWARE OSZILLATOR SETTING !!!!
#define F_CPU 1000000UL
#define UART_BAUD 9600

/*
 *  module global variables
 */
int g_idx;
int p_idx;
int MAX_BUFFER_SIZE;
MAX_BUFFER_SIZE=UART_TX_BUFFER_SIZE;
unsigned char Buf[UART_TX_BUFFER_SIZE]; //Empfang Buffer
unsigned char TBuf[UART_TX_BUFFER_SIZE];// Sende Buffer
int tmp = 0;
unsigned char c;

void uart_init(void);
unsigned int uart_getdata(void);
//unsigned char uart_getc(void);
void uart_putdata(unsigned char c);
//int uart_putc(unsigned char c);
void uart_puts (char *s);

int main(void)
{
   unsigned char c;

   DDRD = 0XFF;     // PORT D als Ausgang
   PORTD = 0x08;   // 4.Pin des PORTD eischalten um das CTS anzusprechen 
(empfangt Bedingung für die controller)

   uart_init();
   sei();
   uart_puts("hello world!\r\n\r\n");

   while(1)
   {
      // Poll
      c = uart_getdata();

      // Funny conversion

     /************************************************************
     This converion ist only use to convert the alphabetic letter
     and they will be return als echo to the screen
     ************************************************************/

      //if (c >= 'a' && c <= 'z')
       //  c += 'A' - 'a';
      //else if (c >= 'A' && c <= 'Z')
        // c += 'a' - 'A';

      // Echo
      uart_putdata(c);
   }

   return 0;
}

void uart_init(void)

/******************************************************************
 Function: Uart_init()
 Purpose: Initialise UART and set baudrate
 Input: baudrate
 Returns: none
 ******************************************************************/

{


  UCSRB |= (1<<TXEN) |(1<<RXEN) |(1<<RXCIE);  // tx/rx enable
    UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron 8N1

#if F_CPU < 2000000UL && defined(U2X)
    UCSRA |= (1<<U2X);   /* improve baud rate error by using 2x clk */
    UBRRL = (F_CPU / (8UL * UART_BAUD)) - 1;
#else
    UBRRL = (F_CPU / (16UL * UART_BAUD)) - 1;
#endif
}


ISR(USART_RXC_vect)
{
  c = UDR;
}


ISR(USART_UDRE_vect)
{
 p_idx = tmp;
 if (p_idx <= g_idx)
 {
   UDR = TBuf[p_idx];
   tmp++;
 }
 else
 {
   UCSRB &= ~UDRIE;
 }
 return;
}

void uart_putdata(unsigned char c)
{
   int n = g_idx;
   g_idx = 0;

   while (g_idx == n);  // fertig mit senden
    {
   PORTD = 0x08;     // CTS Pin der controller ist wieder ein: sie kann 
wieder die Daten empfangen
   return;          //  zurrückt zur Hauptprogramm
  }

/***************************************************************
 Die Daten werden im Empfangt Puffer geholt und im Transmitter
  Puffer gespeichert damit das sie werden byte pro byte geholt
  und gesendet
****************************************************************/
  c = Buf[g_idx];
  TBuf[g_idx] = c;
    g_idx++;
    UCSRB |= (1<<UDRIE);

}


unsigned int uart_getdata(void)
{
  g_idx = 0;
  while(g_idx != MAX_BUFFER_SIZE) //Das Empfang Puffer ist nicht voll
  {
    if(c == '\r')                 // letzte zeichen: zurrückt zur 
Hauptprogramm
     {
    return;
   }
  else
   {
    Buf[g_idx] = c; // Zeichen im Empfang puffer laden bis der Puffer 
voll ist
    g_idx++;
   }

  }
   PORTD = 0x04;  // der Puffer ist voll die Controller kann keine daten 
mehr empfangen
   return;       // also CTS ausschalten und RTS freischalten damit der 
Controller kann die daten senden
 }

Autor: Jano (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,
kann jemand mir helfen?
danke

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jano wrote:

> ISR(USART_RXC_vect)
> {
>   c = UDR;
> }

Das wiederrum ist nun wieder etwas zuwenig Arbeit für die
ISR.

Die ISR soll das Zeichen empfangen und zb. in den Buffer
stellen. Gleichzeitig überwacht die ISR, welches Zeichen
empfangen wurde, um der Hauptschleife in main() mitteilen
zu können, dass eine Zeile empfangen wurde.
volatile unsigned char LineReceived;

...

ISR( USART_RXC_vect )
{
  char c;

  // Hole das Zeichen von der USART
  c = UDR;

  // war das ein '\n', wenn ja dann teile der main() mit,
  // das eine Zeile empfangen wurde und zur Bearbeitung ansteht
  if( c == '\n' ) {
    Buf[g_idx] = '\0';   // Die Zeile für einen String korrekt abschliessen
    LineReceived = 1;    // Das gloable Flag setzen
    g_idx = 0;           // Beim nächsten empfangenen Zeichen wieder vorne
                         // im String speichern
  }

  else {
     // Die Zeile ist noch nicht zuende, speichere das Zeichen im
     // Buffer an der nächsten freien Stelle.
     // Hier fehlt noch die Fehlerbehandlung, was zu tun ist, wenn
     // der Buffer voll ist und nichts mehr Platz hat.
     Buf[g_idx] = c;
     g_idx++;
  }
}

...

void uart_puts( const char* OutText )
{
  strcpy( TBuf, OutText );

  ... gib die Zeichen aus TBuf Zeichen für Zeichen
      aus. Dies kann zb. mit einer Interruptsteuerung
      passieren. Das erste Zeichen wird hier ausgegeben.
      Wenn es übertragen wurde, wird ein Interrupt ausgelöst,
      welcher zum Aufruf einer ISR führt, in der dann die
      weiteren Zeichen ausgegeben werden.

  ... Als Übung für den Leser absichtlich nicht implementiert, sondern
      die einfachere Variante

  unsigned char i = 0;
  while( TBuf[i] != '\0' )
    usart_putc( TBuf[i] );
}

int main()
{
  ..

  LineReceived = 0;
  g_idx = 0;

  while( 1 ) {

    if( LineReceived ) {    // Wenn eine Zeile komplett empfangen
                            // wurde, dann bearbeite sie ....

      LineReceived = 0;
                            // zb. indem sie einfach zurückgeschickt
                            // wird
      uart_puts( Buf );
    }
  }
}

Jetzt brauchst du nur noch das Handshake einbauen:
Wenn der Empfangsbuffer droht voll zu werden, dann teilst
du mit der Handshake Leitung dem PC mit, mal kurzzeitig
das Senden zu unterlassen. Jetzt musst du dir noch was
überlegen, wann der PC wieder zu senden anfangen darf.
Aber schau zu erst mal, dass du die Interruptsteuerung
hinkriegst. Und kümmere dich erst dann um das Handshake.

Autor: Jano (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Karl für deine Hilfe,
ich habe noch was zu fragen: wie sieht aus mit dem funktion 
ISR(USART_UDRE_vect) um die Daten zurrückt an der Hyperterminal zu 
schicken.
MFG
Jano

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jano wrote:
> Danke Karl für deine Hilfe,
> ich habe noch was zu fragen: wie sieht aus mit dem funktion
> ISR(USART_UDRE_vect) um die Daten zurrückt an der Hyperterminal zu
> schicken.

Schick sie zurück. Ist doch nicht so schwer. Du weist doch
wie man ein Zeichen ausgibt (bzw. hast eine Funktion dafür
die das macht)

Autor: Jano (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
es ist so die zeichen sollen von Tastatur eigegeben und im Puffer der 
Controller gespeichert bis die letzte zeichen die wäre die Enter (cr) 
zeichen oder bis der Puffer voll nach diesem sollte die zeichen von 
Controller zu PC(Hyperterminal)geschickt. deswegen in deinem code 
verstehe ich nicht die Linereceived und die die function:

void uart_puts( const char* OutText )
{
  strcpy( TBuf, OutText );

  ... gib die Zeichen aus TBuf Zeichen für Zeichen
      aus. Dies kann zb. mit einer Interruptsteuerung
      passieren. Das erste Zeichen wird hier ausgegeben.
      Wenn es übertragen wurde, wird ein Interrupt ausgelöst,
      welcher zum Aufruf einer ISR führt, in der dann die
      weiteren Zeichen ausgegeben werden.

  ... Als Übung für den Leser absichtlich nicht implementiert, sondern
      die einfachere Variante

  unsigned char i = 0;
  while( TBuf[i] != '\0' )
    usart_putc( TBuf[i] );
}

MFG
Jano

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.