www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART LED anschalten und halten


Autor: André (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Ich hab nen Problem mit der UART-Schnittstelle bei einem Mega8. Ich will 
vom Rechner ein Zeichen senden (also 8bit) und wenn der Controller 
dieses empfängt, soll er eine LED an PortC anschalten.
Geht auch alles, nur bleibt die LED nicht an. Er empfängt, die LED 
blitzt auf und geht wieder aus und ich weiß nicht warum.
Wenn ich die zweite While-Schleife wegnehme, bleibt die LED an, wenn 
aber was empfängt, gehts kurz an und wieder aus, das macht keinen Sinn 
finde ich. Wenn der Port einmal auf 1 gesetzt wurde, bleibt er doch auf 
1, da er ja nirgendwo auf 0 setzt.

Hier erstmal der Code:
#include  <avr\io.h>    
//----------------------------------------------------------------------

int main ( void )
       {
  DDRC=0x01;

  UCSRA=0x00;
  UCSRB=0x10;  //receiver
  UCSRC=0x86;  //8bit 1stop
  UBRRH=0x00;
  UBRRL=0x19;  //Baud 9600 bei 4MHz Takt

  while (1)
    {

           while (((UCSRA >> RXC) & 1) ==0)
               {}

     PORTC = 0x01; 
    }

  return 0;
       }

Bitte entschuldigt die komische Frage, aber ich komm einfach nicht 
weiter an dem Punkt und hoffe ihr könnt mir helfen. Vielen Dank schonmal

Viele Grüße
André

Autor: Hubert G. (hubertg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Watchdog eingeschalten, macht der µC ein Reset?

Autor: Moritz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was steht denn im Datenregister drin?

Gruß

Autor: willi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich würde ja fast wetten, dass die LED leuchtet wenn der entsprechende 
ausgangspin auf 0 ist

Autor: André (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
An der 0 kann es nicht liegen, wenn ich "while (((UCSRA >> RXC) & 1) 
==0)" wegnehme, dann geht die LED an und bleibt es auch.
Kann es sein, dass es einen Reset gibt, sobald wieder oben in die 
while(1)-schleife gegangen wird?
Der watchdog ist doch standartmäßig aus oder? ich hab ihn jedenfalls 
nicht wissendlich angeschaltet.
Was im Emfangsregister steht, ist mir erstmal egal, ich will nur 
unterscheiden, ob was drin steht, oder nicht. Wenn was drin steht, soll 
er die LED anschalten und sie soll an bleiben.

nochmal eine andere Idee Code, vllt wird dann eher klar, wo mein Problem 
liegt:
  while(1)
  {
         if (UDR !=0x00)
         PORTC = 0x01;
   }

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Find erst mal raus, ob dein µC ungewollt resettet.

Häng an einen 2.ten Pin noch eine Led.
In main schaltest du die LED ein, wartest ein Weilchen und schaltest sie 
wieder aus
#define F_CPU 4000000
#include <avr\io.h> 
#include <util\delay.h>

//----------------------------------------------------------------------

int main ( void )
{
  DDRC=0x03;

  PORTC |= 0x02;
  _delay_ms( 1000 );
  PORTC &= ~0x02;

  UCSRA=0x00;
  UCSRB=0x10;  //receiver
  UCSRC=0x86;  //8bit 1stop
  UBRRH=0x00;
  UBRRL=0x19;  //Baud 9600 bei 4MHz Takt

  ...

Wenn diese LED nach dem Programmstart ein zweites mal blinzelt, hat dein 
µC zwischendurch einen Reset gemacht.

Autor: Hubert G. (hubertg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Watchdog ist standardmässig ein. Den musst du mit den Fuses ausschalten.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hubert G. schrieb:
> Watchdog ist standardmässig ein.

Das wär mir neu

Autor: Hubert G. (hubertg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist richtig, WDTON ist  nicht ein, da habe ich mich vom Fuse-Calculator 
verleiten lassen.

Autor: André (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, das mit der Pin hab ich gemacht, aber das delay mag er nicht. er 
schaltet die LED an, aber nicht wieder aus.
Der fehler muss bei der zweiten while schleife liegen, die muss 
irgendwie den Port zurücksetzen auf den wert, der vor aufruf da war.
irgendwie macht das alles keinen sinn ... :S

Autor: Andy H. (vinculum) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wo führt dein return hin, wenn nix auf dem stack liegt?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
André schrieb:
> Ok, das mit der Pin hab ich gemacht, aber das delay mag er nicht. er
> schaltet die LED an, aber nicht wieder aus.

Ich bin mal davon ausgegangen, dass deine LED bei einer 1 am 
Port-Ausgang angehen. Meistens allerdings macht man es genau anders rum.

> Der fehler muss bei der zweiten while schleife liegen, die muss
> irgendwie den Port zurücksetzen auf den wert, der vor aufruf da war.

Das tut sie mit Sicherheit nicht.

> irgendwie macht das alles keinen sinn ... :S

Du sagst es.

Bist du absolut, 100% sicher, dass bei dir die LED angehen, wenn der 
Portpin auf 1 gesetzt wird?

Autor: sam (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich würde dir empfehlen erstmal die korrekte funktion deiner serriellen 
verbindung zu testen:
auf zeichen auf der usart warten und per usart wieder zurücksenden ... 
mit einem terminalprogramm (z.b. HTerm) kannst du dann sicherstellen , 
dass der mega8 überhaupt was empfängt etc.

dann würde ich im mainloop einfach die empfangenen zeichen auswerten 
(per if oder switch) und z.b. bei 'a' ein ausgang togglen : PORTB=PORTB 
^ 0xFF;
und dazu noch ein echo zurück an den pc senden.

und was mich dann noch stört: bevor PORTC dann auf 0x01 gesetzt wird ist 
er quasi undefiniert (eigentlich sollte er immer 0x00 sein, aber da du 
ihm das nie gesagt hast, kannst du dir nicht sicher sein)

in der C-programmierung gibt es doch auch eine warnung wenn man 
nichtinitialisierte variablen benutzt, weil man den inhalt eben nicht 
kennt.

Autor: André (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, da bin ich wieder. Hab jetzt ne Weile experimentiert und mir 
einiges durchgelesen und einiges klappt und das eigentlich gewollte 
immernoch nicht.

Ich hab mir einen Beispielquellcode aus dem Internet geladen, was per 
UART ein Byte empfängt und wieder zurücksendet. Das macht er, aber nicht 
immer, manchmal kommt quatsch, ich denke, wenn ich zu schnell 
hintereinander sende. Er empfängt aber auch das richtige, Einstellung 
müssten also stimmen.

Was aber immernoch nicht geht, egal ob LED bei 0 oder bei 1 an sein 
soll, ist das Halten des Status. Er setzt immer wieder zurück, ich weiß 
nicht warum.

Hier mal der Text, bei 0 soll die LED jetzt an sein:
#define OSCSPEED  4000000    /* in Hz */

#include "avr/io.h"

void Initialize(void)
{
  PORTB = 0x0;
  PORTC = 1<<2;  /* turn the LED off */
  PORTD = 0x0;

  DDRB = 0x0;
  DDRC = 1<<2;    /* PC2 as output - the LED is there */
  DDRD = 0x0;

}

void InitUART(uint32_t baud)  /* here a simple int will not suffice*/  
{
  int baudrate=(OSCSPEED/(16*baud))-1; /* as per pg. 133 of the user manual */
  /* Set baud rate */
  UBRRH = (unsigned char)(baudrate>>8);
  UBRRL = (unsigned char)baudrate ;
  /* Enable Receiver and Transmitter */
  UCSRB = (1<<RXEN)|(1<<TXEN);
  /* Set frame format: 8data, 1stop bit */
  UCSRC = (1<<URSEL)|(3<<UCSZ0);
  
}

unsigned char UARTReceive(void)
{
  if (UCSRA & (1<<RXC))
    return UDR;
  else  /* no data pending */
    return 0;
}

void UARTTransmit(unsigned char data)
{
  while (!( UCSRA & (1<<UDRE)) );
  /* Put data into buffer, sends the data */
  UDR = data;
}

int main(void)
{
  unsigned char ch;
  Initialize();
  InitUART(9600);

  while (1)
  {
    ch=UARTReceive();
    if (ch==0x41)
       PORTC &= ~(1<<2);

    if (ch)
    {
      UARTTransmit(ch);
    }

  }
  return 0;
}
Wann kann es denn allgemein sein, dass der Controller resetet? Wenn ich 
sonst den PORT setze, bleibt er doch auch.

Viele Dank aber schonmal für die ganzen Vorschläge und natürlich auch 
vorab vielen Dank :)

Grüße
André

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1. Frage die sich mir stellt:
Woher kommt der Takt? Sind die Fuses richtig gesetzt (ist zwar eine 
zweite Frage, hängt aber mit demTaktproblem zusammen).

2. Findet der Kommunikationsabbruch in regelmäßigen Abständen statt? 
(Watchdog immer noch an?)

3. Wieso machst du dein Programm so unnötig kompliziert?
#define OSCSPEED  4000000    /* in Hz */
#define baudrate=(OSCSPEED/(16L*baud))-1; /* as per pg. 133 of the user manual */

#include "avr/io.h"

void Initialize(void)
{
  PORTB = 0x0;
  PORTC = 1<<2;  /* turn the LED off */
  PORTD = 0x0;

  DDRB = 0x0;
  DDRC = 1<<2;    /* PC2 as output - the LED is there */
  DDRD = 0x0;

}

void InitUART(uint32_t baud)  /* here a simple int will not suffice*/  
{

  /* Set baud rate */
  UBRRH = (unsigned char)(baudrate>>8);
  UBRRL = (unsigned char)baudrate ;
  /* Enable Receiver and Transmitter */
  UCSRB = (1<<RXEN)|(1<<TXEN);
  /* Set frame format: 8data, 1stop bit */
  UCSRC = (1<<URSEL)|(3<<UCSZ0);
  
}


int main(void)
{
  unsigned char ch;
  Initialize();
  InitUART(9600);

  while (1)
  {
    while (!(UCSRA & (1<<RXC))); // Warten bis ein Zeichen eingetroffen ist
    ch=UDR;
    if (ch==0x41) // Empfangenes Zeichen ist eine '1' (*)
       PORTC &= ~(1<<2);
  
    while (!( UCSRA & (1<<UDRE)) ); // auf leeren Sendepuffer warten
    UDR = ch; // Zeichen versenden
    }

  }
  return 0;
}

Sollte völlig reichen.
Die mit (*) markierte Zeile kann man auch auskommentieren, was zu einem 
Blinken der LED bei jeden empfangenen Zeichen führt.

Autor: André (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
zu 1:
Der Takt kommt von einem Quarz, 4MHz zwischen PB6 und PB7 und von jedem 
nen 22pF Kondensator gegen Masse. Die Fuses hab ich mit "myAVR Workpad" 
eingestellt. Ich hab "Ext. Crystal/Resonator High Freq.; Start-up time: 
258 CK + 4 ms" gewählt, hab ich irgendwo so gelesen. Der berechnet die 
Fusebits dann, kam raus: Low Fuse (0xCE)  High Fuse (0x99) Lockbits 
(0xFF)
Könnt ihr damit was anfangen? Mir wäre es auch lieber, wenn ich 
verstehen würde, was ich da machen lasse. Ich wollte aber nichts kaputt 
machen ...

zu 2. Watchdog war nie an bzw nie wissentlich angemacht. Hab schon 
versucht, nen System zu erkennen, aber ich finde keins, wann es nicht 
richtig geht.

Zu 3. Du meintest, wenn ich "if (ch == 0x41)" weglasse, blinkt er beim 
Empfangenen aus ... das ist ja genau mein Problem. Das will ich nicht, 
die Lampe soll an bleiben. Weil ich setze doch den Port und sage 
nirgendwo, dass wenn er nichts empfängt, er den Port zurückschalten 
soll.
Ich will den Controller letztendlich als Steuereinheut einsetzen, ich 
sende ihm z.b. ein "E" und er schaltet eine Lampe ein und wenn ich ihm 
irgendwann ein "A" sende, geht die Lampe wieder aus. Aber das geht ja 
nur, wenn der PORT nach dem Empfangen auch so bleibt wie ich ihn setze.
Versteht ihr was ich meine und vorhabe? :)

Danke für die Geduld

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
André schrieb:

> nur, wenn der PORT nach dem Empfangen auch so bleibt wie ich ihn setze.
> Versteht ihr was ich meine und vorhabe? :)

Ja.
Wenn es auf deinem System mit deinem Programm so ist, dass die LED beim 
empfang eines Zeichens an geht und kurz darauf wieder aus, dann hast du 
ein Hardwareproblem. Das hat nichts mit deinem µC (ausser wenn der 
defekt wäre, was aber unwahrscheinlich ist) oder dem Programm zu tun.

Hier sind wir raus. Dein Hardwareproblem können wir so nicht lösen, da 
musst du ran. Mal die üblichen Verdächtigen abklopfen. 
Versorgungsspannung, Blockkondensatoren etc.

Autor: Marco -. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo
ich möchte über USART zeichen empfangen und auswerten. USART 
fukntioniert auch soweit aber ich hab ein Problem mit der Funktion 
"test". Komischerweise wird die LED nur dann eingeschaltet wenn ich in 
der if-abfrage eine andere Funktion aufrufe oder eine Verzögerungszeit 
drin habe, die größer als 90 ms ist. Beim Ausschalten gibts keine 
Probleme. Hat jemand eine Idee woran das liegen könnte?
Danke im Voraus.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "uart.h"

void init ( void );
void test( uint8_t data );
uint8_t temp;



int main(void){

  cli();              /* disable interrupt */
  init();              /* init ports, baudrate */
  sei();              /* enable interrupt */

  while(1){
    test(temp);
  }
  
  return 0;
}



ISR(USART_RX_vect){
  
  unsigned char receive;
  
  if(UDR == 0x73){          /* "s" command */
            
    receive = USART_Receive();
    
    if(receive == 0x61)        /* "a" command */  
      temp = 1;  
    
    if(receive == 0x62)        /* "b" command */  
      temp = 2;  

    if(receive == 0x63)        /* "c" command */
      temp = 3;
  }
}



void init( void ){
  DDRB = 0xff;
  PORTB = 0xff;
  
  /* baudrate 19200 using a 8MHz crystal */
  USART_Init(25);        

  temp = 0;

}


void test(uint8_t data){

  if (data == 1){
  //  USART_Transmit('a');
    PORTB &= ~(1<<PB0);
  //  _delay_ms(100);
  }

  if (data == 3){
    PORTB |= (1<<PB0);
  }
}

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe Interrupt, Stichwort volatile.

Autor: aaaaa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
stack in ordnung?

Autor: gadgaet (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du die LED direkt an den µC angeschlossen? Mir ist es schonmal 
passiert, dass an der LED zu viel Strom fließt und der µC deswegen 
"abstürzt". Liegt es vllt. daran?

An wie vielen Stellen im Code wird das Ausgangsregister neu gesetzt? 
Kann es sein, dass das Bit für die LED aus Versehen gelöscht wird?

grüssse
g.

Autor: Marco -. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
volatile hats gebracht
danke

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.