Atmega16L @ gcc [Prg. läuft nur Debug Mode]

Gast #1675911
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
}
#1676124
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren