Forum: Mikrocontroller und Digitale Elektronik PIC18F2550 USB und RS232


von Ron N. (blitzgeist)


Lesenswert?

Hallo zusammen,

habe folgendes Verständnisproblem. Wie ist das genau mit USB und RS232.
Ich sende Daten via USB in den PIC und nöchte diese via RS232 
weitersenden. Muss beim senden via RS232 das interne USB Modul des PIC´s 
deaktiviert werden?

lg,
blitzgeist

von Bitz Antwort (Gast)


Lesenswert?


von Gast (Gast)


Lesenswert?

Nein, dass USB-Modul muß nicht abgeschaltet werden. Die serielle 
Schnittstelle des PICs ist unabhängig.

von Ron N. (blitzgeist)


Lesenswert?

Die Seite kenn ich mitlerweile in und auswendig. Ist echt ne sehr gute 
Seite jedoch wird da auch nicht meine Frage beantwortet.
Versuche es mal ein bischen genauer zu beschreiben...

von Ron N. (blitzgeist)


Lesenswert?

In der Firmware von MP gibt es u.a. zwei Funktionen USBModuleEnable und 
USBModuleDisable. USBModuleEnable macht folgendes: usb_device_state = 
ATTACHED_STATE; d.h. Enable module & attach to bus
und USBModuleDisable macht: Disable module & detach from bus, 
usb_device_state = DETACHED_STATE;

Jetzt gibt es in einer anderen Funktion namens BlinkUSBStatus den 
Codeausschnitt:
.
.
.
 if(UCONbits.SUSPND == 1)
    {
        if(led_count==0)
        {
            mLED_1_Toggle();
            mLED_2 = mLED_1;        // Both blink at the same time
        }//end if
    }
    else
    {
        if(usb_device_state == DETACHED_STATE)
        {
            mLED_Both_Off();

            PICDEMFSUSBDemoBoardTest();
        }
        else if(usb_device_state == ATTACHED_STATE)
        {
            mLED_Both_On();
        }
.
.
.

Der Funktionsauffruf: PICDEMFSUSBDemoBoardTest() führt ein RS232 Setup 
durch  und startet die Übertragung via RS232.
ABER: PICDEMFSUSBDemoBoardTest() wird erst aufgerufen wenn 
usb_device_state == DETACHED_STATE!!! Dann ist doch aber mein USB Modul 
im PIC deaktiviert? Wie soll das genau funktionieren?

Versuche es schon seit Stunden zu vertehen, vergebens...
Wäre echt nett wenn jemand ein Paar erklärende Worte findet.

lg,
blitzgeist

von Ron N. (blitzgeist)


Lesenswert?

@gast
aber laut fw wird doch das USB Modul ausgeschaltet.

Wie rufe ich überhaupt die Kommunikation auf, dass über RS232 gesendet 
werden soll? Schaffe ich mir da ein Command namens SendViaRS232? Wenn 
dieser Command in meiner switch/case Anweisung ankommt, in den 
entsprechenden case Zweig geht, und da die RS232 initialisiert und die 
Daten versendet? Aber wie gesagt, laut fw muss ich das interne USB Modul 
deaktivieren (usb_device_state == DETACHED_STATE).

von Gast (Gast)


Lesenswert?

Kann ja nicht wissen, dass du von Microchips Firmware sprichst.

Das Problem ist, wenn das USB-Modul aktiviert ist und eine Übertragung 
über RS232 erfolgt, welche ja deutlich länger braucht, als ein 
USB-Transfer, dann bleibt für das Hauptprogramm nicht mehr genug Zeit, 
um die State-Machine für die USB-Kommunikation zu bedienen. Es käme 
somit zu einem sofortigen Abbruch und der PIC würde aus der 
Systemsteuerung verschwinden. Das steht auch in irgendeinem PDF von 
Microchip, dass in der USB-Schleife nichts gemacht werden soll, was 
länger braucht.

Ich hoffe, das war einigermaßen verständlich.

von Ron N. (blitzgeist)


Lesenswert?

@Gast
Ja benutze MCHPFSUSB. Aber wenn das USB Modul deaktiviert ist bekommt 
dann der PIC überhaupt noch Spannung, wenn es ein bus power device 
werden soll?

von Gast (Gast)


Lesenswert?

Ich denk schon, die 5V werden doch vom Host immer geliefert. Schließlich 
muß ein neu angeschlossenes Gerät ja auch Saft bekommen.

von Ron N. (blitzgeist)


Lesenswert?

Klingt logisch.
Und was meinst du hierzu?

Wie rufe ich überhaupt die Kommunikation auf, dass über RS232 gesendet
werden soll? Schaffe ich mir da ein Command namens SendViaRS232? Wenn
dieser Command in meiner switch/case Anweisung ankommt, in den
entsprechenden case Zweig geht, und da die RS232 initialisiert und die
Daten versendet?

Denke das ist ein möglicher Ansatz, oder?

von snwoman (Gast)


Lesenswert?

na von Microchip hab ich eine SW, die "CDC RS-232 Emulation Tutorial 
Instructions" heisst und für ihre 18er-PICs mit USB geschrieben ist. 
getestet habe ich sie noch nie, aber ich denke USB und RS232 kann man 
gleichzeitig brauchen ...beid der performance kommt es halt darauf an, 
wie die SW geschrieben wird.

von holger (Gast)


Lesenswert?

@Ron

// For board testing purpose only
void PICDEMFSUSBDemoBoardTest(void);

Das ist tatsächlich nur eine Funktion zum testen des
Demoboards von Microchip. Soweit ich weiß hat das ein
eigenes Netzteil. Da in der Funktion solche Warteschleifen stehen

        while(!Switch2IsPressed());

die zu einer längeren Unterbrechung der USB Routinen
führen könnten (was man wie Gast ja schon sagte nicht darf),
wird diese Routine nur aufgerufen wenn der PIC NICHT am
USB Port angeschlossen ist. Spannung bekommt er aber weiter
aus dem Netzteil. Somit macht DETACHED_STATE schon Sinn.
Sobald du den PIC an den USB Port anschließt kannst du die
Routine aber nicht mehr aufrufen.

von Ron N. (blitzgeist)


Lesenswert?

Danke schon mal für eure Antworten=)
Mir ist das immernoch ein wenig unklar. Ich habe nun in der docu zu 
diesem Demo Board von MCHP gelesen (steht auf im Datenblatt des PICs), 
dass über das UCONbits.USBEN ein simulierendes trennen des PIC´s als USB 
device erzeugen kann. Für was ist das gut? Und wenn man sich mal die 
Firmware von MCHP und zwar genau die im Verzeichnis MCHPFSUSP\fw\demo 
anschaut, frage ich mich WO hier der if Zweig

if(usb_device_state == DETACHED_STATE){
mLED_Both_Off();
PICDEMFSUSBDemoBoardTest();
}

aufgerufen wird. Ok, klar, wenn man den PIC vom BUS trennt. Man trennt 
ihn aber doch nicht physikalisch sondern nur über UCONbits.USBEN = 0, 
oder??????
Wenn ja, WO wird das in der fw gemacht?

Und, mal ne generelle Frage: Muss ich also immer, wenn ich was über 
RS232 senden möchte den PIC in den usb_device_state == DETACHED_STATE 
bringen? Wie ich nun aus euren Beiträgen herausgelesen habe, hält die fw 
MCHPFSUSP\fw\demo die USB routinen an, solange via RS232 
gesendet/empfangen wird, an.
Wäre nett, wenn ihr mir weiter helfen könntet.

lg
blitzgeist

von Kloberscht (Gast)


Lesenswert?

Hi,

ist schon etwas länger her bei mir, dennoch versuche ich es mal.

Du hast die main(void), in der läuft als Endlosschleife
1
while(1)
2
{ 
3
  USBTasks();
4
  ProcessIO();      
5
}

Wobei in USBTasks() zwei Dinge geschehen. Zum einen wird mittels der 
Funktion USBCheckBusStatus() überprüft, ob ein Gerät angeschlossen ist. 
Hierzu hat du zwei Möglichkeiten: entweder über einen Spannungspegel an 
einem IO-Pin des PICs, oder aber unabhängig davon, also rein durch die 
Firmware. Außerdem werden in USBTasks() sämtliche USB-relevanten 
Interrupts ausgewertet. Die Funktion USBTasks() darf daher auf keinen 
Fall lange unterbrochen werden. Wie lange, kann ich dir leider nicht 
sagen. Solltest du es herausfinden, bitte schreien :)

In ProcessIO() kannst du nun deine Sachen reinschreiben, 
Tastenauswertung oder Displayansteuerung, um nur zwei Beispiele zu 
nennen. Auch kannst du in ProcessIO() natürlich deine RS232-Routine 
reinbasteln.

Auf keinen Fall würde ich den PIC in den DETACHED_STATE versetzen, da 
sich dadurch der PIC ja auch jedesmal am PC neu an- und abmeldet. 
Theoretisch kein Problem, nur wie das halt so ist, es funktioniert 
selten 100%. Aus eigener Erfahrung kann ich sagen, dass es manchmal 
vorkommt, dass sich der PIC nicht mehr anmeldet. Nur ein Totalreset 
rettet die Situation. Ich bezweifle, dass es am Betriebssystem des PCs 
liegt, da ich das Problem sowohl unter Linux als auch Windows beobachtet 
habe. Scheint wohl eher was mit der Firmware des PICs nicht in Ordnung 
zu sein, oder aber sogar mit dem Host-Controller auf meinem Mainboard; 
keine Ahnung.

Also daher versuche deine RS232-Routine so zu schreiben, dass sie 
längere  Ausgaben nicht an einem Stück macht. Lege einen Puffer an, 
schreibe in diesen deinen Text und sende die Daten häppchenweise, 
vielleicht sogar interruptgesteuert. Keine Ahnung, ob das in deinem Fall 
funktioniert. Du hast ja auch leider nichts geschrieben, wieviel du 
senden willst.

BTW: ich finde die Firmware von Microchip extrem unübersichtlich und 
shlecht dokumentiert.

von Kloberscht (Gast)


Lesenswert?

Das wäre übrigens mal ne nette Sache für das Wiki: komplette Analyse und 
Erklärung des USB-Frameworks von Microchip.

von holger (Gast)


Lesenswert?

@Ron

>aufgerufen wird. Ok, klar, wenn man den PIC vom BUS trennt. Man trennt
>ihn aber doch nicht physikalisch sondern nur über UCONbits.USBEN = 0,
>oder??????
>Wenn ja, WO wird das in der fw gemacht?

NIRGENDS !

>Und, mal ne generelle Frage: Muss ich also immer, wenn ich was über
>RS232 senden möchte den PIC in den usb_device_state == DETACHED_STATE
>bringen?

Nein, natürlich nicht !

Geh endlich aus diesem verdammten Demoprogramm raus.
Sieh dir die Beispiele für HID oder CDC an.

von Ron N. (blitzgeist)


Lesenswert?

Vielen Dank für deine ausführliche Information. Sehr hilfreich 
Kloberscht. Nun was mir ein wenig zu bedenken gibt, ist, dass man die 
USB routine nur für eine gewisse Zeit unterbrechen darf. Für was ist 
dann der isochrone Transfer gut, welcher Echtzeit unterstützt?
Angenommen ich habe ein System, das sagen wir mal 30 Minuten Daten über 
RS232 an den PIC sendet und von da aus via USB an den Host (PC). Dann 
geht das nur, wie du schon sagst, über kleine interruptgesteuerte 
Datenpakete?
Hmmm...
Also das würde mich brennden interessieren wie lange man die USB Routine 
unterbrechen darf. Woher stammt eigendlich diese Aussage? Man kann doch 
bestimmt mal bei einen technischen support von Microchip anfragen was 
das mit der Unterbrechung der USB routine betrifft.

lg.
blitzgeist


@holger
HID und CDC ist aber nichts für meine Anwendung. Ich benötige USB FS 
also 12MBit/s, was mit HID und CDC(emulator) ja nicht möglich ist. Für 
mich kommt nur die MCHP Custom Driver fw in Frage.
Communication Device Class (CDC) firmware

CDC auf Microchip:
The Communication Device Class firmware is the most direct way or 
migrating a serial port (legacy) application to USB. In fact this 
firmware provides direct emulation of a serial port on PC running 
Windows 2K and Windows XP. As the PIC18F4550 is attached to the PC, a 
virtual COMx port is created. All PC software using a COM1-4 port will 
work without modifications with the virtual COM port if only at a much 
higher speed (approx 1Mbit/s)

PROS: free, simple to use, easy migration from serial port applications

CONS: data transfer speed limited to about 1Mbit/s, no hardware 
handshake emulation (not necessary)

Memory requirements: about 4K bytes

Windows drivers: no driver required (Windows 2K/XP), xxx.inf file must 
be supplied
.
.
.

von Bernd R. (Firma: Promaxx.net) (bigwumpus)


Lesenswert?

Ähm,
vielleicht verpasse ich etwas,
aber IMHO können USB- und EUSART-Hardware gleichzeitig laufen.
Die Int-Routinen für den UART können gar nicht lange dauern, um den 
USB-Part auszubremsen.
Warum also die (Software-)emulierten Ports verwenden ?

von Ron N. (blitzgeist)


Lesenswert?

@Bernd Rüter: das klingt doch etwas ermutigend =) Gut, denke mir auch 
das die Init-Routine für einen EUSART nicht langen andauern, aber was 
ist wenn ich ca. 30 Minuten z.B. eine Messung via RS232 aufnehme? Wird 
dann zu lange die USBTasks() unterbrochen? Ich habe es noch nicht auf 
der HW ausprobiert, aber ist das so?

Was mir auch aufgefallen ist in der Firmware MCHPFSUSB\fw\Demo wird 
mittels while(!Switch2IsPressed()); quasi die USBTasks() für eine 
unendliche Zeit unterbrochen, bis eben der User den Taster betätigt und 
denke die Software wird sich auch nicht aufhängen.

Also Bernd, meinst du USB und EUSART können parallel arbeiten? Und was 
hat das  dann mit der MCHPFSUSB\fw\Demo aufsich? bezüglich
1
 if(UCONbits.SUSPND == 1)
2
    {
3
        if(led_count==0)
4
        {
5
            mLED_1_Toggle();
6
            mLED_2 = mLED_1;        // Both blink at the same time
7
        }//end if
8
    }
9
    else
10
    {
11
        if(usb_device_state == DETACHED_STATE)
12
        {
13
            mLED_Both_Off();
14
15
            PICDEMFSUSBDemoBoardTest();
16
        }
17
        else if(usb_device_state == ATTACHED_STATE)
18
        {
19
            mLED_Both_On();
20
        }

lg,
blitzgeist

P.S. was meinst du bitte mit IMHO?

von holger (Gast)


Lesenswert?

@Ron
>Danke trotzdem für deine Antworten, wäre aber noch sehr hilfreich wenn
>du mir sagen würdest, wie es jetzt nun ist. Wo wird denn nun das
>UCONbits.USBEN gesetzt?

usbdrv.c nimm einen Texteditor mit Suchfunktion.

>Was mir auch aufgefallen ist in der Firmware MCHPFSUSB\fw\Demo wird
>mittels while(!Switch2IsPressed()); quasi die USBTasks() für eine
>unendliche Zeit unterbrochen, bis eben der User den Taster betätigt und
>denke die Software wird sich auch nicht aufhängen.

USBTasks() wird nicht unterbrochen. Warum nicht ? Es wird gar nicht
aufgerufen. Warum nicht ?
PICDEMFSUSBDemoBoardTest(); wird nur aufgerufen wenn keine
USB Verbindung vorhanden ist.

        if(usb_device_state == DETACHED_STATE)
        {
            mLED_Both_Off();

            PICDEMFSUSBDemoBoardTest();
        }

Das hier: while(!Switch2IsPressed());
steht nur in PICDEMFSUSBDemoBoardTest();
Das wird nur dann aufgerufen wenn Programm nicht hat Verbindung
mit USB. Du mich jetzt können verstehen ?


Man bist du lernresistent.

von holger (Gast)


Lesenswert?

>@holger
>HID und CDC ist aber nichts für meine Anwendung. Ich benötige USB FS
>also 12MBit/s, was mit HID und CDC(emulator) ja nicht möglich ist. Für
>mich kommt nur die MCHP Custom Driver fw in Frage.

Du glaubst doch nicht ernsthaft das du mit einem lahmen PIC
auch nur annähernd 12MBit/s schaffen kannst ? So über den
Daumen 1MB/s. Jede us soll ein Byte aus dem PIC tröpfeln.
Bei einer softwarebasierten USB Lösung. Du kannst froh sein
wenn du da 100kB/s raus kriegst.

von Gast (Gast)


Lesenswert?

Geh vielleicht auch mal auf forum.microchip.com, dort sind sehr 
kompetente Leute, u. a. auch Ingenieure von Microchip.

> Bei einer softwarebasierten USB Lösung. Du kannst froh sein
> wenn du da 100kB/s raus kriegst.

Der PIC18Fx550 hat einen USB-FS-Transceiver eingebaut, 100kB/s ist kein 
Problem.

von Ron N. (blitzgeist)


Lesenswert?

Moin zusammen,

@holger: ich glaube ernsthat dass man mit den PICs 18F2455, 2550, 4455, 
4550 12MBit/s hinbekommt. Es heißst ja nicht umsonst PIC´s mit FS auf 
der Microchip Seite.

>USBTasks() wird nicht unterbrochen. Warum nicht ? Es wird gar nicht
>aufgerufen.

USBTasks() wird IMMER aufgerufen.
1
void main(void)
2
{
3
    InitializeSystem();
4
    while(1)
5
    {
6
        USBTasks();         // USB Tasks
7
        ProcessIO();        // See user\user.c & .h
8
    }//end while
9
}//end main
Von dort aus geht es zu  USBCheckBusStatus();
1
void USBCheckBusStatus(void)
2
{
3
    /**************************************************************************
4
     * Bus Attachment & Detachment Detection
5
     * usb_bus_sense is an i/o pin defined in io_cfg.h
6
     *************************************************************************/
7
    #define USB_BUS_ATTACHED    1
8
    #define USB_BUS_DETACHED    0
9
10
    if(usb_bus_sense == USB_BUS_ATTACHED)       // Is USB bus attached?
11
    {
12
        if(UCONbits.USBEN == 0)                 // Is the module off?
13
            USBModuleEnable();                  // Is off, enable it
14
    }
15
    else
16
    {
17
        if(UCONbits.USBEN == 1)                 // Is the module on?
18
            USBModuleDisable();                 // Is on, disable it
19
    }//end if(usb_bus_sense...)
20
    
21
    /*
22
     * After enabling the USB module, it takes some time for the voltage
23
     * on the D+ or D- line to rise high enough to get out of the SE0 condition.
24
     * The USB Reset interrupt should not be unmasked until the SE0 condition is
25
     * cleared. This helps preventing the firmware from misinterpreting this
26
     * unique event as a USB bus reset from the USB host.
27
     */
28
    if(usb_device_state == ATTACHED_STATE)
29
    {
30
        if(!UCONbits.SE0)
31
        {
32
            UIR = 0;                        // Clear all USB interrupts
33
            UIE = 0;                        // Mask all USB interrupts
34
            UIEbits.URSTIE = 1;             // Unmask RESET interrupt
35
            UIEbits.IDLEIE = 1;             // Unmask IDLE interrupt
36
            usb_device_state = POWERED_STATE;
37
        }//end if                           // else wait until SE0 is cleared
38
    }//end if(usb_device_state == ATTACHED_STATE)
39
40
}//end USBCheckBusStatus
Ist das USB Modul deaktivert, wird es über  USBModuleEnable(); aktiviert 
gelangt somit in die states DETACHED -> ATTACHED -> POWERED -> DEFAULT 
-> ADDRESS_PENDING -> ADDRESSED -> CONFIGURED -> READY
In main.c, ProcessIO(),
1
void ProcessIO(void)
2
{   
3
    BlinkUSBStatus();
4
    // User Application USB tasks
5
    if((usb_device_state < CONFIGURED_STATE)||(UCONbits.SUSPND==1)) return;
6
    .
7
    .
8
    .
In ProcessIO(void) wird die Funktion BlinkUSBStatus() aufgeruft:
1
void BlinkUSBStatus(void)
2
{
3
    static word led_count=0;
4
    
5
    if(led_count == 0)led_count = 10000U;
6
    led_count--;
7
8
    #define mLED_Both_Off()         {mLED_1_Off();mLED_2_Off();}
9
    #define mLED_Both_On()          {mLED_1_On();mLED_2_On();}
10
    #define mLED_Only_1_On()        {mLED_1_On();mLED_2_Off();}
11
    #define mLED_Only_2_On()        {mLED_1_Off();mLED_2_On();}
12
13
    if(UCONbits.SUSPND == 1)
14
    {
15
        if(led_count==0)
16
        {
17
            mLED_1_Toggle();
18
            mLED_2 = mLED_1;        // Both blink at the same time
19
        }//end if
20
    } 
21
    else
22
    {
23
        if(usb_device_state == DETACHED_STATE)
24
        {
25
            mLED_Both_Off();
26
            
27
            PICDEMFSUSBDemoBoardTest();
28
        }
29
        else if(usb_device_state == ATTACHED_STATE)
30
        {
31
            mLED_Both_On();
32
        }
33
        .
34
        .
35
        .
In der wiederrum die Funktion PICDEMFSUSBDemoBoardTest(), welche dann 
letzt endlich eine RS232 Übertragung startet.
Aber nur wenn usb_device_state == DETACHED_STATE. Der usb_device_state 
kann nur über USBTasks()-> USBCheckBusState() (hier wird nur die 
physikalische Verbindung überprüft)  oder -> USBDriverService(). Dort 
verläuft es sich dann in den Tiefen des USB Treibers... Fakt ist das 
jedoch nur über USBTasks()->USBCheckBusState()->USBModuleDisable() 
usb_device_state in den  DETACHED_STATE gelangt oder noch über die 
Funktion void USBSoftDetach(void). Wo jedoch die aufgerufen wird, habe 
ich noch nicht gefunden(spätestens jetzt brauche ich endlich mal einen 
Texteditor mit Suchfunktion, Spaß am Rande).

Wie gelangt nun usb_device_state in den DETACHED_STATE? Nur über 
USBTasks()->USBCheckBusState()->USBModuleDisable(), wenn das USB-Kabel 
physikalisch getrennt ist? Das kann nicht sein. Denke das hat was mit 
void USBSoftDetach(void) zutun.

ABER, laut Bernd Rüter, mus usb_device_state gar nicht in den 
DETACHED_STATE. Was meint der Rest dazu? Wenn dem so ist, finde ich die 
MCHPFSUSB\fw\Demo ein wenig verwirrend, dass nur RS232 
gesendet/empfangen werden kann, wenn usb_device_state im DETACHD_STATE 
ist.

lg,
blitzgeist

@Gast:
Ich habe auch schon mal eine Schilderung des Sachverhalts an den support 
vom MCHP gesendet. Bin mal gespannt wann/was zurückkommt =)

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.