UART Interrupt toggelt PORT nicht

Gast #3865967
Lesenswert?

Hallo,

nach langem Probieren und Googeln habe ich es geschafft, dass mein 
Smartphone endlich über das Bluetooth-Modul HC-06 kommunizieren kann.

Verwendet wird ein ATmega8, der über 5V versorgt wird, genauso auch das 
Modul.
Am Pin PB1 soll eine LED getoggelt werden, sobald der USART was 
empfängt. Nur leider will das nicht so recht. Die LED wird zu 
Programmbeginn ausgeschaltet (bzw. der Pin PB1.

Hier der Code dazu:
1
#define F_CPU 1843200UL
2

3
#include <avr/io.h>
4
#include <inttypes.h>
5
#include <avr/interrupt.h>
6
//#include <util/delay.h>
7

8

9
//USART DEFS
10
#define BAUDRATE 9600UL    // Baudrate
11
//#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
12
//#define UBRR_VAL ((F_CPU/(16UL*BAUD))-1)
13
#define uart_maxstrlen 25    // Definiere maximale Laenge für Empfang
14

15
volatile uint8_t uart_str_complete=0;
16
volatile uint8_t uart_str_count=0;
17
volatile char uart_string[uart_maxstrlen+1]= "Test";
18

19
int received = 0;
20

21
ISR(USART_RXC_vect)
22
{
23
  PORTB ^= (1<<PB1);
24
  /*
25
  if(received==0)
26
  {
27
  PORTB |= (1<<PB1);
28
  received = 1;
29
  }
30
  else if(received==1)
31
  {
32
    PORTB &= ~(1<<PB1);
33
    received = 0;
34
  }
35
  */
36
  
37
  
38
  //PORTB ^= (1<<PB2);
39
  /*
40
  unsigned char buffer;
41
  buffer = UDR;
42
  if( uart_str_complete==0 )
43
  {
44
    if(buffer!= '\n' && buffer!= '\r' && uart_str_count<uart_maxstrlen-1)
45
    {
46
      uart_string[uart_str_count]=buffer;
47
      uart_str_count++;
48
    }
49
    else
50
    {
51
      uart_string[uart_str_count]= '\0';
52
      uart_str_count=0;
53
      uart_str_complete=1;
54
    }
55
  }
56
  uart_str_complete=0;
57
  */
58
}
59

60
void uart_init(void)
61
{
62
  //uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16UL*BAUDRATE) -1);
63
  unsigned int ubrr = F_CPU/16/BAUDRATE-1;
64
  UBRRH = (unsigned char) (ubrr>>8);
65
  UBRRL = (unsigned char) ubrr;
66
  
67
  cli();
68
  UCSRB |= (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);    // UART RX, TX und RX Interrupt einschalten
69
  UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);    // Asynchron 8N1
70
}
71

72

73
int uart_putc(unsigned char c)
74
{
75
  while(!(UCSRA & (1<<UDRE)))
76
  {
77
  }
78
  UDR = c;
79
  return 0;
80
}
81

82
void uart_puts (char *s)
83
{
84
  while(*s)
85
  {
86
    uart_putc(*s);
87
    s++;
88
  }
89
}
90

91

92
uint8_t uart_getc(void)
93
{
94
  while(!(UCSRA & (1<<RXC)))    // warten bis Zeichen verfuegbar
95
  ;
96
  return UDR;    // Zeichen aus UDR an Aufrufer zurueckgeben
97
}
98

99
void uart_gets(char* Buffer, uint8_t MaxLen )
100
{
101
  uint8_t NextChar;
102
  uint8_t StringLen = 0;
103
  NextChar = uart_getc();
104
  // Warte auf und empfange das nächste Zeichen
105
  // Sammle solange Zeichen, bis:
106
  // * entweder das String Ende Zeichen kam
107
  // * oder das aufnehmende Array voll ist
108
  while( NextChar != '\n' && StringLen < MaxLen - 1 )
109
  {
110
    *Buffer++ = NextChar;
111
    StringLen++;
112
    NextChar = uart_getc();
113
  }
114
  // Noch ein '\0' anhängen um einen Standard
115
  // C-String daraus zu machen
116
  *Buffer = '\0';
117
}
118

119

120
int main (void)
121
{
122
  DDRB = 0xFF;
123
  
124
  PORTB |= (0<<PB1);
125
  
126
  
127
  //uart_puts("AT");
128
  
129
  uart_init();
130
  sei();
131
  while(1)
132
  {
133
    /*
134
    uart_puts(uart_string);
135
    uart_puts("\n");
136
    _delay_ms(500);
137
    */
138
  }
139
}
Vielen Dank im Voraus für jede Idee / Hilfe!

Joe
Gast #3867117
Lesenswert?

So.....jetzt habe ich meine ISR mal angepasst und nun geht das 
"toggeln":
1
ISR(USART_RXC_vect)
2
{
3
  unsigned char nextChar;
4
  
5
  //Daten aus dem Puffer lesen
6
  nextChar = UDR;
7
  uart_string[uart_str_count] = nextChar;
8
  
9
  if(uart_string[uart_str_count] == '1')
10
  {
11
    PORTB |= (1<<PB1);
12
  }
13
  
14
  if(uart_string[uart_str_count] =='0')
15
  {
16
    PORTB &= ~(1<<PB1);
17
  }
18
  
19
  uart_str_count = 0;
20
}
Warum das normale Toggeln nicht ging, ist mir allerdings auch nach 
Einsehen Deiner Links nicht wirklich klar.

Gruß Joe
#3868081
Lesenswert?

Joe schrieb:

> Warum das normale Toggeln nicht ging, ist mir allerdings auch nach
> Einsehen Deiner Links nicht wirklich klar.

Weil du im Receive Complete Interrupt das UDR auch auslesen musst. Die 
Interrupt Anforderung wird erst durch das Auslesen von IDR gelöscht. 
List du UDR nicht aus, wird die ISR daher wieder und immer wieder 
aufgerufen. Dein Programm kommt zu nichts anderem mehr, als ständig ISR 
Aufrufe abzuarbeiten.

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