Forum: Mikrocontroller und Digitale Elektronik Mikrocontroller drosseln?


von Jan S. (Gast)


Lesenswert?

Hallo,
ich habe folgendes Problem.
Über den Mikrocontroller PIC32MX695F512H möchte ich einen Slave über SPI 
configurieren. Dazu lese ich die Daten aus einem Register (I) und muss 
einen Wert inkrementieren und diesen wiederum in ein anderes Register 
(II) schreiben. Dies geschieht in einer Schleife, bis ein passender Wert 
erreicht ist.

Schaue ich mir die Resultate an, so scheint der Microcontroller zwar 
richtig zu funktionieren, allerdings scheint der Slave nicht so schnell 
auf die Änderung reagieren zu können, wie eine while schleife iteriert 
wird.

Folglich wird zB 10x derselbe (I) Wert eingelesen und darauf mit einem 
Inkrement von (II) reagiert. Sobald sich nun (I) ändert (nach ca. 10-20 
Zyklen) so ist der Wert als wäre der aktuelle (II) Wert verwendet 
worden.

Was kann ich tun?
(Mit 100mal ausgeführten For-Schleifen lässt sich das machen,
find ich aber unelegant.)

von Vlad T. (vlad_tepesch)


Lesenswert?

vor allem hast du vergessen das Datenblatt deines Controllers zu lssen.
Normalerweise muss man der SPI noch sagen, dass sie den Transfer starten 
soll. Via bescreiben eines Steuerregisters.
Weiterhin sollte im Datenblatt stehen, wieviele Takte die SPI braucht, 
um die Daten rauszuschreiben. so lange solltest du auf jeden fall nix 
neues über die SPI versenden.

Dann solltest du das Datenblatt des anderen Controllers studieren und 
schauen, ob er mit der SPI-Freuqenz überhaupt klar kommt und beide 
Controller so konfigurieren, dass es zusammen passt.

von Peter D. (peda)


Lesenswert?

Jan S. schrieb:
> allerdings scheint der Slave nicht so schnell
> auf die Änderung reagieren zu können

Und was steht dazu im Datenblatt des (unbekannten) Slave?
Mein Kristallkugel ist nämlich grad zur Reparatur.

SPI enthält kein Handshake. Deshalb muß man die Timings im Datenblatt 
lesen und einhalten.


Peter

von Jan S. (Gast)


Lesenswert?

Also es handelt sich um einen Capacitance-to-Digital Converter den 
AD7147, welcher automatisch Kapazität misst.
(http://www.analog.com/static/imported-files/data_sheets/AD7147.pdf)
der Teil zu SPI ist auf Seite 33ff.

Der Microcontroller Enthält folgendes zu SPI.
(http://ww1.microchip.com/downloads/en/DeviceDoc/DS-61106F.pdf)

Ich will es im Normalen Master Mode betreiben.(32 Bit)

Was ich momentan nicht mache ist, aktiv in diese Register zu schreiben.
Ich kann mittels einer Bibliotheksfunktion mit dem CDC kommunizieren.
Das hat bisher wunderbar für alles geklappt. Allerdings nun mit dieser 
Schleife macht das eben Probleme.

Ich bin mir nich sicher ob es an der Kommunikation oder nur daran liegt, 
dass der AD zu langsam auf den neuen Registerwert reagiert und somit 
seine Messwerte noch nicht abgeändert hat. (BIAS-Addition)

von Karl H. (kbuchegg)


Lesenswert?

Ich komm ehrlich gesagt mit deiner Fehlerbeschreibung aus dem 
Eröffnungsposting nicht klar.

Kannst du nicht den Codeausschnitt zeigen und auch ein paar echte Daten 
dazu. Dazu dann: Was ist an den Daten falsch, wie sollten sie richtig 
aussehen und was ist deine Theorie was da passiert.

Deine ganze Fehlerbschreibung im Eröffnungsposting klingt für mich nach:
Warum vergleichst du nicht den Wert aus (I) mit demselben Wert aus dem 
unmittelbar vorhergehenden Durchgang und unternimmst nichts, soalnge die 
beiden gleich sind (oder eine voreingestellte ANzahl Durchläufen 
abgearbeitet wurde). Aber ich bin mir nicht sicher, ob ich dir das 
vorschlagen soll, weil ich eben die Fehlerbeschreibung nicht 100% 
verstanden habe.

von Ago (Gast)


Lesenswert?

Vielleicht einfach mal die "9-36ms update rate" abwarten (s. Seite 3 
uter Update Rate)?

von Jan S. (Gast)


Angehängte Dateien:

Lesenswert?

Das mit der update rate ist, wann ein neues CDC-Resultat gemessen wird.
Da ich ja eben dieses Register auslese, kann das zusammenhängen.
Wie könnte ich diese Zeit mit einem Microcontroller abwarten?
wait oder sleep ??

Also ich hab mal n bisschen Zeit gebraucht, um das alles zu analysieren.
Irgendwie gabs ständig anderes Verhalten.
nun schaut euch diesen Code mal an. Das ist noch nicht mal
die Funktion die ich machen will, aber irgendwas scheint an dem 
vergleich
nicht zu funktionieren. Die UARTFunktionen senden das alles an einen PC.
Dort wird das mit HTERM aufgefangen.

1
  int stageresult;
2
  short i = 0;
3
   // for nur, da am Anfang Mistwerte und nicht die wirklichen kommen
4
    for (i=0; i<100; i++){
5
      readViaSPIfromCDC_single(STAGE0, &stageresult);
6
      sendPackageViaUART(UART1A,stageresult);
7
      UARTSendDataByte ( UART1A, '\n');
8
    }
9
10
//1111 signalisiert den Beginn der Schleife
11
  sendPackageViaUART(UART1A,0x1111);
12
  UARTSendDataByte ( UART1A, '\n');  
13
    // ist der Wert also > 0x8000, dann soll einfach der Datenstrom unendlich lange ausgegeben werden.
14
  while(stageresult > 0x8000){
15
16
      readViaSPIfromCDC_single(STAGE0, &stageresult);
17
      sendPackageViaUART(UART1A,stageresult);
18
      UARTSendDataByte ( UART1A, '\n');
19
  }
20
//2222 signalisiert ende der schleife.
21
sendPackageViaUART(UART1A,0x2222);

Und hier nun, was in dem HTERM ausgegeben wird im Anhang.
Oben sind noch Werte aus der For Schleife,
zwischen 1111 und 2222 findet ihr einen Eintrag.
Manchmal ist da auch keiner. Das variiert.

Jedenfalls stellen wir fest das 0x87.. > 0x8000
Dieser Wert bleibt auch nach der Schleife erhalten.
Jedoch springt er entweder garnicht rein (sieht man hier nicht)
oder eben nur einmal!!
Was funktioniert hier nicht?
Darf man mit HEXwerten nicht vergleichen??

von Jan S. (Gast)


Lesenswert?

Okay dieser Fehler lag an dem int.

Es muss ein unsigned int sein dann geht das.
Ich melde mich sobald ich mehr weiß.
Danke für eure Hilfe bisher.

von Jan S. (Gast)


Angehängte Dateien:

Lesenswert?

Also nochmals.

So jetzt nochmal.
Über UART wird das an den PC geschickt und mit HTERM empfangen.
1
        unsigned short stageresult;
2
  unsigned short offsetresult;
3
  unsigned short offset = 0x0100;
4
  unsigned short Pos_Offset = 0x000;
5
6
7
  short i = 0;
8
        //for ist egal. das is nur, damit richtige werte kommen am Anfang
9
    for (i=0; i<100; i++){
10
      readViaSPIfromCDC_single(ADCRESULT_S0+stage, &stageresult);
11
      sendPackageViaUART(UART1A,stageresult);
12
      UARTSendDataByte ( UART1A, '\n');
13
    }
14
15
16
//1111 als start merkpunkt
17
  sendPackageViaUART(UART1A,0x1111);
18
  UARTSendDataByte ( UART1A, '\n');  
19
  while(stageresult > 0x8340){
20
21
      Pos_Offset = Pos_Offset + offset;
22
      writeViaSPItoCDC_single(STAGE0_CONNECTION+8*stage+2,Pos_Offset);
23
      
24
//      for (i = 0; i<1000; i++)
25
        readViaSPIfromCDC_single(ADCRESULT_S0+stage, &stageresult);
26
        readViaSPIfromCDC_single(STAGE0_CONNECTION+8*stage+2, &offsetresult);
27
        
28
      sendPackageViaUART(UART1A,stageresult);
29
      sendPackageViaUART(UART1A,offsetresult);
30
      UARTSendDataByte ( UART1A, '\n');
31
32
33
  }
34
//2222 als Endmerkpunkt
35
  sendPackageViaUART(UART1A,0x2222);
36
}

Hier sieht man wie der offset hochgezählt wird,
da der CDC mit der Änderung nicht mitkommt.

Mit der for-Schleife geht es. (während 1000x auslesen, reicht die Zeit 
für den CDC sich anzupassen)
Wie geht es eleganter? (Sleep/wait??)

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.