2015-02-05 76 views
0

我有一個問題,可能是在我結束一個簡單的誤解。 我有一個帶有USB CDC固件的PIC18F2550器件。我想發送一個命令,每秒向控制檯輸出一些內容。但是,它似乎並不奏效。我放入一個循環來迭代5秒鐘,每秒顯示一個輸出消息,但它實際上不會輸出任何內容。它通過5秒循環,直到循環執行後顯示最終消息的結束。它不會在循環中輸出任何東西。與輸出到控制檯困惑,C/USB CDC/PIC18F2550

我包括我的整個ProcessIO功能,因爲我認爲這是對這個問題很重要,但我評論,我放在確切的命令,我試圖找出。

感謝你們有什麼建議,我很感激。我是一名機械工程師,試圖學習一些嵌入式的東西。

/******************************************************************** 
* 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(); 
} 

回答

1

你應該重寫output_message 之前也打電話putUSBUSART()CDCTxService()CDCTxService()需要經常調用,所以你必須延遲循環中調用它。

 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(); 
      } 
     } 

雖然那種bloking延遲可以工作(__delay_ms()),更好的形式給出是檢查的ellapsed定時器,或時間戳。喜歡的東西:

 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和TickDiff是你必須實現自己的功能,但也有很多例子在Microchip庫

+0

這絕對有效,謝謝Smasho。經常調用CDCTxService()有什麼缺點嗎? 此外,從理論上說,是有可能把一個的sprintf()的延遲循環內?我嘗試過,但得到了一些奇怪的結果。可以putUSBUSART()的功能不如1ms快嗎? – coolestDisplayName 2015-02-06 02:16:28

+0

CDCTxService()會實際發送您使用putsUSBUSART入隊的數據。根據需要頻繁地調用它並沒有問題,但在發送更多數據之前您需要等待傳輸完成。這就是爲什麼你不能在沒有足夠延遲的情況下在一個循環內調用putUSBUSART。在發送更多數據之前,您必須檢查USBUSARTIsTxTrfReady()。 – Smasho 2015-02-06 04:45:15

+0

Smasho,你太棒了!出於好奇,是什麼讓你的TickDiff方法優於__delay_ms()?我認爲,因爲delay_ms依賴於振盪器,可能並不總是完全準確?謝謝! – coolestDisplayName 2015-02-06 06:40:41

0

簡短版本:這種方法不起作用。你需要重新思考你是如何做到這一點的。

USB設備不能處理事件時的延遲 - 它們必須能夠及時響應主機發送的每個請求。一秒鐘延遲通常會導致主機假定設備已斷開連接。

它的關鍵在這裏瞭解到,USB設備模型是基於(幾乎)完全圍繞主機發送請求到設備,設備回答。設備無法生成未經請求的響應。現在

,你沒有看到這裏的預期結果的原因是因爲sprintf()不將結果發送到主機;它所做的只是將一條消息放入一個緩衝區中,以便準備它將被髮回。多次調用它會覆蓋該緩衝區,而不是發回多個消息。

+0

我同意,但芯片圖書館generaly作品「作業」功能,你打電話定期進行工作,迴應事件等等。你可以每1毫秒或每10毫秒給他們打電話,這些功能有他們自己的會計時間方式。因此,只要您繼續調用「任務」功能,您就可以延遲並繼續事件處理。 – Smasho 2015-02-05 20:27:24

+0

謝謝黃昏!你能指出我採取不同的方法嗎? – coolestDisplayName 2015-02-06 02:17:23