Forum: Mikrocontroller und Digitale Elektronik STM32 VCP über USB Problem


von Patrick L. (crashdemon)


Lesenswert?

Hallo Leute,

ich nutze das STM32 Discovery Board 
(http://www.st.com/web/en/catalog/tools/FM116/SC959/SS1532/PF254044) um 
mir die Daten der darauf befindlichen Sensoren per User USB an den PC zu 
senden. Dafür habe ich das "VirtualComport_Loopback" Beispiel aus der 
STM32_USB-FS-Device_Lib_V4.0.0 auf meine Problemstellung adaptiert. 
Leider will der Code aber nicht wie gedacht funktionieren.

main:
1
int main(void)
2
{ 
3
4
    ...
5
    
6
    Gyro_Init(); // Gyro initialisieren
7
    Acc_Init(); // Acc initialisieren
8
    
9
    SysTick_init(); // Initialisiert die SysTicks
10
    fDt = FDT; // Timebase (CycleTime)
11
    
12
    while(1)
13
    {         
14
        if(sample)
15
        {
16
            GyroReadAngRate(raw_gyro); 
17
            AccReadData(raw_acc);
18
      
19
            if(bDeviceState == CONFIGURED)
20
            {
21
                //CDC_Send_DATA((unsigned char*)buffer, strlen(buffer));
22
23
                sprintf(buffer, "%+.2f,", raw_acc[0]);
24
                USB_SendData(buffer);
25
26
                sprintf(buffer, "%+.2f,", raw_acc[1]);
27
                USB_SendData(buffer);
28
29
                sprintf(buffer, "%+.2f\n\n", raw_acc[2]);
30
                USB_SendData(buffer);                
31
            }        
32
            
33
            sample = 0;
34
        }
35
    }
36
}

USB_SendData
1
void USB_SendData(char *data)
2
{ 
3
    if(packet_sent == 1)
4
    {
5
        CDC_Send_DATA((unsigned char*) data, strlen(data));    
6
    }
7
}

Ich habe das Beispiel so abgeändert das immer nur die Sensordaten 
rausgesendet werden. Allerdings werden diese teilweise falsch 
ausgegeben:

Empfangene Daten:

-329.00,+10.00,-328.00,+12.00,-334.00,+17.00,-329.00,+11.00,-329.00,+13. 
00,+1014.00<\n>
<\n>
+15.00,+1009.00<\n>
<\n>
+12.00,+1012.00<\n>
<\n>
+14.00,+1008.00<\n>

Es scheint mir nach einem Timing Problem, kennt jemand so ein Problem 
oder hat jemand einen Code der meine Problemstellung erfüllt?

von holger (Gast)


Lesenswert?

>Allerdings werden diese teilweise falsch ausgegeben:

Woher denkst du soll jemand wissen welche Ausgabe du
ERWARTET hast? Was ist denn jetzt falsch an der Ausgabe?

von Patrick L. (crashdemon)


Lesenswert?

Wird eig. aus dem Code ersichtlich. Ich würde z.B. immer Zeilen in der 
folgenden Form erwarten:

0.20,102.00,0.39\n\n

Siehe Codeteil:
1
sprintf(buffer, "%+.2f,", raw_acc[0]);
2
USB_SendData(buffer);
3
4
sprintf(buffer, "%+.2f,", raw_acc[1]);
5
USB_SendData(buffer);
6
7
sprintf(buffer, "%+.2f\n\n", raw_acc[2]);
8
USB_SendData(buffer);

von holger (Gast)


Lesenswert?

1
void USB_SendData(char *data)
2
{ 
3
    if(packet_sent == 1)
4
    {
5
        CDC_Send_DATA((unsigned char*) data, strlen(data));    
6
    }
7
}

Jetzt überleg mal was passiert wenn packet_send gleich Null ist.
Richtig: Deine Ausgabe wird nicht gemacht. Das dürfte des Rätsels
Lösung sein;)

von Patrick L. (crashdemon)


Lesenswert?

...nein das ist nicht die Lösung. Vorallem sehr kurzsichtig gedacht. Am 
besten wäre es wenn sich hier Leute äussern die die 
STM32_USB-FS-Device_Lib_V4.0.0 einsetzen und sich damit auskennen.

von holger (Gast)


Lesenswert?

>...nein das ist nicht die Lösung.

Schade.

> Vorallem sehr kurzsichtig gedacht.

Nö, logische Schlussfolgerung. Wenn packet_sent Null ist
wird nichts gesendet. Aus, Basta.

von Uwe B. (derexponent)


Lesenswert?

Patrick L. schrieb:
> Am
> besten wäre es wenn sich hier Leute äussern die die
> STM32_USB-FS-Device_Lib_V4.0.0 einsetzen und sich damit auskennen

mit solchen Äuserungen wäre ich vorsichtig

und holger hat sehr wahrscheinlich recht


versuch mal das hier :
1
void USB_SendData(char *data)
2
{ 
3
    // warte bis letztes Packet komplett gesendet ist
4
    while(packet_sent != 1);
5
6
    // sende neues Packet
7
    CDC_Send_DATA((unsigned char*) data, strlen(data));    
8
9
}

und schreib ob das besser funktioniert

von Patrick L. (crashdemon)


Lesenswert?

Hab die oben angegebene Codeänderung mal ausgetestet. Resultat ist das 
dann gar nichts mehr empfangen wird. Ich hab habe packet_sent auch 
pauschal ausgeschlossen, da ich ja mitunter Daten empfange, diese dann 
aber nicht zwingend vollständig sind (siehe oben).

Für mich sieht das nach einem Timing Problem aus. Vllt. kann man die 
Sachen einfach nicht so schnell hintereinander raussenden und man müsste 
eine Wartezeit zwischen den USB_SendData Aufrufen einfügen?

Der ursprüngliche Code von STM sieht so aus:
1
int main(void)
2
{
3
  Set_System();
4
  Set_USBClock();
5
  USB_Interrupts_Config();
6
  USB_Init();
7
  
8
  while (1)
9
  {
10
    if (bDeviceState == CONFIGURED)
11
    {
12
      CDC_Receive_DATA();
13
      /*Check to see if we have data yet */
14
      if (Receive_length  != 0)
15
      {
16
        if (packet_sent == 1)
17
          CDC_Send_DATA ((unsigned char*)Receive_Buffer,Receive_length);
18
        Receive_length = 0;
19
      }
20
    }
21
  }
22
}

Dort werden die Daten die man vom PC an das Eval Board sendet direkt 
wieder zurück gesendet. Was auch ohne Probleme Funktioniert hat.

Die CDC_Send_DATA Funktion habe ich komnplett von STM übernommen.
1
uint32_t CDC_Send_DATA (uint8_t *ptrBuffer, uint8_t Send_length)
2
{
3
  /*if max buffer is Not reached*/
4
  if(Send_length < VIRTUAL_COM_PORT_DATA_SIZE)     
5
  {
6
    /*Sent flag*/
7
    packet_sent = 0;
8
    /* send  packet to PMA*/
9
    UserToPMABufferCopy((unsigned char*)ptrBuffer, ENDP1_TXADDR, Send_length);
10
    SetEPTxCount(ENDP1, Send_length);
11
    SetEPTxValid(ENDP1);
12
  }
13
  else
14
  {
15
    return 0;
16
  } 
17
  return 1;
18
}

von Uwe B. (derexponent)


Lesenswert?

Patrick L. schrieb:
> Ich hab habe packet_sent auch
> pauschal ausgeschlossen, da ich ja mitunter Daten empfange, diese dann
> aber nicht zwingend vollständig sind

und da liegt halt dein Denkfehler

du hast eine IF-Abfrage vor dem eigentlichen senden
1
if(packet_sent == 1)

solange diese nicht erfüllt ist, kannst du die Funktion "USB_SendData" 
aufrufen sooft du willst...am PC wird nichts ankommen
(das sieht dann halt so aus als ob etwas fehlen würde)

hast du den Quellcode von ST 1:1 übernommen ?
dann müsste im Main.c das hier stehen :
1
uint32_t packet_sent=1;

was du auch probieren kannst ist alles in einem Rutsch zu senden :
1
sprintf(buffer, "%+.2f,%+.2f,%+.2f\n\n", raw_acc[0], raw_acc[1], raw_acc[2]);
2
USB_SendData(buffer);

dann wird halt u.U. der komplett String einmal nicht gesendet
(Vorsicht "bufffer" muss groß genug sein)

oder du machst (wie du schon geschrieben hast)
eine kleine Pause zwischen jedem Sendeaufruf

von Patrick L. (crashdemon)


Lesenswert?

Es klappt jetzt, dazu habe ich jetzt einfach die if(packet_sent == 1) 
Abfrage aus void USB_SendData(char *data) komplett entfernt.

Durch einfügen einer Wartezeit von 1ms nach USB_SendData() klappt auch 
das raussenden ohne Probleme.

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.