Forum: Mikrocontroller und Digitale Elektronik Atmega zu schnell


von Andre B. (andre-atmega168)


Lesenswert?

Hallo,

über die UDRO Schnittstelle übergebe ich eine 16 bit Temperatur. Die ich 
in Labview über die Visa Schnisttelle einlese. Das Problem ist 
folgendes:
Labview initialiesiert die Visa Schnittstelle bei jedem 
Schleifendurchgang neu, so dass schon ca. 1000 Bytes am Port der Visa 
Schnittstelle anliegen bevor die abgeolt werden können. Die Schittstelle 
ist also überladen, weil der uC viel schneller ist. Außerdem wird die 16 
bit Temperatut in Labview manchmal falsch angezeigt. Mal kommt das 
2.Byte vor dem 1.Byte mal umgekehrt.
Kann man den µC mit Labview synchroniesieren oder gibt es noch andere 
Mölglichlkeiten?
Kann mir jemand helfen?
1
sendSPI:
2
  ldi  r20,0b00101110  ; master [clk(5) mosi(3)  ss(2)]=outp
3
  out  DDRB,r20
4
  in  r16,SPSR  ; dummy read
5
  ldi  r20,0b11111111  ; Befehl[FF] für Temp-Sensor(Temp senden)
6
  cbi  portb,2  ; bit 2 von portb auf 0 = cs low
7
  out  spdr,r20  ; 1.byte senden
8
  ret
9
10
receiveSPI:
11
  in  r16,SPSR
12
  sbrs  r16,SPIF  ; warte auf transmitflag
13
  rjmp  receiveSPI
14
  ;sbi  portb,2  ; cs auf high
15
  in  r18,spdr  ; 1.Byte wird empfangen
16
  out  spdr,r20  ; 2.Byte senden
17
  ret
18
receiveSPI2:
19
  in  r16,SPSR
20
  sbrs  r16,SPIF  ; warte auf transmitflag
21
  rjmp  receiveSPI2
22
  sbi  portb,2  ; cs auf high
23
  in  r19,spdr  ; 2.Byte wird empfangen
24
25
26
27
  ret
28
29
30
;--------------------------------------------------------------
31
putTemp:
32
  lds  r16,UCSR0A
33
  sbrs  r16,5  ; Senderegister nicht leer?
34
  ret    ; ... dann Rücksprung
35
  sts  UDR0,r18
36
  sts  UDR0,r19
37
38
  ret    ; nächstes Zeichen

von Benedikt K. (benedikt)


Lesenswert?


von Andre B. (andre-atmega168)


Lesenswert?

hallo,

hat jemand vielleicht schon ein Beispiel in Quellcode-Form.
bin sehr unter Zeitdruck. DANKE

von Maik F. (sabuty) Benutzerseite


Lesenswert?

Polling?

Irgendein Zeichen an den µC gesendet, nachdem LabView die Schnittstelle 
initialisiert hat, zB ein "T". Darauf hin schickt der µC die 16 Bit an 
den PC.

von Andre B. (andre-atmega168)


Lesenswert?

ja polling!

das mache ich schon, schicke bei jedem Schleifendurchgang in Labview die 
PWM-Signalbreite an den µC und lese eine Temperatur aus. Habe aber immer 
ein Dreher zwischen dem 1.Byte und dem 2.Byte.

1
sendSPI:
2
  ldi  r20,0b00101110  ; master [clk(5) mosi(3)  ss(2)]=outp
3
  out  DDRB,r20
4
  in  r16,SPSR  ; dummy read
5
  ldi  r20,0b11111111  ; Befehl[FF] für Temp-Sensor(Temp senden)
6
  cbi  portb,2  ; bit 2 von portb auf 0 = cs low
7
  out  spdr,r20  ; 1.byte senden
8
  ret
9
10
receiveSPI:
11
  in  r16,SPSR
12
  sbrs  r16,SPIF  ; warte auf transmitflag
13
  rjmp  receiveSPI
14
  ;sbi  portb,2  ; cs auf high
15
  in  r18,spdr  ; 1.Byte wird empfangen
16
  out  spdr,r20  ; 2.Byte senden
17
  ret
18
receiveSPI2:
19
  in  r16,SPSR
20
  sbrs  r16,SPIF  ; warte auf transmitflag
21
  rjmp  receiveSPI2
22
  sbi  portb,2  ; cs auf high
23
  in  r19,spdr  ; 2.Byte wird empfangen
24
25
26
27
  ret
28
29
30
31
32
33
;--------------------------------------------------------------
34
putTemp:
35
  lds  r16,UCSR0A
36
  sbrs  r16,5  ; Senderegister nicht leer?
37
  ret    ; ... dann Rücksprung
38
  sts  UDR0,r18
39
  sts  UDR0,r19
40
41
  ret    ; nächstes Zeichen
42
43
getPWM:
44
  lds  r16,UCSR0A
45
  sbrs  r16,7  ; Alle Daten im UDR-Register...
46
  ret    ; ... wenn nicht, dann Rücksprung
47
  lds  serdatin,UDR0  ; ... wenn doch,  dann Zeichen abholen
48
  sts  OCR1AL,serdatin  ; PWM bedienen
49
50
  ret

von Uwe (Gast)


Lesenswert?

Hi!
Bin ja bischen doof, aber kannste mir deine Denkweise an der Stelle mal 
erklären:

>putTemp:
>  lds  r16,UCSR0A
>  sbrs  r16,5  ; Senderegister nicht leer?
>  ret    ; ... dann Rücksprung
>>  sts  UDR0,r18
>>  sts  UDR0,r19

Ohne nachzufragen schreibst du 2 Byte nach UDR??

MFG Uwe

von Andre-Atmega168 (Gast)


Lesenswert?

Genau. Die beiden Bytes schicke ich ins UDR0 und übergebe diese in 
Labview, allerdings habe ich dann fast immer eine Dreher in der 
Temperatur(wie oben beschrieben)

von André (Gast)


Lesenswert?

Du koenntest zwischendrin auch einfach mal warten, bis der Uart fertig 
damit ist, das erste Byte zu senden :D. Siehe Datenblatt.

von Andre-Atmega168 (Gast)


Lesenswert?

der Uart wird doch so schnell berschrieben, so dass die Daten in Labview 
gar nicht zu schnell abgeholt werden. oder meinst du was anderes

von Stefan E. (sternst)


Lesenswert?

Nein, die Frage ist, woher weißt du beim zweiten "sts  UDR0,rXX", dass 
UDR0 schon wieder frei ist?

Und wenn die beiden Bytes verkehrt herum ankommen, dann sendest du sie 
entweder verkehrt herum, oder du hast einen Fehler im Ablauf und LabView 
und µC sind nicht mehr synchron.

von Andre-Atmega168 (Gast)


Lesenswert?

die temperatur wird sporadisch mal richig mal falsch angezeigt.
Das heisst, entweder kommt das 1.Byte vor dem 2.Byte oder umgekehrt.
Die Reihenfolge im Assembler ist auch richtig.

von Stefan E. (sternst)


Lesenswert?

Dann korrigiere erstmal das UDR0-Handling, und schaue was dann kommt.

von Peter D. (peda)


Lesenswert?

Andre B. wrote:
> Außerdem wird die 16
> bit Temperatut in Labview manchmal falsch angezeigt. Mal kommt das
> 2.Byte vor dem 1.Byte mal umgekehrt.

Woher soll den Labview auch wissen, welches das 1. und welchse das 
2.Byte ist?
Labview kann ja nicht hellsehen.

Dein Problem ist, Du hast kein Protokoll.

Ein einfaches Protokoll wäre, der AVR sendet nur auf Anforderung.
Z.B. Labwiev sendet ein '?' und dann erst sendet der AVR. Damit weiß 
dann Labview, welches das 1. Byte ist.


Peter

von Peter D. (peda)


Lesenswert?

Uwe wrote:

>>putTemp:
>>  lds  r16,UCSR0A
>>  sbrs  r16,5  ; Senderegister nicht leer?
>>  ret    ; ... dann Rücksprung
>>>  sts  UDR0,r18
>>>  sts  UDR0,r19
>
> Ohne nachzufragen schreibst du 2 Byte nach UDR??

Stimmt, der Code ist falsch.
Wenn man 2 Byte schreiben will, muß man auf das TXC0 Bit testen.
Das geht aber schief, wenn noch garnichts gesendet wurde.

Daher besser ne putchar-Funktion schreiben und die zweimal aufrufen.


Peter

von Andre-Atmega168 (Gast)


Lesenswert?

Das habe ich ja soweit verstanden. Es hapert bei mir aber noch an der 
Umsetzung. Kann mir jemand nen Beispiel schicken. Danke.

von Stefan E. (sternst)


Lesenswert?

Peter Dannegger wrote:

> Dein Problem ist, Du hast kein Protokoll.

Ich dachte, er hätte eins, weil er sagte:
> das mache ich schon, schicke bei jedem Schleifendurchgang in Labview die
> PWM-Signalbreite an den µC und lese eine Temperatur aus.

von Andre-Atmega168 (Gast)


Lesenswert?

richtig, so mache ich das auch, es funktioniert aber nicht.

nochmal der Code.
1
getPWM:
2
  lds  r16,UCSR0A
3
  sbrs  r16,7  ; Alle Daten im UDR-Register...
4
  ret    ; ... wenn nicht, dann Rücksprung
5
  lds  serdatin,UDR0  ; ... wenn doch,  dann Zeichen abholen
6
  sts  OCR1AL,serdatin  ; PWM bedienen
7
8
  ret
9
10
putTemp:
11
  lds  r16,UCSR0A
12
  sbrs  r16,5  ; Senderegister nicht leer?
13
  ret    ; ... dann Rücksprung
14
  sts  UDR0,r18
15
  sts  UDR0,r19
16
17
  ret    ; nächstes Zeichen

von Stefan E. (sternst)


Lesenswert?

An dem Code ist nicht zu erkennen, ob du irgendein Protokoll hast, z.B. 
ob du die Temperatur immer sendest, nachdem du den neuen PWM-Wert 
bekommen hast.

von Thilo M. (Gast)


Lesenswert?

Ich hatte das Problem auch mal. Bin jetzt dazu übergegangen, die 
Messwerte in ASCII zu übertragen. LabView kann die prima einlesen, auch 
bei 115200 Baud keine Fehler drin, da ein eindeutiger Rahmen das 
Datenpaket kennzeichnet (\n zum Schluss und <spc> als Trennzeichen).

von Uwe (Gast)


Lesenswert?

Hi!

Wie wäre es denn so:

putTemp:
lds   r16,UCSR0A
sbrs  r16,UDRE  ; Senderegister nicht leer?
rjmp  putTemp    ; ... dann Rücksprung
sts   UDR0,r18
Byte2:
lds   r16,UCSR0A
sbrs  r16,UDRE  ; Senderegister nicht leer?
rjmp  Byte2
sts   UDR0,r19
ret

Viel Erfolg, Uwe

von Andre-Atmega168 (Gast)


Lesenswert?

hi,
also den dreher habe ich ich nicht mehr.(siehe die letzten 4 Zeilen bei 
"getPWM". Allerdings kriege ich periodisch immer mal wieder eine 0 
Übergeben. Die Visaschnittstelle gibt dann auch 0Bytes am Port an. Woher 
kommt die null?




getPWM:
  lds  r16,UCSR0A
  sbrs  r16,7  ; Alle Daten im UDR-Register...
  ret    ; ... wenn nicht, dann Rücksprung
  lds  serdatin,UDR0  ; ... wenn doch,  dann Zeichen abholen
  sts  OCR1AL,serdatin  ; PWM bedienen

  lds  r16,UCSR0A
  sbrs  r16,7  ; Alle Daten im UDR-Register...
  rcall putTemp
  rcall mainloop

  ret

putTemp:
  lds  r16,UCSR0A
  sbrs  r16,5  ; Senderegister nicht leer?
  ret    ; ... dann Rücksprung
  sts  UDR0,r18
  sts  UDR0,r19

  ret    ; nächstes Zeichen

von Andre-Atmega168 (Gast)


Lesenswert?

Hat keiner ne Idee

von Stefan E. (sternst)


Lesenswert?

> Hat keiner ne Idee

Wie wäre es, wenn du erstmal das beseitigst, was dir schon mehrfach 
genannt wurde?

> sts  UDR0,r18
> sts  UDR0,r19

von Andre-Atmega168 (Gast)


Lesenswert?

das habe ich schon gemacht, ändert aber auch nix

von Uwe (Gast)


Lesenswert?

Hi!
>das habe ich schon gemacht, ändert aber auch nix
Das sah aber in deinem letzten post nicht so aus.

Sende mal feste Werte, nicht das bei deiner Einleserei was schief geht.

Viel Erfolg, Uwe

von Simon K. (simon) Benutzerseite


Lesenswert?

Andre-Atmega168 wrote:
> das habe ich schon gemacht, ändert aber auch nix

Zeig mal den berichtigten Code.

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.