CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

USB virtual port

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Requan



Joined: 11 May 2008
Posts: 74

View user's profile Send private message

USB virtual port
PostPosted: Mon Mar 24, 2014 1:58 am     Reply with quote

Hello,
I run example ex12.c - USB virtual port (Pic 24FJ256GB206 - on CCS PCB, CCS v5.021):

Code:
#include "CCSUSB.h"
#include <usb_cdc.h>

void main(VOID)
{
   CHAR c;
   UNSIGNED int8 delay=0;
   LED_ON(GREEN_LED);
   LED_OFF(YELLOW_LED);
   LED_OFF(RED_LED);
   setup_adc(ADC_CLOCK_INTERNAL | ADC_TAD_MUL_2);
   setup_adc_ports(MY_ANALOG_PORTS);
   set_adc_channel(AN_POT);
   usb_init();
   
   
   BYTE USBRxBuff[64];
   int index = 0;
   

   WHILE (TRUE)
   {
      IF (usb_enumerated () )
      IF (usb_attached () )
      {
         LED_ON(YELLOW_LED);

         IF (usb_cdc_kbhit () )
         {
           
            USBRxBuff[index]=usb_cdc_getc();

            IF(  USBRxBuff[index++] == 0X0D)
               output_toggle(RED_LED);

         }

         IF (++delay > 200)
         {
            delay=0;
            printf(usb_cdc_putc,"\r\nADC=%U", read_adc());
         }

         delay_ms(5);
      }
      else
      {
      LED_OFF(YELLOW_LED);
      }
   }
}

I installed driver and open port in RS232 terminal on PC. All was ok, but i saw strange behavior: when i open port RS232 and disconnect USB (or reset uP) and connect again, i can't open port again (In devices manager i see virtual port), so i have to close port and reset again and then is ok. Conclusion is that: i can't reset devices or disconnect USB when port is open.
I tried some function to clear USB when i connect USB, when no helps.
Could advise what i can to do ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Mon Mar 24, 2014 3:39 am     Reply with quote

There are several things to getting USB to attach/detach properly.

First is that 'connection sense' (using a pin to actually detect the 5v on the USB line), is actually _required_. If you read the USB spec's, a device _must_ detect this, and re-enumerate if the line drops/rises. CCS don't make this clear.
Then separately, your device needs to be able to detect when the master opens and closes a port. The device is still enumerated, but your code needs to know that the master has disconnected. The easiest way to do this is to use the usb_cdc_carrier.dte_present indicator, and have the PC code set to enable DTE when it connects, so your code can go back to waiting for a 'new' connection, when this drops:
Code:

//in main
   int1 usb_cdc_oldconnected=FALSE;


   do {
      if (usb_attached()) {
         usb_task();
         if (usb_enumerated()){
            if (usb_cdc_carrier.dte_present) {
               if (usb_cdc_oldconnected==FALSE) {
                  printf(usb_cdc_putc,"message here to master\n\r");
                  usb_cdc_oldconnected=TRUE;
               }
               if (usb_cdc_kbhit()) {
                  //Need to parse USB here
                  tchar=usb_cdc_getc();
                  parseusb(tchar);
                  //also clear host error here

               }
            }
            else {
               usb_cdc_oldconnected=FALSE;
            }
         }
         else {
            usb_cdc_oldconnected=FALSE;
         }
      }


The 'message to master', is a message saying something like 'My device is attached' which is sent _once_ whenever the device first sees the port open. Then your PC code knows it is talking to the right device. In my case the device also signals a 'no host' error in hardware, where 'clear host error' is remarked. This automatically sets using a timeout, if no data is transferred in a minute. For a standard simple port this wouldn't be used.
With 'usb_attached' using the connection sense pin, this gives correct handling of open/close, and hardware reconnect.

Best Wishes
Requan



Joined: 11 May 2008
Posts: 74

View user's profile Send private message

PostPosted: Mon Mar 24, 2014 7:24 am     Reply with quote

Thanks Ttelmah for big help as always, I will add 5v checking, and use DTE, but first i have repair my evaluation board after some burning Mad .

Let me ask one more question: where i find function: parseusb(), because my example doesn't contains.
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Tue Mar 25, 2014 1:50 pm     Reply with quote

That is whatever you want to use to parse what you have received from the USB!.
Should always be done as a singe character 'state' parser (so returns immediately if a packet/string is not complete), so that your main code can keep looping and doing other things.
Requan



Joined: 11 May 2008
Posts: 74

View user's profile Send private message

PostPosted: Thu Mar 27, 2014 7:56 am     Reply with quote

Arrow Ttelmah

I add checking USB voltage:
Code:

 WHILE (TRUE)
   {
      int16 adc_value;
      adc_value = read_adc();
      volts = (float)(adc_value * 3.3)/255;       
      //lcd_gotoxy(2,1);
     // printf(lcd_putc, "\nVolt=%3.2f%s", volts,"V"); //3-znaki; 2- znaki po przecinku

      if (volts > 2.5)
      {
         
         IF (usb_enumerated () )
         IF (usb_attached () )
         {
            LED_OFF(YELLOW_LED);
   
            IF (usb_cdc_kbhit () )
            {
               
               USBRxBuff[index]=usb_cdc_getc();
   
               IF(  USBRxBuff[index++] == 0X0D)
                  output_toggle(RED_LED);
            }
            IF (++delay > 200)
            {
               delay=0;
               printf(usb_cdc_putc,"\r\nADC=%U", read_adc());
            }
   
            delay_ms(5);
         }
         else
         {
         }
      }
      else
      {
         LED_ON(YELLOW_LED);
      }
   }

Could you tell me what i missed? Because it works in the same way as before.
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Thu Mar 27, 2014 8:47 am     Reply with quote

You are still not checking for dte.

There are other ways of doing this, but the 'point' is this allows the code to know if the connection is 'open'. Problem otherwise is if the connection goes 'open', and then the port is closed, the code does not know that this has happened, and won't handle being opened again properly.

You also need to ensure you are using the usb_init_cs call, not usb_init.
Requan



Joined: 11 May 2008
Posts: 74

View user's profile Send private message

PostPosted: Fri Mar 28, 2014 6:48 am     Reply with quote

Ttelmah wrote:
You are still not checking for dte.

There are other ways of doing this, but the 'point' is this allows the code to know if the connection is 'open'. Problem otherwise is if the connection goes 'open', and then the port is closed, the code does not know that this has happened, and won't handle being opened again properly.

You also need to ensure you are using the usb_init_cs call, not usb_init.

Sorry i forget to put two code together:
Code:

 WHILE (TRUE)
   {
      int16 adc_value;
      adc_value = read_adc();
      volts = (float)(adc_value * 3.3)/255;       

      if (volts > 2.5)
      {
         
         IF (usb_attached () )
         {
            IF (usb_enumerated () )
            {
               if (usb_cdc_carrier.dte_present)
               {
                  LED_OFF(YELLOW_LED);
                  if (usb_cdc_oldconnected==FALSE)
                  {
                     printf(usb_cdc_putc,"message here to master\n\r");
                     usb_cdc_oldconnected=TRUE;
                  }
         
                  IF (usb_cdc_kbhit () )
                  {
                     
                     USBRxBuff[index]=usb_cdc_getc();
         
                     IF(  USBRxBuff[index++] == 0X0D)
                        output_toggle(RED_LED);
                  }
                  IF (++delay > 200)
                  {
                     delay=0;
                     printf(usb_cdc_putc,"\r\nADC=%U", read_adc());
                  }
         
                  delay_ms(5);
               }
               else
               {
                  usb_cdc_oldconnected=FALSE;
               }
            }
            else
            {
               usb_cdc_oldconnected=FALSE;
            }
         }
         else
         {
            LED_ON(YELLOW_LED);
         }
      }
   }
}

I dont know if i correct understand you: my PC program put DTE high and checking if message was receive from USB, when not then close port, and next trying to open. When i connect USB again, program can open port, so all work fine.
Thanks very much for help and your time.
Requan



Joined: 11 May 2008
Posts: 74

View user's profile Send private message

PostPosted: Tue Apr 08, 2014 5:22 am     Reply with quote

Dear Ttelmah:
Let me ask another question:
Based on Your example i prepared simple program to send USB echo:

Code:

 if(USB_CABLE_IS_ATTACHED())
        {
           if (usb_attached())
           {
               if (usb_enumerated () )
               {
                  CHAR c;
                 
                  if (usb_cdc_carrier.dte_present)
                  {
                     if (usb_cdc_oldconnected==FALSE)
                     {
                        printf(usb_cdc_putc,"message here to master\n\r");
                        usb_cdc_oldconnected=TRUE;
                     }
                     if (usb_cdc_kbhit () )
                     {
                           c=usb_cdc_getc();
                           usb_cdc_putc(c);
   
                           delay_cycles(150);
                       
                           if(c == 0x0D)
                           {
                               usb_cdc_putc('O');
                               delay_cycles(150);
                               usb_cdc_putc('K');
                               delay_cycles(150);
                           }
                      }
                  }
                  else
                  {
                     usb_cdc_oldconnected=FALSE;
                  }
               }
               else
               {
                  usb_cdc_oldconnected=FALSE;
               }
               }
           }
     

I had to add delay_cycles(150) after send and receive commands , because otherways i lost character or hang on terminal.
I also tried to add clear procedure usb_clear_trn(); but no changes. You wrote "also clear host error here " but i don't know to do it.
Could You advise why did it happen?
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Tue Apr 08, 2014 8:38 am     Reply with quote

Comments/questions:

First 'USB_CABLE_IS_ATTACHED', and 'usb_attached()' do the same thing.

This from usb.h (hopefully small enough part that nobody will complain!).
Code:

#if defined(USB_CABLE_IS_ATTACHED)
 #define usb_attached() USB_CABLE_IS_ATTACHED()
#else
 #define usb_attached() TRUE
#endif

So provided USB_CABLE_IS_ATTACHED is defined, 'usb_attached()' gets defined as a slightly more friendly looking route to it.
Provided you define 'USB_CON_SENSE_PIN' _before_ you load usb.h, the 'cable is attached' macro gets defined to read this pin.

So, make sure you are defining this pin, and get rid of one or the other of the calls....

Now the only reason to need a delay, is that something is preventing the USB interrupt from being properly serviced. Remember that when using USB, it becomes totally essential to ensure all other interrupt handlers exit quickly. This is always 'good practice', but with USB, it is vital.

On the 'host error', this is totally down to you. As I said, the my system actually flags a hardware error when the USB connection is not present/enumerated/receiving data. It turns on a relay and if it remains off for more than a few seconds, sounds a siren. This has to be cleared when USB is once more working OK.
Requan



Joined: 11 May 2008
Posts: 74

View user's profile Send private message

PostPosted: Wed Apr 09, 2014 4:39 am     Reply with quote

Arrow Ttelmah:
Thanks for answer and Your time.
Quote:
Now the only reason to need a delay, is that something is preventing the USB interrupt from being properly serviced. Remember that when using USB, it becomes totally essential to ensure all other interrupt handlers exit quickly. This is always 'good practice', but with USB, it is vital.


Please forgive me simple question, but how to check if interrupt is exit ?
By checking one of flag below:

IDLEIF: Idle Detect Interrupt bit
RESUMEIE: Resume Interrupt bit
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group