|
|
View previous topic :: View next topic |
Author |
Message |
Requan
Joined: 11 May 2008 Posts: 74
|
USB virtual port |
Posted: Mon Mar 24, 2014 1:58 am |
|
|
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: 19513
|
|
Posted: Mon Mar 24, 2014 3:39 am |
|
|
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
|
|
Posted: Mon Mar 24, 2014 7:24 am |
|
|
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 .
Let me ask one more question: where i find function: parseusb(), because my example doesn't contains. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Tue Mar 25, 2014 1:50 pm |
|
|
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
|
|
Posted: Thu Mar 27, 2014 7:56 am |
|
|
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: 19513
|
|
Posted: Thu Mar 27, 2014 8:47 am |
|
|
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
|
|
Posted: Fri Mar 28, 2014 6:48 am |
|
|
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
|
|
Posted: Tue Apr 08, 2014 5:22 am |
|
|
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: 19513
|
|
Posted: Tue Apr 08, 2014 8:38 am |
|
|
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
|
|
Posted: Wed Apr 09, 2014 4:39 am |
|
|
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 |
|
|
|
|
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
|