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


von USART Uli (Gast)


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...

???
1
int main(void)
2
{
3
  char datasend[]="L1Value30\0";
4
  //char empfangen[10];
5
6
  DDRD|=(1<<PD6);
7
  DDRB=0xff;
8
9
  UBRRH=0;
10
  UBRRL=12;
11
  UCSRA|=(1<<U2X);
12
  UCSRB|=(1 << TXEN) | (1<<RXEN);
13
14
  uart_clear();
15
  uart_puts(datasend);
16
  //uart_gets(empfangen, sizeof(empfangen));
17
  //uart_puts(empfangen);
18
19
  while(1)
20
  {
21
    delay(1);
22
    PORTD^=(1<<PD6);
23
  }
24
  return 0;
25
}
26
27
void delay(unsigned char sekunden)
28
{
29
  for(char i=0; i<=(sekunden*100);i++)
30
    _delay_ms(10);
31
};
32
33
34
void uart_putc(unsigned char c)
35
{
36
    while (!(UCSRA & (1<<UDRE)));  
37
    UDR = c;                     
38
    
39
};
40
 
41
void uart_puts (char *s)
42
{
43
    while (*s)
44
    {  
45
        uart_putc(*s);
46
        s++;
47
    _delay_ms(5);
48
    }
49
  
50
};
51
52
int uart_getc (void)
53
{
54
  while(!(UCSRA & (1<<RXC)));
55
  return(UDR);
56
};
57
58
void uart_clear (void)
59
{
60
  unsigned char a;
61
  for (char c=0;c<10;c++)
62
  {  
63
    a = UDR;
64
  }
65
};

von Stefan B. (stefan) Benutzerseite


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?

von USART Uli (Gast)


Lesenswert?

Hallo Stefan,

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

von USART Uli (Gast)


Angehängte Dateien:

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. ???

1
// Defines an den Controller und die Anwendung anpassen
2
 
3
#define F_CPU 2000000L                  // Systemtakt in Hz
4
#define F_PWM 70                       // PWM-Frequenz in Hz
5
#define PWM_STEPS 256                   // PWM-Schritte pro Zyklus(1..256)
6
#define PWM_PORT PORTB                  // Port für PWM
7
#define PWM_DDR DDRB                    // Datenrichtungsregister für PWM
8
 
9
// ab hier nichts ändern, wird alles berechnet
10
 
11
#define T_PWM (F_CPU/(F_PWM*PWM_STEPS)) // Systemtakte pro PWM-Takt
12
 
13
#if (T_PWM<(93+5))
14
    #error T_PWM zu klein, F_CPU muss vergrösst werden oder F_PWM oder PWM_STEPS verkleinert werden
15
#endif
16
 
17
// includes
18
 
19
#include <stdint.h>
20
#include <string.h>
21
#include <avr/io.h>
22
#include <avr/interrupt.h>
23
24
void uart_puts (char *s);
25
void uart_putc(unsigned char c);
26
int uart_getc(void);
27
void uart_clear(void);
28
void uart_gets( char* Buffer, uint8_t MaxLen );
29
 
30
// globale Variablen
31
 
32
volatile uint8_t pwm_setting[8]; // Einstellungen für die einzelnen PWM-Kanäle
33
34
char empfangen[10];
35
36
 
37
// Timer 1 Output COMPARE A Interrupt
38
 
39
ISR(TIMER1_COMPA_vect) 
40
{
41
    static uint8_t pwm_cnt=0;
42
    uint8_t tmp=0;
43
 
44
    OCR1A += (uint16_t)T_PWM;
45
        
46
    if (pwm_setting[0] > pwm_cnt) tmp |= (1<<0);
47
    if (pwm_setting[1] > pwm_cnt) tmp |= (1<<1);
48
    if (pwm_setting[2] > pwm_cnt) tmp |= (1<<2);
49
    if (pwm_setting[3] > pwm_cnt) tmp |= (1<<3);
50
    if (pwm_setting[4] > pwm_cnt) tmp |= (1<<4);
51
    if (pwm_setting[5] > pwm_cnt) tmp |= (1<<5);
52
    if (pwm_setting[6] > pwm_cnt) tmp |= (1<<6);
53
    if (pwm_setting[7] > pwm_cnt) tmp |= (1<<7);
54
    PWM_PORT = tmp;                         // PWMs aktualisieren
55
    if (pwm_cnt==(uint8_t)(PWM_STEPS-1))
56
        pwm_cnt=0;
57
    else
58
        pwm_cnt++;
59
}
60
61
62
int main(void) {
63
 
64
    //uint8_t kommando, geraet, kanal, wert;
65
  // PWM einstellen
66
    
67
    PWM_DDR = 0xFF;         // Port als Ausgang
68
    
69
    // Timer 1 OCRA1, als variablem Timer nutzen
70
 
71
    TCCR1B = 1;             // Timer läuft mit vollem Systemtakt
72
    TIMSK |= (1<<OCIE1A);   // Interrupt freischalten
73
   
74
  // USART Initialisierung
75
    UBRRH=0;
76
  UBRRL=12;
77
  UCSRA|=(1<<U2X);
78
  UCSRB|=(1 << TXEN)|(1<<RXEN)|(1<<RXCIE);
79
  uart_putc('N');
80
81
  sei(); // Interrupts gloabl einschalten
82
  while(1)
83
  {
84
    if( (UCSRA & (1<<RXC)) )
85
    {
86
      cli();
87
      //PORTB &=~(1<<PB4);
88
      uart_gets(empfangen, sizeof(empfangen));
89
      uart_puts(empfangen);
90
      pwm_setting[empfangen[2]-'0']=(empfangen[3]-'0')*25;
91
      for(int i=0; i<=7; i++)
92
      {
93
        uart_putc((char)pwm_setting[i]);
94
      }
95
      sei();
96
    }
97
98
 
99
    return 0;
100
}

von holger (Gast)


Lesenswert?

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

Ändern in

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

Ohne Interruptroutine sollte man einen Interrupt
nie freigeben ;)

von USART Uli (Gast)


Lesenswert?

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

Vielen Dank holger, jetzt klappts!!! :D

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.