www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik USART: AVR via RS232 an PC Problem. AVR-Programm Reset beim Empfang von Daten!?


Autor: USART Uli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe ein eigenartiges Problem mit dem USART vom Tiny2313. Es dürfte 
sich dabei nicht um ein Baudraten-Problem handeln.

Und zwar folgendes: Der AVR sendet einfach nur einen String zum PC. 
Soweit so gut. Aber wenn ich jetzt einfach mal aus Spaß vom 
Terminalprogramm ein Zeichen oder String zum AVR sende, dann schickt er 
sofort den String "L1Value" wieder zurück.
Das verstehe ich aber nicht, normalerweise läuft doch das Programm in 
der Endlosschleife, und die Tx-funktion habe ich garnicht eingebunden! 
Wirklich sonderbar...

???
int main(void)
{
  char datasend[]="L1Value30\0";
  //char empfangen[10];

  DDRD|=(1<<PD6);
  DDRB=0xff;

  UBRRH=0;
  UBRRL=12;
  UCSRA|=(1<<U2X);
  UCSRB|=(1 << TXEN) | (1<<RXEN);

  uart_clear();
  uart_puts(datasend);
  //uart_gets(empfangen, sizeof(empfangen));
  //uart_puts(empfangen);

  while(1)
  {
    delay(1);
    PORTD^=(1<<PD6);
  }
  return 0;
}

void delay(unsigned char sekunden)
{
  for(char i=0; i<=(sekunden*100);i++)
    _delay_ms(10);
};


void uart_putc(unsigned char c)
{
    while (!(UCSRA & (1<<UDRE)));  
    UDR = c;                     
    
};
 
void uart_puts (char *s)
{
    while (*s)
    {  
        uart_putc(*s);
        s++;
    _delay_ms(5);
    }
  
};

int uart_getc (void)
{
  while(!(UCSRA & (1<<RXC)));
  return(UDR);
};

void uart_clear (void)
{
  unsigned char a;
  for (char c=0;c<10;c++)
  {  
    a = UDR;
  }
};

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
USART Uli wrote:

> Und zwar folgendes: Der AVR sendet einfach nur einen String zum PC.
> Soweit so gut. Aber wenn ich jetzt einfach mal aus Spaß vom
> Terminalprogramm ein Zeichen oder String zum AVR sende, dann schickt er
> sofort den String "L1Value" wieder zurück.
> Das verstehe ich aber nicht, normalerweise läuft doch das Programm in
> der Endlosschleife, und die Tx-funktion habe ich garnicht eingebunden!
> Wirklich sonderbar...

Meine Vermutung: Der AVR resettet zwischendurch wahrscheinlich ausgelöst 
durch deine Eingabe. Dadurch wird main() neu gestartet und auch der 
String gesendet (uart_puts()). Warum der Reset kommt muss ich mir 
ansehen/überlegen. Im Code sehe ich auf Anhieb keinen Hinweis. Hardware 
OK? Insbesondere Spannungsversorgung stabil, wenn der MAX232 (hast du 
einen?) arbeiten muss? Brownout-Fuse benutzt?

Autor: USART Uli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Stefan,

ich habe den Fehler gefunden. Es lag an der Verdrahtung vom Reset des 
Tinys.

Autor: USART Uli (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich muss das Thema wieder hoch holen, da ich wieder mit diesem Problem 
des reseten beim Empfang von Zeichen über USART habe.
Ich verwende diesmal ein anderes Program, aber Controller und seine 
Einstellungen sind gleich.
Das Programm bestet aus dem SoftPWM 
http://www.mikrocontroller.net/articles/Soft-PWM und einer kleinen USART 
Erweiterung, mit de rich die Känale steuere.
Weil ständig die pwm_setting[] nach dem Senden PC->µC auf ihren 
Anfangswert sprang, habe ich wieder an einen Reset gedacht und 
usart_putc('N') vor der Endlosschleife eingefügt, und siehe da, jedesmal 
wenn ich ein Zeichen vom PC sende erscheint zusätzlich ein N im 
Terminalprogramm!

Diesmal liegt es aber nicht an der Reset Verdrahtung (10k gegen Ub=5V).

Jetzt bin ich irgendwie ratlos. ???

// Defines an den Controller und die Anwendung anpassen
 
#define F_CPU 2000000L                  // Systemtakt in Hz
#define F_PWM 70                       // PWM-Frequenz in Hz
#define PWM_STEPS 256                   // PWM-Schritte pro Zyklus(1..256)
#define PWM_PORT PORTB                  // Port für PWM
#define PWM_DDR DDRB                    // Datenrichtungsregister für PWM
 
// ab hier nichts ändern, wird alles berechnet
 
#define T_PWM (F_CPU/(F_PWM*PWM_STEPS)) // Systemtakte pro PWM-Takt
 
#if (T_PWM<(93+5))
    #error T_PWM zu klein, F_CPU muss vergrösst werden oder F_PWM oder PWM_STEPS verkleinert werden
#endif
 
// includes
 
#include <stdint.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>

void uart_puts (char *s);
void uart_putc(unsigned char c);
int uart_getc(void);
void uart_clear(void);
void uart_gets( char* Buffer, uint8_t MaxLen );
 
// globale Variablen
 
volatile uint8_t pwm_setting[8]; // Einstellungen für die einzelnen PWM-Kanäle

char empfangen[10];

 
// Timer 1 Output COMPARE A Interrupt
 
ISR(TIMER1_COMPA_vect) 
{
    static uint8_t pwm_cnt=0;
    uint8_t tmp=0;
 
    OCR1A += (uint16_t)T_PWM;
        
    if (pwm_setting[0] > pwm_cnt) tmp |= (1<<0);
    if (pwm_setting[1] > pwm_cnt) tmp |= (1<<1);
    if (pwm_setting[2] > pwm_cnt) tmp |= (1<<2);
    if (pwm_setting[3] > pwm_cnt) tmp |= (1<<3);
    if (pwm_setting[4] > pwm_cnt) tmp |= (1<<4);
    if (pwm_setting[5] > pwm_cnt) tmp |= (1<<5);
    if (pwm_setting[6] > pwm_cnt) tmp |= (1<<6);
    if (pwm_setting[7] > pwm_cnt) tmp |= (1<<7);
    PWM_PORT = tmp;                         // PWMs aktualisieren
    if (pwm_cnt==(uint8_t)(PWM_STEPS-1))
        pwm_cnt=0;
    else
        pwm_cnt++;
}


int main(void) {
 
    //uint8_t kommando, geraet, kanal, wert;
  // PWM einstellen
    
    PWM_DDR = 0xFF;         // Port als Ausgang
    
    // Timer 1 OCRA1, als variablem Timer nutzen
 
    TCCR1B = 1;             // Timer läuft mit vollem Systemtakt
    TIMSK |= (1<<OCIE1A);   // Interrupt freischalten
   
  // USART Initialisierung
    UBRRH=0;
  UBRRL=12;
  UCSRA|=(1<<U2X);
  UCSRB|=(1 << TXEN)|(1<<RXEN)|(1<<RXCIE);
  uart_putc('N');

  sei(); // Interrupts gloabl einschalten
  while(1)
  {
    if( (UCSRA & (1<<RXC)) )
    {
      cli();
      //PORTB &=~(1<<PB4);
      uart_gets(empfangen, sizeof(empfangen));
      uart_puts(empfangen);
      pwm_setting[empfangen[2]-'0']=(empfangen[3]-'0')*25;
      for(int i=0; i<=7; i++)
      {
        uart_putc((char)pwm_setting[i]);
      }
      sei();
    }

 
    return 0;
}

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>  UCSRB|=(1 << TXEN)|(1<<RXEN)|(1<<RXCIE);

Ändern in

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

Ohne Interruptroutine sollte man einen Interrupt
nie freigeben ;)

Autor: USART Uli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh man was ein Fehler! Kommt wohl durch copy & paste. :-/

Vielen Dank holger, jetzt klappts!!! :D

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.