Forum: Mikrocontroller und Digitale Elektronik Uart-Programm testen


von astalavista (Gast)


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

von Timmo H. (masterfx)


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.

von astalavista (Gast)


Lesenswert?

Danke.

von astalavista (Gast)


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
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
int main (void){
5
6
7
UBRR1= (6>>8); //9600, 1MHZ
8
UBRR1= 6;
9
UCSR1B= (1<<RXEN1) | (1<<TXEN1);
10
UCSR1C= (1<<USBS1) | (3<<UCSZ10);
11
12
while(1)
13
{
14
while(!(UCSR1A & (1<<UDRE1)))
15
;
16
UDR1= 'x';
17
}
18
19
}

MfG

von spess53 (Gast)


Lesenswert?

Hi

Quarz benutzt?

MfG Spess

von gast (Gast)


Lesenswert?

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

von astalavista (Gast)


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.

von spess53 (Gast)


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

von astalavista (Gast)


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.

von spess53 (Gast)


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

von astalavista (Gast)


Lesenswert?

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

von astalavista (Gast)


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.

von spess53 (Gast)


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

von spess53 (Gast)


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

von astalavista (Gast)


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.
1
CLKSEL0= 0x04;  // SUT-ext.Osz=00; Enable ext. Osz
2
CLKSEL1= 0x0C;  //EXCKSEL[3..0]=1100

MfG

von astalavista (Gast)


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.

1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
int main (void){
5
6
7
CKSEL0= 0x04;  // SUT-ext.Osz=00; Enable ext. Osz
8
CKSEL1= 0x0C;  //EXCKSEL[3..0]=1100
9
10
UBRR1= (51>>8); //9600, 8MHZ
11
UBRR1= 51;
12
UCSR1B= (1<<RXEN1) | (1<<TXEN1);
13
UCSR1C= (1<<USBS1) | (3<<UCSZ10);
14
15
while(1)
16
{
17
while(!(UCSR1A & (1<<UDRE1)))
18
;
19
UDR1= 'x';
20
}
21
22
}

von Timmo H. (masterfx)


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.

von astalavista (Gast)


Lesenswert?

Ich würde gerne die Schaltung mit einem externen Quarz 8MHz antreiben.

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

von Timmo H. (masterfx)


Lesenswert?

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

von Erik W. (exor)


Lesenswert?

im avrstudio...da gibs im konfigurierungsfenster nen extra reiter für

von astalavista (Gast)


Lesenswert?

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

von spess53 (Gast)


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

von Karl H. (kbuchegg)


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!

von astalavista (Gast)


Lesenswert?

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

von Timmo H. (masterfx)


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?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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 = '

von astalavista (Gast)


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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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

von spess53 (Gast)


Lesenswert?

Hi

>Was kann da das Problem sein.

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

MfG Spess

von astalavista (Gast)


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.
1
ISR (USART1_TX_vect) 
2
{
3
   
4
  while(!(UCSR1A & (1<<UDRE1)))
5
  ;
6
  UDR1= zeichen;
7
        //UCSR1A= (1<<UDRE1);
8
}
9
10
11
ISR (USART1_RX_vect) 
12
{
13
14
  while ( !(UCSR1A & (1<<RXC1)) )
15
  ;
16
  zeichen = UDR1;
17
18
19
  while(!(UCSR1A & (1<<UDRE1)))
20
  ;
21
  UDR1= zeichen;
22
}

MfG

von holger (Gast)


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.

von spess53 (Gast)


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

von astalavista (Gast)


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.
1
ISR (USART1_TX_vect) 
2
{
3
  UDR1= zeichen;
4
}
5
6
7
ISR (USART1_RX_vect) 
8
{
9
  zeichen = UDR1;
10
11
  while(!(UCSR1A & (1<<UDRE1)))
12
  ;
13
  UDR1= zeichen;
14
}

MfG

von Karl H. (kbuchegg)


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.

von astalavista (Gast)


Lesenswert?

Achso, danke.

D.h. stoppen kann ich den ISR-TX wieder mit
1
  while ( !(UCSR1A & (1<<RXC1)) )
2
  ;
3
4
  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;
}

von Karl H. (kbuchegg)


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.
1
ISR (USART1_TX_vect) 
2
{
3
  // nichts. Ist noch völlig uninteressant, wann ein Zeichen rausgegangen ist
4
}
5
6
ISR (USART1_RX_vect) 
7
{
8
// Ist unnötig
9
// Der Interrupt wurde aufgerufen WEIL ein Zeichen empfangen wurde
10
// an dieser Stelle braucht daher nicht getestet werden.
11
// Es ist Faktum, dass ein Zeichen da ist!
12
//
13
//  while ( !(UCSR1A & (1<<RXC1)) )
14
//  ;
15
  zeichen = UDR1;
16
17
18
  while(!(UCSR1A & (1<<UDRE1)))
19
    ;
20
  UDR1= zeichen;
21
}

von astalavista (Gast)


Lesenswert?

Habe mich nur damit gespielt um beide Interrupts zu testen. Trotzdem 
danke

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.