mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Uart-Programm testen


Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich arbeite mich gerade in die UART Programmierung mit C ein. 
Anscheinend kann man das mit AVRStudio nicht wirklich simulieren.

Habe gelesen dass man das mit dem Terminalprogramm HTerm testen kann. 
Braucht man dazu eine Hardware oder kann man das auch nur mit Firmware 
testen.

MfG

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein Simulieren kann man das in AVR-Studio nicht. Da kann man höchstens 
manuell die Ports setzen (also einzelne HEX-Werte). Aber ganze Texte etc 
geht nicht, da musst du schon was aufbauen.

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke.

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe es versucht zu testen. Irgendwie empfange ich einen Blödsinn. Es 
schreibt nur Quadrate hin.

Eingestellt in hterm habe ich Baud=9600, Data=8 und Stop=2 und 
Parity=None

Der uC ist ein at90
#include <avr/io.h>
#include <avr/interrupt.h>

int main (void){


UBRR1= (6>>8); //9600, 1MHZ
UBRR1= 6;
UCSR1B= (1<<RXEN1) | (1<<TXEN1);
UCSR1C= (1<<USBS1) | (3<<UCSZ10);

while(1)
{
while(!(UCSR1A & (1<<UDRE1)))
;
UDR1= 'x';
}

}

MfG

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Quarz benutzt?

MfG Spess

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
http://www.helmix.at/hapsim/
Mit HAPSIM kann man eine serielle Verbindung simulieren.

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Laut Schaltplan ist ein Quarz mit 8MHZ in der Schaltung. Habe UBRR auf 
51 gestellt => 9600 und 8Mhz.

Jetzt kommt aber ein Quadrat und ein unbeschreibliches Zeichen.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Laut Schaltplan ist ein Quarz mit 8MHZ in der Schaltung. Habe UBRR auf
>51 gestellt => 9600 und 8Mhz.

51 stimmt erstmal. Und arbeitet der AVR auch mit dem Quarz -> Fuses 
gesetzt?

MfG Spess

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fuses kenne ich nicht, muss ich mir zuerst mal anschauen. Habe es mit 
1MHZ und 8MHZ probiert. Eins hätte ja funktionieren müssen aber beide 
funktionieren nicht.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Fuses kenne ich nicht, muss ich mir zuerst mal anschauen.

?????????????

>Habe es mit 1MHZ und 8MHZ probiert. Eins hätte ja funktionieren müssen aber
>beide funktionieren nicht.

Wie kannst du das gemacht haben, ohne die Einstellungen des Controllers 
zu kennen?

MfG Spess

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Indem ich UBRR=6 (9600, 1MHZ) und auf UBRR=51 (9600, 8Mhz) gesetzt habe.

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe in hterm jetzt paar mal Connect und Disconnect gedrückt. Manchmal 
kommen Quadrate und manchmal kommen 'x'.

Finde ich komisch, was kann das sein.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Versuch erst mal den Quarz zu laufen zu bekommen. Der interne 
RC-Oszillator ist für serielle Kommunikation nicht sonderlich geeignet.

MfG Spess

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Habe in hterm jetzt paar mal Connect und Disconnect gedrückt. Manchmal
>kommen Quadrate und manchmal kommen 'x'.

>Finde ich komisch, was kann das sein.

Beim internen RC-Oszillator durchaus möglich.

MfG Spess

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe in den Code diese zwei Zeilen eingefügt. Es zeigt mir aber Fehler 
an. Vermutlich fehlen mir die Headerdateien.

Wie kann ich jetzt die richtigen Headerdateien finden.
CLKSEL0= 0x04;  // SUT-ext.Osz=00; Enable ext. Osz
CLKSEL1= 0x0C;  //EXCKSEL[3..0]=1100

MfG

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube ich habe den Fehler gefunden. Im Datenblatt steht CLKSEL aber 
es gehört CKSEL.

Habe es getestet es kommt aber trotzdem wieder ein Blödsinn raus.

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

int main (void){


CKSEL0= 0x04;  // SUT-ext.Osz=00; Enable ext. Osz
CKSEL1= 0x0C;  //EXCKSEL[3..0]=1100

UBRR1= (51>>8); //9600, 8MHZ
UBRR1= 51;
UCSR1B= (1<<RXEN1) | (1<<TXEN1);
UCSR1C= (1<<USBS1) | (3<<UCSZ10);

while(1)
{
while(!(UCSR1A & (1<<UDRE1)))
;
UDR1= 'x';
}

}

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>CKSEL0= 0x04;  // SUT-ext.Osz=00; Enable ext. Osz
>CKSEL1= 0x0C;  //EXCKSEL[3..0]=1100

Moment, das sind doch Fusebits, die kannst du doch nicht im C-Programm 
setzen.

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde gerne die Schaltung mit einem externen Quarz 8MHz antreiben.

Wenn ich die Fusebits nicht im C-Programm setze wo dann.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Womit programmierst du denn deinen Controller bzw. was für einen 
Programmieradapter verwendest du? Mit Ponyprog? Mit AVR-Studio?

Autor: Erik W. (exor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
im avrstudio...da gibs im konfigurierungsfenster nen extra reiter für

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den C-Code schreibe ich in AVR-Studio aber Flashen tu ich mit einem 
eigenen Programm für die Hardware.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Den C-Code schreibe ich in AVR-Studio aber Flashen tu ich mit einem
>eigenen Programm für die Hardware.

Jetzt wissen endlich alle *womit+ du den Controller programmierst.

MfG Spess

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

Bewertung
0 lesenswert
nicht lesenswert
astalavista schrieb:
> Den C-Code schreibe ich in AVR-Studio aber Flashen tu ich mit einem
> eigenen Programm für die Hardware.

Welches eigene Programm?
Du gibt es doch sicher einen Menüpunkt "Fuses" oder so ähnlich.

(Hast du den Prozessor gekauft, oder war der bei deiner Hardware dabei 
und welche Hardware ist das.

Mann versteh doch: Du musst die Fuses auf eine bestimmte Stellung 
einstellen. Das ist aber oftmals etwas diffizil wenn man das das erste 
mal macht. Also wollen wir rauskriegen, ob es überhaupt notwendig ist 
oder ob die Fuses in deiner Hardware ev. schon umgestellt wurden. Wenn 
sie noch nicht umgestellt wurden, dann kommt es auf den Brennprogramm 
an, wie das geht. Aber dazu musst du Info rausrücken und dich nicht in 
leeren Flosekeln wie 'eigenes Brennprogramm' verlieren.

Und noch was: Wenn du das in deinem Programm gefunden hast, lies auf 
jeden Fall zuerst die aktuelle Einstellung vom µC aus!

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Software habe ich von einer UNI die von Studenten programmiert 
wurde. Unter Fuses sehe ich nichts.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann verwende die Progs die hier von allen anderen verwendet werden 
(Ponyprog, avrdude etc.) Dann kannst du das auch einstellen. Oder ist da 
ein Bootloader drauf?

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Manchmal kommen Quadrate und manchmal kommen 'x'.
Mach mal eine längere Pause (>1ms) zwischen zwei Zeichen. Es gibt 
durchaus Bitmuster, die passen korrekt in einen Frame und sind dabei 
immer um ein paar Bits versetzt.

Nehmen wir das x (=0x78) : 01111000
Davor dann ein Start- und danach ein Stopbit.
Das ergibt 0 01111000 1
Und das jetzt mal als nimmer endenden Datenstrom:
0011110001001111000100111100010011110001001111000100111100010011110001.. 
.
Wenn jetzt der Empfänger spätern mal dazukommt, dann sieht er evtl. 
sowas:
      0001001111000100111100010011110001001111000100111100010011110001...
Und daraus wird dann
0 00100111 1
00100111 = 0x27 = '

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke das war das Problem. Setze ich keine Pause kommen manchmal die 
richtigen und manchmal die falschen Zeichen. Setze ich eine Pause von 20 
ms dann kommen meist die richtigen Zeichen, hin und wieder drängen sich 
trotzdem paar Sonderzeichen hinein.

Was kann da das Problem sein.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Was kann da das Problem sein.
Ich würde mal wie oben schon angesprochen die Fuses kontrollieren...

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Was kann da das Problem sein.

Dein Controller läuft immer noch mit dem internen RC-Oszillator.

MfG Spess

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe bisschen Probleme mit dem Empfangen von Zeichen. Wenn ich von 
hterm ein Zeichen schicke wird es in "zeichen" gespeichert. Es sollte 
auch gleich wieder EIN Zeichen an hterm wieder zurück schicken.

Das Problem ist jetzt, es wird nicht ein Zeichen geschickt sondern es 
werden andauernd Zeichen geschickt. Ich hätte aber gerne dass nur das 
EINE Zeichen welches geschickt wurde auch wider zurück geschickt wird.
ISR (USART1_TX_vect) 
{
   
  while(!(UCSR1A & (1<<UDRE1)))
  ;
  UDR1= zeichen;
        //UCSR1A= (1<<UDRE1);
}


ISR (USART1_RX_vect) 
{

  while ( !(UCSR1A & (1<<RXC1)) )
  ;
  zeichen = UDR1;


  while(!(UCSR1A & (1<<UDRE1)))
  ;
  UDR1= zeichen;
}

MfG

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Das Problem ist jetzt, es wird nicht ein Zeichen geschickt sondern es
>werden andauernd Zeichen geschickt. Ich hätte aber gerne dass nur das
>EINE Zeichen welches geschickt wurde auch wider zurück geschickt wird.

Dann schalte den TX Interrupt ab. Der kommt immer wenn ein
Zeichen gesendet wurde. Und da du dort immer wieder in UDR schreibst
ist das so ne Endlosgeschichte.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>ISR (USART1_RX_vect)
>{
>  while ( !(UCSR1A & (1<<RXC1)) )  <- Blödsinn

weil der Interrupt genau bei der Bedingung ausgelöst wird.

>ISR (USART1_TX_vect)
>{
> while(!(UCSR1A & (1<<UDRE1))) <- Blödsinn
> UDR1= zeichen;                <- Damit

schiebst nach jedem gesendeten Zeichen eins hinterher.

MfG Spess

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Das ist mir noch unklar. Mit "zeichen=UDR1" schicke ich ein Zeichen vom 
PC zum uC.
Somit befindet sich ein Zeichen im Puffer und deshalb wird ISR-TX 
ausgelöst.

Dadurch wird ja das eine Zeichen wieder zurück geschickt zum PC. Der 
Puffer sollte ja wieder leer sein. Da ich aber kein Zeichen mehr vom PC 
zum uc schicke, schiebe ich kein Zeichen nach jedem gesendeten 
hinterher.
ISR (USART1_TX_vect) 
{
  UDR1= zeichen;
}


ISR (USART1_RX_vect) 
{
  zeichen = UDR1;

  while(!(UCSR1A & (1<<UDRE1)))
  ;
  UDR1= zeichen;
}

MfG

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

Bewertung
0 lesenswert
nicht lesenswert
Dieser Interrupt

ISR (USART1_TX_vect)
{
  UDR1= zeichen;
}


wird ausgelöst, sobald die USART das Zeichen vollständig abgeschickt 
hat.
Als Folge davon schickst du wieder ein Zeichen weg, das natürlich auch 
irgendwann vollständig weggeschickt wurde, was dazu führt dass der 
Interrupt schon wieder ausgelöst wird (denn es wurde ja ein Zeichen 
abgeschickt) was wiederrum dazu führt, dass du das nächste Zeichen 
rausschickst, was wiederrum zum Interrupt führt woraufhin ... ad 
nauseam.

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso, danke.

D.h. stoppen kann ich den ISR-TX wieder mit
  while ( !(UCSR1A & (1<<RXC1)) )
  ;

  zeichen = UDR1;

Bei diesem Interrupt schickt er mir zuerst ein a,b,b,b,b....
Sollte es nicht a,b,c,d,.... sein?

ISR (USART1_TX_vect)
{
  UDR1= zeichen+1;
}

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

Bewertung
0 lesenswert
nicht lesenswert
Der ganze Ansatz mit 'Zeichen schicken sobald ein TX Interrupt auftritt' 
ist in deinem Fall Schrott.
Du veruschst das Problem an der falschen Stelle zu beheben.
ISR (USART1_TX_vect) 
{
  // nichts. Ist noch völlig uninteressant, wann ein Zeichen rausgegangen ist
}

ISR (USART1_RX_vect) 
{
// Ist unnötig
// Der Interrupt wurde aufgerufen WEIL ein Zeichen empfangen wurde
// an dieser Stelle braucht daher nicht getestet werden.
// Es ist Faktum, dass ein Zeichen da ist!
//
//  while ( !(UCSR1A & (1<<RXC1)) )
//  ;
  zeichen = UDR1;


  while(!(UCSR1A & (1<<UDRE1)))
    ;
  UDR1= zeichen;
}

Autor: astalavista (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe mich nur damit gespielt um beide Interrupts zu testen. Trotzdem 
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.