www.mikrocontroller.net

Forum: Compiler & IDEs Atmega8 - UART sendet doppelt


Autor: Max D. (triops)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Ich habe gerade ein kleines Versuchsprogramm zum Test des Int0 und des 
UART geschrieben(für stk500). Es soll bei jedem Int0-Ereignis einen 
String über die UART schicken. Das macht es auch soweit, aber ab dem 
zweiten Mal werden die ersten beiden Buchstaben doppelt geschickt (z.B 
DiDies ist ein...). Stehen diese beiden Bytes noch in irgendeinem 
Puffer; kann ich den löschen?
Da ich noch nicht so viel für µController programmiert habe, wäre ich 
auch über allgemeine Anmerkungen und Verbesserungsvorschläge zu meinem 
Code dankbar:
Viele Grüße Max

#include <avr/io.h>
#include <avr/interrupt.h>

static volatile unsigned char text[] = "Dies ist ein Versuchstext! ";
static volatile unsigned char *ptext = text;

//************Unterprogramme**************

void uart_on(void){
  UBRRL = 47;    //4800baud @ 3686400Hz
   UCSRB = 0x68; }    //Sender + Int. an

void uart_out(void){
  UCSRB = 0x00;  }    //alles deaktiviert

void int0_enable(void){
  MCUCR = _BV(ISC01);
  GICR = _BV(INT0);  }

//***********Interruptroutinen*************
ISR(USART_UDRE_vect){
  UDR = *ptext;
  ptext++;      //nächstes Zeichen
  if (*ptext == '\0') {    //Ende erreicht?
    uart_out();
    ptext = text; }}  //WIEDER AUF ANFANG ZEIGEN

ISR(INT0_vect){
  uart_on(); }    //UART anschalten

//******************************************
int main(){
  int0_enable();
  SREG = _BV(7);
  for(;;){}
  return 0; }

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
INT0 ist ein Taster? Der prellt.

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> UCSRB = 0x68;     //Sender + Int. an
ist verkehrt (oder du hast die ISR(USART_TXC_vect) 'nur' nicht 
gepostet), Endlich ein Argument für "UCSRB = (1<<TXEN)|(1<<UDRIE);"

Wenn du den Pointer in der ISR auf null testest, wird gerade ein Byte 
gesendet, und dieses Senden wird abgebrochen, wahrscheinlich bleibt 
dieses Byte dann im Puffer stehen und wird beim nächsten Mal gesendet.

(und statt "SREG |= _BV(7);" geht einfach "sei();")
Also alles in allem etwa so (alles ungetestet!):
#include <avr/io.h>
#include <avr/interrupt.h>

#define BAUD 4800
// F_CPU wird eigentlich im Makefile/vom AVR-studio definiert
#ifndef F_CPU
#  define F_CPU 3686400
#endif

#define UBRRVAL = F_CPU/(16*BAUD)-1

static const char text[] = "Dies ist ein Versuchstext! ";


//******************************************
int main()
{
    UBRRH = (UBRRVAL>>8);
    UBRRL = UBRRVAL;
    UCSRB = (1<<UDRIE)|(1<<TXEN);
  
    MCUCR |= (1<<ISC01);
    GICR |= (1<<INT0);
    sei();
  
    for(;;){
    }
    return 0;
}

//***********Interruptroutinen*************
ISR(USART_UDRE_vect)
{
    static char* ptext = text;
    if(!(UDR = *(ptext++))){  // naechstes Byte senden (sry, btw ;) 
        UCSRB &= ~(1<<UDRIE);  // nur den Interrupt abschalten
        ptext = text;        // pointer ruecksetzen
    }
} 

ISR(INT0_vect)
{
    UCSRB |= (1<<UDRIE);
}

hth. Jörg
ps.: hier gibt's ein tolles AVR-GCC Tutorial :)
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.