Forum: Mikrocontroller und Digitale Elektronik UART Interrupt toggelt PORT nicht


von Joe (Gast)


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

von Frank L. (frank_l)


Lesenswert?

Hallo Joe,

schau Dir mal die beiden Tutorials an:

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Datenrichtung_bestimmen

und

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART

dann wird Dir sicher auffalen, was Du falsch machst.


Gruß
Frank

von Joe (Gast)


Lesenswert?

Danke für Deine Antwort sowie den Hinweis.
Ich werde mir die vorgeschlagenen Links vergleichend zu meinem Code 
ansehen.

Gruß
Joe

von Joe (Gast)


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

von Karl H. (kbuchegg)


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.

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.