Forum: Mikrocontroller und Digitale Elektronik Atmega16L @ gcc [Prg. läuft nur Debug Mode]


von luke (Gast)


Lesenswert?

Hallo.

Meine ersten Gehversuche mit einem AVR werfen zahlreiche Fragen auf. Auf 
einige findet sich eine Antwort auf andere nicht.
Der letztere Umstand zwingt mich hier um Rat zu bitten.

Ich benutze folgendes:

AVRStudio 4 @ gcc (neueste Version) sowie einen Atmega16L.

Das folgende Programm liest eine Zeichenfolge über RS232 ein, extrahiert 
daraus eine Zahl mit Hilfe von sscanf() und schreibt diese in das OCR0 
Register des Timer0, um die Tastrate der Fast-PWM zu stellen.

Das Ganze funktioniert allerdings nur im Debug-Modus.
Wenn ich das Programm direkt, also nich im D-Modus, im Controller laufen 
lasse. So stelle ich fest (Debug-LED), dass kein Sprung in 
"ISR(USART_RXC_vect)" stattfindet, nachdem ich ein Zeichen zum µC sende.

Woran kann das liegen?

Vielen Dank & Grüße
luke
1
/* . */
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include "C:/Program Files/Atmel/WinAVR/avr/include/stdio.h"
6
7
#define F_CPU       7372800UL
8
9
#define BAUD        9600UL
10
#define UBRR_BAUD   ((F_CPU/(16UL*BAUD))-1)
11
12
volatile char intflg = 0;
13
volatile unsigned char rx_buf[6];
14
volatile unsigned char n = 0;
15
char test = 0;
16
unsigned int druck = 0;
17
unsigned char cdruck = 0;
18
19
20
// Funktionsdeklarationen
21
void pwm_conf( void);
22
void uart_init(void);
23
24
25
26
27
int main(void)
28
{
29
    uart_init();
30
  pwm_conf();
31
32
    sei();
33
34
35
36
    while(1)
37
  {
38
39
    if( (intflg & 0b00000001) & 0b00000001)
40
    {
41
42
      sscanf( rx_buf,"D%i.", &druck);
43
44
      druck = (druck*0.0254);
45
      cdruck = (unsigned char)druck;
46
         while ( !( UCSRA & (1<<UDRE)) );
47
      UDR = cdruck;
48
      OCR0 = cdruck;
49
      PORTB ^= (1<<PB4); 
50
      intflg = ( 0b11111110 & intflg);
51
    }
52
    
53
  }
54
        
55
}
56
57
58
// Interrupt wird ausgelöst sobald neue Daten im USART-Empfangspuffer liegen
59
ISR(USART_RXC_vect)
60
{
61
  unsigned char buffer;
62
    // Daten aus dem Puffer lesen ...
63
    buffer = UDR;
64
  rx_buf[n]=buffer; n++;
65
  if( buffer == '.'){ n= 0; intflg = ((intflg & 0b111111111) | 0b00000001);}
66
  
67
}
68
69
70
// Konfiguriert Timer0 für den Fast-PWM Modus
71
void pwm_conf( void)
72
{
73
//           +++------- Clock Source
74
  TCCR0 = 0b01111001;
75
//         +  +---------- Waveform Generation Mode
76
77
78
  OCR0 = 120; // Vergleichsregister. Wenn wert erreicht -> Ausgang TOGGLE
79
80
//Port D pins as input
81
82
  DDRD=0x00;
83
84
//Enable internal pull ups
85
86
  PORTD=0xFF;
87
88
//Set PORTB1 pin as output
89
90
  DDRB=0xFF;
91
92
  OCR0 = 0;
93
}
94
95
96
97
98
void uart_init(void)
99
{
100
    // Baudrate einstellen (Normaler Modus)
101
    UBRRH = (unsigned char) (UBRR_BAUD>>8);
102
    UBRRL = (unsigned char) (UBRR_BAUD & 0x0ff);
103
104
    // Aktivieren des Empfängers, des Senders und des "Daten empfangen"-Interrupts
105
    UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
106
107
    // Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
108
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
109
}

von Hc Z. (mizch)


Lesenswert?

luke schrieb:
1
> while ( !( UCSRA & (1<<UDRE)) );
Diese Zeile im Hauptprogramm ist eine unendliche Schleife.  Denn UDRE 
wird zwar beim Empfang eines Zeichens gesetzt.  Da aber der Rx-Interrupt 
aktiv ist, wird bei Zeichen sofort die Interruptroutine angesprungen, 
dort UDR ausgelesen und damit UDRE gelöscht -- und bis die UDRE-Abfrage 
im Hauptprogramm ausgeführt wird, ist UDRE längst wieder 0.

Es gibt auch sonst noch einiges Verbesserungspotenzial, z.B. bei der 
Bitmanipulation.  Meditiere doch mal über folgende Zeilen (die zwar 
nicht falsch sind, aber so recht unsinnig):
1
intflg = ((intflg & 0b111111111) | 0b00000001);
2
if( (intflg & 0b00000001) & 0b00000001)
3
 ...

Ein Bufferüberlauf (Index n für rx_buf) wird nicht abgefangen.  Auch das 
eine Stelle, die zwar momentan notfalls geht, aber so nicht bleiben 
sollte, denn Schnittstellen sind notorisch für potentielle Überläufe.

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.