Forum: Mikrocontroller und Digitale Elektronik USART mit dem Attiny2313 / 4313 geht nicht


von Michael (c0d3z3r0)


Lesenswert?

Hallo!

Ich habe folgendes Problem mit dem Attiny2313 / 4313.

Ich habe den tiny über einen MAX232N an die Serielle Schnittstelle 
gepackt. An einem Port (PD6) hängt ne LED, die sich per Taster 
ein-/ausschalten lässt.

Die Ausgabe an den PC per uart_puts() funktioniert ohne Probleme.
1
void uart_puts (char *s)
2
{
3
    while (*s)
4
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */
5
        uart_putc(*s);
6
        s++;
7
    }
8
}

Aber sobald ich am PC auch nur ein Zeichen eingebe, leuchtet plötzlich 
die zuvor ausgeschaltete LED auf und es geht gar nichts mehr. Den 
Empfang habe ich nach einem Tutorial per Interrupt gelöst:
1
ISR(USART_RXC_vect)
2
{
3
  uart_puts("test");
4
}

Initialisiert wird USART wie folgt:
1
void uart_init()
2
{
3
  UBRRH = UBRR_VAL >> 8;
4
  UBRRL = UBRR_VAL & 0xFF;
5
  UCSRB |= (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);  // UART RX, TX und RX Interrupt einschalten
6
  /* Set frame format: 8data, 2stop bit */
7
  UCSRC = ( 1 << USBS ) | ( 3 << UCSZ0 );
8
}

Wieso leuchtet plötzlich die LED auf / hängt sich der tiny auf? Und 
warum mag er meine Eingaben nicht verarbeiten? :(  Ich hoffe ihr könnt 
mir helfen!


Danke schonmal!

von Stefan E. (sternst)


Lesenswert?

Michael Niewöhner schrieb:
> Ich habe folgendes Problem mit dem Attiny2313 / 4313.
1
ISR(USART_RXC_vect)

Und wo hast du diesen Namen her?
Merke: Den Vektornamen errät man nicht und man kopiert ihn auch nicht 
einfach von einem anderen Code der für einen anderen µC geschrieben 
wurde. Stattdessen informiert man sich, wie dieser Name für genau deinen 
µC lautet.

PS: Und außerdem ignoriert man die diesbezügliche Compiler-Warnung 
nicht.

von Michael (c0d3z3r0)


Lesenswert?

Dank für die flotte Antwort!

Naja, erraten hab ich den Namen sicher nicht... und der compiler spricht 
folgendes:
1
uart.h:23:1: warning: type defaults to 'int' in declaration of 'ISR'
2
uart.c:40:1: warning: type of 'UART0RX_vect' defaults to 'int'

Das Datenblatt hat gesprochen... "USART0_RXC" ist wohl richtig... Geht 
aber auch nicht, gleiches Problem :(

von KeyMusic (Gast)


Lesenswert?

Hallo Michael,

was macht denn die Funktion uart_puts?!
Puffert sie die zu sendenden Zeichen oder blockiert sie? Im zweiten Fall 
wäre es sehr "gefährlich" sie aus einer InterruptServiceRoutine 
aufzurufen...

Gruß
KeyMusic

von Michael (c0d3z3r0)


Lesenswert?

Blockieren?  Sie puffert den zu sendenden String und arbeiten diesen 
zeichenweise mit putz ab.

Auch wenn ich statt der Ausgabe die LED toggle, hängt sich der µC auf..
1
ISR(USART0_RXC)
2
{
3
  //uart_puts("do");
4
  PORTD ^= (1<<PD6);
5
}

von Stefan E. (sternst)


Lesenswert?

Michael Niewöhner schrieb:
> und der compiler spricht
> folgendes:

Dann hast du außerdem auch noch ein
1
#include <avr/interrupt.h>
vergessen.

Michael Niewöhner schrieb:
> Das Datenblatt hat gesprochen... "USART0_RXC" ist wohl richtig...

Irgendwelche Namen in irgendwelchen Assembler-Beispiel-Codes sind 
irrelevant.

http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

von Michael (c0d3z3r0)


Lesenswert?

Stefan Ernst schrieb:
> Dann hast du außerdem auch noch ein#include <avr/interrupt.h>vergessen.

Nein, ist bereits drin.

von Stefan E. (sternst)


Lesenswert?

Michael Niewöhner schrieb:
>> Dann hast du außerdem auch noch ein#include <avr/interrupt.h>vergessen.
>
> Nein, ist bereits drin.

Aber garantiert nicht an der Stelle der ersten Fehlermeldung.
1
uart.h:23:1: warning: type defaults to 'int' in declaration of 'ISR'
Was hat das "ISR" überhaupt in einer deiner Header-Dateien zu suchen?

von Michael (c0d3z3r0)


Lesenswert?

Okay, der Name ist laut Liste "USART_RX_vect". Geht auch nicht.

Stefan Ernst schrieb:
> uart.h:23:1: warning: type defaults to 'int' in declaration of 'ISR'Was hat das 
"ISR" überhaupt in einer deiner Header-Dateien zu suchen?

Gute Frage.... hab ich rausgenommen. Keine Änderung...

von Stefan E. (sternst)


Lesenswert?

Michael Niewöhner schrieb:
> Keine Änderung...

Dann poste den kompletten aktuellen Code, und alle Compiler-Meldungen 
dazu.

von Michael (c0d3z3r0)


Lesenswert?

Danke für eure Hilfe!  Bitte nicht gleich schlagen :S indeckunggeh


main.c
1
#include <avr/io.h>
2
#include "functions.h"
3
#include <util/delay.h>
4
#include "uart.h"
5
#include <avr/interrupt.h> 
6
7
void init(void)
8
{  
9
  // Eingänge
10
  DDRB &= ~( (1<<DDB0) ); // Taster 1
11
  PORTB |= (1 << PB0); // Pull-Up ein
12
  
13
  //Ausgänge
14
  DDRD  |= (1<<DDD6); // LED
15
16
  //UART initialisieren
17
  uart_init();
18
19
  //LED EIN
20
  PORTD |= (1<<PD6);
21
  
22
  //Interrupts ein
23
  sei();
24
  uart_puts("INIT\n\r");
25
}
26
27
int main()
28
{
29
  init();
30
  uint16_t i;
31
  char s[10];
32
  while(1)
33
  {
34
    // Taster 1
35
    if (debounce(&PINB, PB0))
36
    {
37
      PORTD ^= (1<<PD6);
38
      uart_puts("TEST\n\r");
39
    }
40
  }
41
  
42
  return 0;
43
}

functions.c
1
#include <avr/io.h>
2
#include "functions.h"
3
#include <util/delay.h>
4
  
5
uint8_t debounce(volatile uint8_t *port, uint8_t pin)
6
{
7
    if  (!(*port & (1 << pin)))
8
    {
9
        _delay_ms(30);
10
        if (  (*port & (1 << pin)) )
11
    {
12
      _delay_ms(30);
13
      return 1;
14
    }
15
    }
16
    return 0; 
17
}

functions.h
1
#ifndef F_CPU
2
  #define F_CPU 8000000UL
3
#endif
4
5
uint8_t debounce(volatile uint8_t *port, uint8_t pin);

uart.c
1
#include <avr/io.h>
2
#include "uart.h"
3
#include <avr/interrupt.h>
4
 
5
volatile uint8_t uart_str_complete = 0;
6
volatile uint8_t uart_str_count = 0;
7
volatile char uart_string[UART_MAXSTRLEN + 1] = "";
8
9
void uart_init()
10
{
11
  UBRRH = UBRR_VAL >> 8;
12
  UBRRL = UBRR_VAL & 0xFF;
13
  UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);  // UART RX, TX und RX Interrupt einschalten
14
  UCSRC = ( 1 << USBS ) | ( 3 << UCSZ0 );
15
  //UCSRC = (1<<UCSZ1)|(1<<UCSZ0);
16
  
17
}
18
19
int uart_putc(unsigned char c)
20
{
21
    while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
22
    {
23
    }                             
24
 
25
    UDR = c;                      /* sende Zeichen */
26
    return 0;
27
}
28
 
29
void uart_puts (char *s)
30
{
31
    while (*s)
32
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */
33
        uart_putc(*s);
34
        s++;
35
    }
36
}
37
38
39
ISR(USART_RX_vect)
40
{
41
  PORTD ^= (1<<PD6);
42
}

uart.h
1
#ifndef F_CPU
2
  #define F_CPU 8000000UL
3
#endif
4
5
#define BAUD 9600UL      // Baudrate
6
 
7
// Berechnungen
8
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
9
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
10
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
11
 
12
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
13
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
14
#endif
15
16
#define UART_MAXSTRLEN 10
17
18
int uart_putc(unsigned char c);
19
void uart_puts (char *s);
20
void uart_init();
21
unsigned char USART_Receive( void );
22
23
extern volatile uint8_t uart_str_complete;
24
extern volatile uint8_t uart_str_count;
25
extern volatile char uart_string[UART_MAXSTRLEN + 1];

von Michael (c0d3z3r0)


Lesenswert?

Compiler:
1
avr-gcc (GCC) 4.5.1
2
Copyright (C) 2010 Free Software Foundation, Inc.
3
This is free software; see the source for copying conditions.  There is NO
4
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5
6
7
Compiling: main.c
8
avr-gcc -c -mmcu=attiny4313 -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 -DF_OSC= -funsigned-char -funsigned-bitfields -MD -MP -MF .dep/main.o.d main.c -o main.o 
9
In file included from main.c:4:0:
10
uart.h:20:1: warning: function declaration isn't a prototype
11
main.c:27:5: warning: function declaration isn't a prototype
12
main.c: In function 'main':
13
main.c:50:4: warning: "/*" within comment
14
main.c:31:7: warning: unused variable 's'
15
main.c:30:11: warning: unused variable 'i'
16
17
Compiling: functions.c
18
avr-gcc -c -mmcu=attiny4313 -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=functions.lst  -std=gnu99 -DF_OSC= -funsigned-char -funsigned-bitfields -MD -MP -MF .dep/functions.o.d functions.c -o functions.o 
19
20
Compiling: uart.c
21
avr-gcc -c -mmcu=attiny4313 -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=uart.lst  -std=gnu99 -DF_OSC= -funsigned-char -funsigned-bitfields -MD -MP -MF .dep/uart.o.d uart.c -o uart.o 
22
In file included from uart.c:2:0:
23
uart.h:20:1: warning: function declaration isn't a prototype
24
uart.c:9:6: warning: function declaration isn't a prototype
25
26
Linking: main.elf
27
avr-gcc -mmcu=attiny4313 -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o  -std=gnu99 -DF_OSC= -funsigned-char -funsigned-bitfields -MD -MP -MF .dep/main.elf.d main.o functions.o uart.o   --output main.elf -Wl,-Map=main.map,--cref    -lm
28
29
Creating load file for Flash: main.hex
30
avr-objcopy -O ihex -R .eeprom main.elf main.hex
31
32
Creating load file for EEPROM: main.eep
33
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
34
  --change-section-lma .eeprom=0 -O ihex main.elf main.eep
35
avr-objcopy: --change-section-lma .eeprom=0x00000000 never used
36
37
Creating Extended Listing: main.lss
38
avr-objdump -h -S main.elf > main.lss
39
40
Creating Symbol Table: main.sym
41
avr-nm -n main.elf > main.sym
42
43
Size after:
44
AVR Memory Usage
45
----------------
46
Device: attiny4313
47
48
Program:     346 bytes (8.4% Full)
49
(.text + .data + .bootloader)
50
51
Data:         28 bytes (10.9% Full)
52
(.data + .bss + .noinit)
53
54
55
56
Errors: none
57
-------- end --------

von MWS (Gast)


Lesenswert?

Du musst UDR auslesen, sonst hört der Interrupt nicht auf zu triggern.

von Stefan E. (sternst)


Lesenswert?

1
  PORTD ^= (1<<PD6);
Ändere das wieder in das ursprüngliche, und du wirst merken, dass der 
Interrupt vermutlich sehr wohl geht (nur nicht ganz so, wie von dir 
erwartet).

Als nächstes liest du dir dann im Datenblatt die Beschreibung des 
RXC-Flags nochmal durch, und überlegst, was wohl die Ursache dieses "nur 
nicht ganz so, wie von dir erwartet" ist.

Edit:
@MWS
Spielverderber ;-)

von MWS (Gast)


Lesenswert?

Den Lerneffekt wird der TE auch so haben ;D

von Michael (c0d3z3r0)


Lesenswert?

MWS schrieb:
> Du musst UDR auslesen, sonst hört der Interrupt nicht auf zu triggern.

Ja, jetzt klappts :D  Vielen Dank euch!

von Michael (c0d3z3r0)


Lesenswert?

MWS schrieb:
> Den Lerneffekt wird der TE auch so haben ;D

Jep :)

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.