Search code examples
cusbpiccdc

Confused with output to console, C / USB CDC / PIC18F2550


I have a problem that is probably a simple misunderstanding on my end. I have a PIC18F2550 device with a USB CDC firmware. I would like to send it a command to output something to the console every second. However, it doesn't seem to work. I put in a loop to iterate for 5 seconds and display an output message every second, but it won't actually output anything. It passes through the 5 second loop until the end where it DOES display the final message after the loop was executed. It won't output anything DURING the loop though.

I included my entire ProcessIO function because I think it's important for this issue, but I commented where I placed the exact command I'm trying to figure out.

Thanks for any suggestions you guys have, I appreciate it. I'm a mechanical engineer trying to learn some embedded stuff.

/********************************************************************
* Function:        void ProcessIO(void)
* Overview:        This function is a place holder for other user
*                  routines. It is a mixture of both USB and
*                  non-USB tasks.
*******************************************************************/
void ProcessIO(void)
{
BYTE numBytesRead;

// User Application USB tasks
if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;

if (USBUSARTIsTxTrfReady())
{
    if((CDCattached == 0x01) && (CDCattachedcount == 2))
    {
        putUSBUSART((char*)"Text Message\r\n",49);
        CDCTxService();
        CDCattachedcount = 0;
        CDCattached = 0x00;
    }
    numBytesRead = getsUSBUSART(USB_Out_Buffer, 64);
    if (numBytesRead == 1)
    {
        if ((USB_Out_Buffer[0] == '\r'))                      //Received ENTER? Ues-> End of Command
        {
            if (pos >0)
            {
                command_recvd = 0x01;
                Command[pos++] = '\0';
                pos = 0;
            }
        }
        else if ((USB_Out_Buffer[0] == 0x7F) || (USB_Out_Buffer[0] == 0x08))
        {
            if (pos > 0) pos--;
            Command[pos] = '\0';
            putUSBUSART ((char*) USB_Out_Buffer, 1);
        }
        else
        {
            Command[pos++] = USB_Out_Buffer[0];
            putUSBUSART((char*) USB_Out_Buffer, 1);
            Command[pos]='\0';
        }       //No:- Store Character to String
    }
    else if ((numBytesRead > 1))
    {
        strncpy(Command,USB_Out_Buffer,numBytesRead);
        for(int indx = numBytesRead; indx < 64; indx++)
        {
            Command[indx]='\0';
        }
        pos = numBytesRead--;
        command_recvd = 0x01;
        Command[pos++] = '\0';
        // putUSBUSART((char*) USB_Out_Buffer, 1);
        pos = 0;
    }

    if (command_recvd == 0x01)
    {
        for (int aaa = 0; aaa <= 63; aaa++)
        {
            output_message[aaa]= '\0';
        }


************** THIS IS WHERE MY TEST COMMAND IS ***************

        if (strnicmp((char*) Command, (char*) "test", 4) == 0)
        {
            sprintf(output_message, "\r\nStarting loop...\r\n");
            for int bbb = 0; bbb < 5; bbb++)
            {
                sprintf(output_message, "\r\nLooping...\r\n");
                for (delayIndex = 0; delayIndex < 1000; delayIndex++)
                {
                     __delay_ms(1);
                }
            }
            sprintf(output_message, "\r\nLoop finished!\r\n");
        }
        else
        {
            invalidCommand:
            sprintf(output_message, "\r\nInvalid Command Received. Please Retry.\r\n\0");
        }
        command_recvd = 0x00;
    }
}
CDCTxService();
}

Solution

  • You should call putUSBUSART() and CDCTxService() before overwriting output_message Also, CDCTxService() needs to be called frequently, so you have to call it during the delay loop.

            for int bbb = 0; bbb < 5; bbb++)
            {
                sprintf(output_message, "\r\nLooping...\r\n");
                putsUSBUSART(output_message);
    
                for (delayIndex = 0; delayIndex < 1000; delayIndex++)
                {
                     __delay_ms(1); 
    
                     if(USBUSARTIsTxTrfReady()) {
                          sprintf(output_message, "\r\nInside inner loop\r\n");
                          putsUSBUSART(output_message);
                     }
                     CDCTxService();
                }
            }
    

    Although that kind of bloking delays could work ( __delay_ms() ), a better aproach is to check for an ellapsed timer, or a timestamp. Something like:

            for int bbb = 0; bbb < 5; bbb++)
            {
                sprintf(output_message, "\r\nLooping...\r\n");
                putsUSBUSART(output_message);
    
                timestamp = TickGet(); 
                while (TickDiff(timestamp, TickGet()) < TICK_SECOND)
                {
                     if(USBUSARTIsTxTrfReady()) {
                          sprintf(output_message, "\r\nInside inner loop\r\n");
                          putsUSBUSART(output_message);
                     }
                     CDCTxService();
                }
            }
    

    TickGet and TickDiff are functions you have to implement yourself, however there are lots of examples on Microchip libraries