|
|
View previous topic :: View next topic |
Author |
Message |
mendezmh
Joined: 03 Jun 2009 Posts: 4 Location: Argentina
|
PIC18F2550 runs well with USB 2.0 but not with USB 3.0 |
Posted: Sat Feb 13, 2016 8:55 am |
|
|
Hi guys, I'm facing a problem that I can't find what to do.
I have a device with a PIC18F2550 that receives some data from a computer by the USB port (bulk mode). The software running in the PC is very simple, programmed in C#. Everytime that someone click a button, this software sends 2 bytes to the 18F2550. Depending on the data in those bytes, the 18F2550 do some actions and also sends the second byte to another PIC via a simple rs-232 communication.
If I use the device with a USB 2.0 port everything runs smoothly. But, if the PC has at least one USB 3.0 port, only the first 2 bytes are sent. I mean, the 18F2550 only executes the action and sends the first-second-byte via rs-232. Even though I keep clicking the same or others buttons, nothing happens.
So, is there any consideration to keep in mind when the version of the USB port in the PC is 3.0? Any suggestion will be very welcomed!
I've tried on Windows 7, Windows 8 and Windows 10. But, no matter the version of the OS, always the problem is when the PC has USB 3.0 ports.
Windows drivers looks good because PC recognize the device and for the first press runs OK.
Here is the PIC18F2550 code:
Code: |
#include <18F2550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#device ADC=8
#use delay(clock=48000000)
#define USB_HID_DEVICE FALSE //Desabhilito modo HID
#define USB_EP1_TX_ENABLE USB_ENABLE_BULK //Habilito EndPoint de transferencia
#define USB_EP1_RX_ENABLE USB_ENABLE_BULK //Habilito EndPoint de recepción
#define USB_EP1_TX_SIZE 7 //Tamaño del EndPoint de transferencia
#define USB_EP1_RX_SIZE 7 //Tamaño del EndPoint de recepción
#include <pic18_usb.h> //Directivas de la capa física de USB para PIC18Fxx5x
#include <32C_USB.h> //Descriptores y configuraciones para la placa adquisidora de datos
#include <usb.c> //Funciones para obtener control de USB
#define TX1 PIN_B0
#define TX2 PIN_B1
#define TX3 PIN_B2
#define TX4 PIN_B3
#define TX5 PIN_B4
#define TX6 PIN_B5
#define TX7 PIN_B6
#define TX8 PIN_B7
#define Prende output_high
#define Apaga output_low
void main(void){
int8 iBuff[2]; //Buffer de entrada
int8 oBuff[2]; //Buffer de salida
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
setup_spi(SPI_SS_DISABLED);
Apaga(TX1);
Apaga(TX2);
Apaga(TX3);
Apaga(TX4);
Apaga(TX5);
Apaga(TX6);
Apaga(TX7);
Apaga(TX8);
usb_init(); //Enciendo el modo USB
usb_task(); //Habilito las tareas USB
usb_wait_for_enumeration(); //Espera a que la PC enumere a la placa
while(1){
if(usb_enumerated()){ // Si la placa está enumerada
if (usb_kbhit(1)){ //Si hay datos en el endpoint
usb_get_packet(1, iBuff, 2); // Lee el paquete de 2bytes del EndPoint y lo guarda en el buffer de entrada
if (iBuff[0] == 0){ // MODO DISPARO
if(iBuff[1]>=0 && iBuff[1]<=31){
Prende(TX1);
Apaga(TX2);
Apaga(TX3);
Apaga(TX4);
Apaga(TX5);
Apaga(TX6);
Apaga(TX7);
Apaga(TX8);
delay_ms(10);
putc(iBuff[1]);
delay_ms(10);
}
if(iBuff[1]>=32 && iBuff[1]<=63){
Apaga(TX1);
Prende(TX2);
Apaga(TX3);
Apaga(TX4);
Apaga(TX5);
Apaga(TX6);
Apaga(TX7);
Apaga(TX8);
delay_ms(10);
putc(iBuff[1]-32);
delay_ms(10);
}
if(iBuff[1]>=64 && iBuff[1]<=95){
Apaga(TX1);
Apaga(TX2);
Prende(TX3);
Apaga(TX4);
Apaga(TX5);
Apaga(TX6);
Apaga(TX7);
Apaga(TX8);
delay_ms(10);
putc(iBuff[1]-64);
delay_ms(10);
}
if(iBuff[1]>=96 && iBuff[1]<=127){
Apaga(TX1);
Apaga(TX2);
Apaga(TX3);
Prende(TX4);
Apaga(TX5);
Apaga(TX6);
Apaga(TX7);
Apaga(TX8);
delay_ms(10);
putc(iBuff[1]-96);
delay_ms(10);
}
if(iBuff[1]>=128 && iBuff[1]<=159){
Apaga(TX1);
Apaga(TX2);
Apaga(TX3);
Apaga(TX4);
Prende(TX5);
Apaga(TX6);
Apaga(TX7);
Apaga(TX8);
delay_ms(10);
putc(iBuff[1]-128);
delay_ms(10);
}
if(iBuff[1]>=160 && iBuff[1]<=191){
Apaga(TX1);
Apaga(TX2);
Apaga(TX3);
Apaga(TX4);
Apaga(TX5);
Prende(TX6);
Apaga(TX7);
Apaga(TX8);
delay_ms(10);
putc(iBuff[1]-160);
delay_ms(10);
}
if(iBuff[1]>=192 && iBuff[1]<=223){
Apaga(TX1);
Apaga(TX2);
Apaga(TX3);
Apaga(TX4);
Apaga(TX5);
Apaga(TX6);
Prende(TX7);
Apaga(TX8);
delay_ms(10);
putc(iBuff[1]-192);
delay_ms(10);
}
if(iBuff[1]>=224 && iBuff[1]<=255){
Apaga(TX1);
Apaga(TX2);
Apaga(TX3);
Apaga(TX4);
Apaga(TX5);
Apaga(TX6);
Apaga(TX7);
Prende(TX8);
delay_ms(10);
putc(iBuff[1]-224);
delay_ms(10);
}
}
}
}
}
}
|
Here is a part of the PC software (just 3 buttons events code):
Code: |
private void button6_Click(object sender, EventArgs e)
{
bool bres;
byte[] sdBuffer = new byte[2];
sdBuffer[0] = 0x00; //Modo LEDs
string canal = Convert.ToString((Convert.ToByte(button6.Text.Substring(3)) - 1));
sdBuffer[1] = Convert.ToByte(canal);
bres = Form1.picwinusbapi.Write_FCEIA_USB(Form1.iHandle, sdBuffer);
}
private void button7_Click(object sender, EventArgs e)
{
bool bres;
byte[] sdBuffer = new byte[2];
sdBuffer[0] = 0x00; //Modo LEDs
string canal = Convert.ToString((Convert.ToByte(button7.Text.Substring(3)) -1));
sdBuffer[1] = Convert.ToByte(canal);
bres = Form1.picwinusbapi.Write_FCEIA_USB(Form1.iHandle, sdBuffer);
}
private void button8_Click(object sender, EventArgs e)
{
bool bres;
byte[] sdBuffer = new byte[2];
sdBuffer[0] = 0x00; //Modo LEDs
string canal = Convert.ToString((Convert.ToByte(button8.Text.Substring(3)) -1));
sdBuffer[1] = Convert.ToByte(canal);
bres = Form1.picwinusbapi.Write_FCEIA_USB(Form1.iHandle, sdBuffer);
}
|
This C# software uses winusb.dll with this function to send data:
Code: |
public bool Write_FCEIA_USB(IntPtr iHandle, byte[] dBuffer)
{
byte PipeID = 0x01; // send pipe
int szBuffer = dBuffer.GetLength(0);
uint bytesWritten;
bool bResult;
bResult = WinUsb_WritePipe(iHandle, PipeID, dBuffer, szBuffer, out bytesWritten, IntPtr.Zero);
//Debug.WriteLine(bytesWritten);
return bResult;
}
|
Thanks!! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Sat Feb 13, 2016 9:01 am |
|
|
Wondered when this was going to come up...
My knee jerk, common sense reply is to FORCE the PC USB3 ports to become USB2. Now HOW you do this is not in my quiver of arrows however it must be possible, same as setting baudrate, monitor defaults, etc.
Hmm.. I wonder if you can use different pullups on D+, D- to tell the PC it's a 2.0 device ?? Just thinking out loud here.
maybe Google can help ?
Jay |
|
|
mendezmh
Joined: 03 Jun 2009 Posts: 4 Location: Argentina
|
|
Posted: Sat Feb 13, 2016 9:13 am |
|
|
temtronic wrote: | Wondered when this was going to come up...
My knee jerk, common sense reply is to FORCE the PC USB3 ports to become USB2. Now HOW you do this is not in my quiver of arrows however it must be possible, same as setting baudrate, monitor defaults, etc.
Hmm.. I wonder if you can use different pullups on D+, D- to tell the PC it's a 2.0 device ?? Just thinking out loud here.
maybe Google can help ?
Jay |
Hey temtronic, thanks for your reply. I forgot to mention that I've already tried with external resistors at both terminals D+, D-, also at the same time. Moreover I tried with 2 27 Ohm series resistors at D- and D+. That was all suggestion that I could find on google... None of them worked |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Sat Feb 13, 2016 10:19 am |
|
|
I downloaded a 'basic usb3.0' PDF from element14 and read it real quick. Seems resistors aren't used as the detection of 'super speed'...and the'se a 3.0 'descriptor' block required.
Introduction to USB 3.0 protocol.pdf
I still maintain you must be able to force the OS (win7,8,xx) to set the USB 3.0 port to usb2.0 though.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Sat Feb 13, 2016 10:21 am |
|
|
A 2550, is always going to be USB2, and will be seen as USB2 by Windows.
What you are describing, was common. Emphasize _was. When USB3 launched (and for a couple of years afterwards), there were a huge number of USB3 chipsets that dd not correctly handle switching to handle USB2 devices. The simplest solution at the time, was to add a USB2 hub between the device and the PC. For some reason the hub was correctly seen as USB2, and forced the chipset to change 'down' correctly.
Go back a couple of years, and you will find literally tens of thousands of threads for just about every USB2 device. Generally, It was a chipset driver problem, and gradually most have been fixed. However there are a couple of chipsets that have hardware issues, and still give this problem.
So, first thing to do is make sure the PC involved does have the latest drivers. In some cases the default Windows drivers are not the latest, and these have to be loaded separately.
Then as a separate issue, if the actual board layout is a little less than ideal (traces to the USB socket are not quite matched in length and impedance), then this can tend to show problems because the uSB3 drivers can generate faster edges. Adding 22 to 27R series resistors in the D+/D- right adjacent to the PIC, can help if this is the problem. I see you have tried this, though have to ask where you put them?. They do want to be close to the PIC. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Sat Feb 13, 2016 11:38 am |
|
|
As a comment, your code is faulty.
usb_task needs to be inside the while loop. It is _required_ to be called when certain events occur on the USB bus. It should be called at regular intervals to ensure these are handled.
I'd guess that this is being required when the USB3 host renegotiates the bus speed, and hence the code fails.
This will cause problems on USB2 as well, but presumably you are being lucky and not triggering these.... |
|
|
drolleman
Joined: 03 Feb 2011 Posts: 116
|
|
Posted: Sat Feb 13, 2016 1:49 pm |
|
|
I have a 2550 I use regularly. it works fine, and stable weeks at a time. it connects to many different mb's with usb 3.0. I don't even have resistors on the d+ and d-. when I first designed it I didn't know they are required, but they work fine. I have over 20 of these boards in service, before upgrading to 26j50/53. it also works connected to a 3.0 port. I would look at your code. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Sat Feb 13, 2016 2:14 pm |
|
|
The resistors aren't required. The match is generally OK without them. However only with very short runs to the chip.
I think the failure to call usb_task is actually the problem. This handles the USB 'housekeeping'. If you aren't enabling USB interrupts, this has to be called fairly frequently. With interrupts enabled it can just be called 'occasionally'.
The code posted doesn't enable interrupts, so usb_task has to be called.
Problem is that the speed change is seen as a disconnect/reconnect cycle, and since this is only called once to handle the original connection, USB on any machine that has the USB3 stack, will hang.
Some chipsets are really fussy, while others worked pretty much from the first. |
|
|
mendezmh
Joined: 03 Jun 2009 Posts: 4 Location: Argentina
|
|
Posted: Sun Feb 28, 2016 5:00 pm |
|
|
Hi guys, thanks a lot for your considerations! I was out of the office, so I will try your suggestions regarding the 2.0 hub and usb_task() inside the main loop this week. |
|
|
mendezmh
Joined: 03 Jun 2009 Posts: 4 Location: Argentina
|
|
Posted: Tue Mar 08, 2016 4:33 pm |
|
|
Hello,
I finally solved the problem.
I have to eliminate the usb_kbhit(1) function, and now it's working! I'm polling the USB data all the time and when I detect that data has changed I do the actions.
I know that isn't it an elegant solution, but it's working... And for this old development should be enough.
Even thought I've tried your suggestion regarding usb_task inside the main loop and the hub, but none of them worked.
Thanks again for your support! |
|
|
|
|
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
|