2014-04-11 4 views
0

저는 현재 NXP LPC1788 마이크로 컨트롤러로 작업 중이며 USB를 사용하여 Windows 7 PC와 통신하도록 구성하려고합니다. 저는 USB에 대한 경험이 부족합니다. (이번 주 초에 프로토콜을 배우기 시작했습니다.) 저는 LPC1788을 오랫동안 사용해 왔으며 다른 통신 프로토콜 (CAN, I2C, SSP)에 대한 경험이 있습니다.LPC1788 마이크로 컨트롤러를 사용하여 USB를 통해 통신하려면 어떻게해야합니까?

디바이스로 작동하고 PC가 호스트로 작동하도록 내 마이크로 컨트롤러를 구성하고 싶습니다. 전 속도 인터럽트 전송을 사용하여 통신하도록 마이크로 컨트롤러를 구성해야한다고 생각합니다. 또한 나중에 PC 용으로 자체 공급 업체별 USB 드라이버를 만들어야 할 필요가 있습니다. 아직이 작업을 수행하지 않았으며 내 설명자가 제대로 구성되지 않았습니다.

내 특정 문제는 내 프로그램을 실행하고 마이크로 컨트롤러의 USB 장치를 초기화/활성화 할 때 두 개의 USB 인터럽트 만 수신한다는 것입니다. 각 경우에있어서의 인터럽트 상태 (DEVINTST) 값은 다음

0x19 - (CON (connected), SUS_CH (suspend state change), and RST (bus reset)) 
다음 DEVSTAT를 수신하는 경우
0x19 - (FRAME, DEVSTAT, and CCEMPTY interrupts) 
0x1 - (FRAME interrupt) 

인터럽트, I는 GET 장치 STATUS 명령을 사용하여 직렬 인터페이스 엔진으로부터 다음 값을 읽어

USBlyzer를 사용하면 다음과 같은 네 개의 패킷 만 얻을 수 있습니다 : http://i.imgur.com/WRk7RBv.png.

필자는 올바르게 구성된 디스크립터 나 PC 끝에 일치하는 드라이버가 없어도 이보다 더 많은 정보를 받아야한다고 생각합니다. 끝점 0에서 Get Descriptor 요청을받을 것으로 예상됩니다.

내 주요 기능은 내 USB 장치 만 초기화하고 무한정 반복합니다.

의 USB 초기화 코드가 아래에 주어진다 :

void USBInit() 
{ 
    // Turn on power and clock 
    CLKPWR_ConfigPPWR(CLKPWR_PCONP_PCUSB, ENABLE); 

    // PLL0 clock is 96 MHz, usbclk should be 48 MHz. 
    LPC_SC->USBCLKSEL = 0x102; 

    // Configure USB pins. 
    PINSEL_ConfigPin(0, 29, 1); // USB_D+1 
    PINSEL_ConfigPin(0, 30, 1); // USB_D-1 
    PINSEL_ConfigPin(1, 18, 1); // USB_UP_LED1 
    PINSEL_ConfigPin(2, 9, 1); // USB_CONNECT1 
    PINSEL_ConfigPin(1, 30, 2); // USB_VBUS 
    //PINSEL_ConfigPin(1, 19, 2); // USB_PPWR1 

    PINSEL_SetPinMode(1, 30, PINSEL_BASICMODE_PLAINOUT); 

    // Set DEV_CLK_EN and AHB_CLK_EN. 
    LPC_USB->USBClkCtrl |= 0x12; 

    // Wait until change is reflected in clock status register. 
    while((LPC_USB->USBClkSt & 0x12) != 0x12); 

    // Select USB port 1. 
    LPC_USB->USBClkCtrl |= 0x8; 
    while((LPC_USB->USBClkSt & 0x8) == 0); 
    LPC_USB->StCtrl &= ~0x3; 
    LPC_USB->USBClkCtrl &= ~0x8; 

    // Reset the USB. 
    USBReset(); 

    // Configure interrupt mode. 
    writeSIECommandData(CMD_SET_MODE, 0); 

    // Enable NVIC USB interrupts. 
    NVIC_EnableIRQ(USB_IRQn); 

    // Set device address to 0x0 and enable device & connection. 
    USBSetAddress(0); 
    USBSetConnection(TRUE); 

    //printf("USB initialised\n"); 
    //printf("EpIntEn: 0x%x\n", LPC_USB->EpIntEn); 

    // No errors here (SIE Error code: 0x0). 
    USBPrintErrCode(); 

    // Packet sequence violation here (SIE Error code: 0x11). 
    USBPrintErrCode(); 
} 

의 USB 리셋 기능 :

void USBReset() 
{ 
    LPC_USB->EpInd = 0; 
    LPC_USB->MaxPSize = USB_MAX_PACKET_SIZE; 
    LPC_USB->EpInd = 1; 
    LPC_USB->MaxPSize = USB_MAX_PACKET_SIZE; 
    while ((LPC_USB->DevIntSt & EP_RLZED_INT) == 0); 

    LPC_USB->EpIntClr = 0xFFFFFFFF; 
    LPC_USB->EpIntEn = 0xFFFFFFFF; 
    LPC_USB->DevIntClr = 0xFFFFFFFF; 
    LPC_USB->DevIntEn = DEV_STAT_INT | EP_SLOW_INT | EP_FAST_INT; 
} 

의 USB 세트 어드레스 기능 :

void USBSetAddress(uint32_t addr) 
{ 
    writeSIECommandData(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | addr)); 
    writeSIECommandData(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | addr)); 
} 

의 USB 세트 접속 기능 :

214,853,931,842,468,163,210의 USB 인터럽트 서비스 루틴 :

void USB_IRQHandler(void) 
{ 
    uint32_t data; 
    uint32_t interruptData = LPC_USB->DevIntSt; 

    printf("InterruptData: 0x%x\n", interruptData); 

    // Handle device status interrupt (reset, connection change, suspend/resume). 
    if(interruptData & DEV_STAT_INT) 
    { 
    LPC_USB->DevIntClr = DEV_STAT_INT; 
    writeSIECommand(CMD_GET_DEV_STAT); 
    data = readSIECommandData(DAT_GET_DEV_STAT); 
    printf("Data: 0x%x\n", data); 

    // Device reset. 
    if(data & DEV_RST) 
    { 
     USBReset(); 
     USBResetCore(); 
     printf("USB Reset\n"); 
    } 

    // Connection change. 
    if(data & DEV_CON_CH) 
    { 
     printf("Connection change\n"); 
     /* Pass */ 
    } 

    // Suspend/resume. 
    if(data & DEV_SUS_CH) 
    { 
     if(data & DEV_SUS) 
     { 
     printf("USB Suspend\n"); 
     USBSuspend(); 
     } 
     else 
     { 
     printf("USB Resume\n"); 
     USBResume(); 
     } 
    } 

    return; 
    } 

    // Handle endpoint interrupt. 
    if(interruptData & EP_SLOW_INT) 
    { 
    printf("Endpoint interrupt\n"); 
    } 

    if(interruptData & EP_FAST_INT) 
    { 
    printf("Endpoint interrupt\n"); 
    } 
} 

터미널 출력 :

InterruptData: 0x19 
Data: 0x19 
USB Reset 
USB Resume 
InterruptData: 0x1 

편집 : SIE의 GET 오류 코드 명령을 사용하여, 나는 "예기치 않은 패킷"로 끝날 것을 발견 USB 초기화 기능이 끝날 때까지 오류가 발생합니다. 그러나 테스트 레지스터를 읽으면 예상대로 0xA50F가 반환되며 SIE와의 통신이 작동하고 USB/AHB 클럭이 올바르게 구성되어 실행 중임을 의미합니다.

답변

0

IAR Embedded Workbench에서 예제 USB 프로젝트를 사용할 수있었습니다.

  • 내가 내 인쇄가 훨씬 빨리 출력했다가 "SWO" "세미 호스팅"에서 내 프로젝트의 구성을 변경 : 그 바탕으로, 나는 주로 내 프로그램을 고정이 명 변경했습니다.

  • 다음 줄을 제거했습니다. 그것은 분명히 USB 클럭 속도를 잘못 구성했습니다.

    LPC_SC->USBCLKSEL = 0x102;