Está en la página 1de 15

#include<p24Fj64GB004.h> #include "usb.h" #include "usb_function_cdc.h" #include "GenericTypeDefs.h" #include "Compiler.h" #include "usb_config.h" #include "usb_device.h" #include "HardwareProfile.

h" _CONFIG1( WINDIS_OFF & FWDTEN_OFF & ICS_PGx1 & GWRP_OFF & GCP_OFF & JTAGEN_OFF ) _CONFIG2( POSCMOD_HS & IOL1WAY_OFF & FCKSM_CSDCMD & FNOSC_PRIPLL & IESO_OFF & PL LDIV_DIV4 & PLL96MHZ_ON) /** V A R I A B L E S FOR USB **/ #pragma udata char USB_Out_Buffer[CDC_DATA_OUT_EP_SIZE]; char RS232_Out_Data[CDC_DATA_IN_EP_SIZE]; unsigned char NextUSBOut; unsigned char NextUSBOut; //char RS232_In_Data; unsigned char LastRS232Out; // Number of characters in the buffer unsigned char RS232cp; // current position within the buffer unsigned char RS232_Out_Data_Rdy = 0; USB_HANDLE lastTransmission; /**END V A R I A B L E S FOR USB **/ int main(){ CLKDIVbits.CPDIV=0b01; CLKDIVbits.DOZEN=0; unsigned int pll_startup_counter = 600; CLKDIVbits.PLLEN = 1; while(pll_startup_counter--); USBDeviceInit(); USBDeviceAttach(); UserInit(); while(1){ ProcessIO(); } } //void _ISR _T1Interrupt(){ // // //} void UserInit(void){ unsigned char i; InitializeUSART(); // Initialize the arrays for(i=0; i<sizeof(USB_Out_Buffer); i++){

USB_Out_Buffer[i] = 0; } NextUSBOut = 0; LastRS232Out = 0; lastTransmission = 0; }//end UserInit /****************************************************************************** * Function: void InitializeUSART(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: This routine initializes the UART to 19200 * * Note: * *****************************************************************************/ void InitializeUSART(void) { // __builtin_write_OSCCONL(OSCCONL&0b11011111); RPINR19bits.U2RXR = 3; RPOR1bits.RP2R = 5; TRISBbits.TRISB3=1; TRISBbits.TRISB2=0; // __builtin_write_OSCCONL(OSCCONL 0b00100000); UART2Init(); }//end InitializeUSART #define mDataRdyUSART() UART2IsPressed() #define mTxRdyUSART() U2STAbits.TRMT /****************************************************************************** * Function: void putcUSART(char c) * * PreCondition: None * * Input: char c - character to print to the UART * * Output: None * * Side Effects: None * * Overview: Print the input character to the UART * * Note: * *****************************************************************************/ void putcUSART(char c) { UART2PutChar(c); }

/****************************************************************************** * Function: void mySetLineCodingHandler(void) * * PreCondition: USB_CDC_SET_LINE_CODING_HANDLER is defined * * Input: None * * Output: None * * Side Effects: None * * Overview: This function gets called when a SetLineCoding command * is sent on the bus. This function will evaluate the request * and determine if the application should update the baudrate * or not. * * Note: * *****************************************************************************/ #if defined(USB_CDC_SET_LINE_CODING_HANDLER) void mySetLineCodingHandler(void) { //If the request is not in a valid range if(cdc_notice.GetLineCoding.dwDTERate.Val > 115200) { //NOTE: There are two ways that an unsupported baud rate could be //handled. The first is just to ignore the request and don't change //the values. That is what is currently implemented in this function. //The second possible method is to stall the STATUS stage of the request . //STALLing the STATUS stage will cause an exception to be thrown in the //requesting application. Some programs, like HyperTerminal, handle the //exception properly and give a pop-up box indicating that the request //settings are not valid. Any application that does not handle the //exception correctly will likely crash when this requiest fails. For //the sake of example the code required to STALL the status stage of the //request is provided below. It has been left out so that this demo //does not cause applications without the required exception handling //to crash. //--------------------------------------//USBStallEndpoint(0,1); } else { DWORD_VAL dwBaud; //Update the baudrate info in the CDC driver CDCSetBaudRate(cdc_notice.GetLineCoding.dwDTERate.Val); //Update the baudrate of the UART dwBaud.Val = (((GetPeripheralClock()/2)+(BRG_DIV2/2*line_coding.dwDTERat e.Val))/BRG_DIV2/line_coding.dwDTERate.Val-1); U2BRG = dwBaud.Val; } } #endif /****************************************************************************** * Function: void putcUSART(char c) * * PreCondition: None *

* Input: None * * Output: unsigned char c - character to received on the UART * * Side Effects: None * * Overview: Print the input character to the UART * * Note: * *****************************************************************************/ unsigned char getcUSART (){ char c; return UART2GetChar(); } /******************************************************************** * Function: void ProcessIO(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: This function is a place holder for other user * routines. It is a mixture of both USB and * non-USB tasks. * * Note: None *******************************************************************/ void ProcessIO(void) { // User Application USB tasks if((USBDeviceState < CONFIGURED_STATE) (USBSuspendControl==1)) return; if (RS232_Out_Data_Rdy == 0) // only check for new USB buffer if the ol d RS232 buffer is { // empty. This will c ause additional USB packets to be NAK'd LastRS232Out = getsUSBUSART(RS232_Out_Data,64); //until the buff er is free. if(LastRS232Out > 0) { RS232_Out_Data_Rdy = 1; // signal buffer full RS232cp = 0; // Reset the current position } } //Check if one or more bytes are waiting in the physical UART transmit //queue. If so, send it out the UART TX pin. if(RS232_Out_Data_Rdy && mTxRdyUSART()) { putcUSART(RS232_Out_Data[RS232cp]); ++RS232cp; if (RS232cp == LastRS232Out) RS232_Out_Data_Rdy = 0;

} //Check if we received a character over the physical UART, and we need //to buffer it up for eventual transmission to the USB host. if(mDataRdyUSART() && (NextUSBOut < (CDC_DATA_OUT_EP_SIZE - 1))) { USB_Out_Buffer[NextUSBOut] = getcUSART(); ++NextUSBOut; USB_Out_Buffer[NextUSBOut] = 0; } //Check if any bytes are waiting in the queue to send to the USB host. //If any bytes are waiting, and the endpoint is available, prepare to //send the USB packet to the host. if((USBUSARTIsTxTrfReady()) && (NextUSBOut > 0)) { putUSBUSART(&USB_Out_Buffer[0], NextUSBOut); NextUSBOut = 0; } } CDCTxService(); //end ProcessIO

// ***************************************************************************** ************************* // ************** USB Callback Functions *************************************** ************************* // ***************************************************************************** ************************* // The USB firmware stack will call the callback functions USBCBxxx() in respons e to certain USB related // events. For example, if the host PC is powering down, it will stop sending o ut Start of Frame (SOF) // packets to your device. In response to this, all USB devices are supposed to decrease their power // consumption from the USB Vbus to <2.5mA each. The USB module detects this co ndition (which according // to the USB specifications is 3+ms of no bus activity/SOF packets) and then ca lls the USBCBSuspend() // function. You should modify these callback functions to take appropriate act ions for each of these // conditions. For example, in the USBCBSuspend(), you may wish to add code tha t will decrease power // consumption from Vbus to <2.5mA (such as by clock switching, turning off LEDs , putting the // microcontroller to sleep, etc.). Then, in the USBCBWakeFromSuspend() functio n, you may then wish to // add code that undoes the power saving things done in the USBCBSuspend() funct ion. // The USBCBSendResume() function is special, in that the USB stack will not aut omatically call this // function. This function is meant to be called from the application firmware instead. See the // additional comments near the function. /****************************************************************************** * Function: void USBCBSuspend(void) * * PreCondition: None

* * Input: None * * Output: None * * Side Effects: None * * Overview: Call back that is invoked when a USB suspend is detected * * Note: None *****************************************************************************/ void USBCBSuspend(void) { //Example power saving code. Insert appropriate code here for the desir ed //application behavior. If the microcontroller will be put to sleep, a //process similar to that shown below may be used: //ConfigureIOPinsForLowPower(); //SaveStateOfAllInterruptEnableBits(); //DisableAllInterruptEnableBits(); //EnableOnlyTheInterruptsWhichWillBeUsedToWakeTheMicro(); //should enable at least USBActivityIF as a wake source //Sleep(); //RestoreStateOfAllPreviouslySavedInterruptEnableBits(); //Prefer rably, this should be done in the USBCBWakeFromSuspend() function instead. //RestoreIOPinsToNormal(); //Preferrably, this should be done in the USBCBWakeFromSuspend() function instea d. //IMPORTANT NOTE: Do not clear the USBActivityIF (ACTVIF) bit here. Thi s bit is //cleared inside the usb_device.c file. Clearing USBActivityIF here wil l cause //things to not work as intended. #if defined(__C30__) #if 0 U1EIR = 0xFFFF; U1IR = 0xFFFF; U1OTGIR = 0xFFFF; IFS5bits.USB1IF = 0; IEC5bits.USB1IE = 1; U1OTGIEbits.ACTVIE = 1; U1OTGIRbits.ACTVIF = 1; Sleep(); #endif #endif } /****************************************************************************** * Function: void _USB1Interrupt(void) * * PreCondition: None * * Input: None * * Output: None

* * Side Effects: None * * Overview: This function is called when the USB interrupt bit is set * In this example the interrupt is only us ed when the device * goes to sleep when it receives a USB sus pend command * * Note: None *****************************************************************************/ #if 0 void __attribute__ ((interrupt)) _USB1Interrupt(void) { #if !defined(self_powered) if(U1OTGIRbits.ACTVIF) { IEC5bits.USB1IE = 0; U1OTGIEbits.ACTVIE = 0; IFS5bits.USB1IF = 0; //USBClearInterruptFlag(USBActivityIFReg,USBActivityIFBitNum); USBClearInterruptFlag(USBIdleIFReg,USBIdleIFBitNum); //USBSuspendControl = 0; } #endif } #endif /****************************************************************************** * Function: void USBCBWakeFromSuspend(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: The host may put USB peripheral devices in low power * suspend mode (by "sending" 3+ms of idle) . Once in suspend * mode, the host may wake the device back up by sending non* idle state signalling. * * This call back is invoked when a wakeup from USB suspend * is detected. * * Note: None *****************************************************************************/ void USBCBWakeFromSuspend(void) { // If clock switching or other power savings measures were taken when // executing the USBCBSuspend() function, now would be a good time to // switch back to normal full power run mode conditions. The host allow s // a few milliseconds of wakeup time, after which the device must be

// // // // }

fully back to normal, and capable of receiving and processing USB packets. In order to do this, the USB module must receive proper clocking (IE: 48MHz clock must be available to SIE for full speed USB operation).

/******************************************************************** * Function: void USBCB_SOF_Handler(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: The USB host sends out a SOF packet to full-speed * devices every 1 ms. This interrupt may be useful * for isochronous pipes. End designers should * implement callback routine as necessary. * * Note: None *******************************************************************/ void USBCB_SOF_Handler(void) { // No need to clear UIRbits.SOFIF to 0 here. // Callback caller is already doing that. } /******************************************************************* * Function: void USBCBErrorHandler(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: The purpose of this callback is mainly for * debugging during development. Check UEIR to see * which error causes the interrupt. * * Note: None *******************************************************************/ void USBCBErrorHandler(void) { // No need to clear UEIR to 0 here. // Callback caller is already doing that. // // // // // // // // Typically, user firmware does not need to do anything special if a USB error occurs. For example, if the host sends an OUT packet to your device, but the packet gets corrupted (ex: because of a bad connection, or the user unplugs the USB cable during the transmission) this will typically set one or more USB error interrupt flags. Nothing specific needs to be done however, since the SIE will automatically send a "NAK" packet to the host. In response to this, the

// // // //

host will normally retry to send the packet again, and no data loss occurs. The system will typically recover automatically, without the need for application firmware intervention.

// Nevertheless, this callback function is provided, such as // for debugging purposes. } /******************************************************************* * Function: void USBCBCheckOtherReq(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: When SETUP packets arrive from the host, some * firmware must process the request and re spond * appropriately to fulfill the request. S ome of * the SETUP packets will be for standard * USB "chapter 9" (as in, fulfilling chapt er 9 of * the official USB specifications) request s, while * others may be specific to the USB device class * that is being implemented. For example, a HID * class device needs to be able to respond to * "GET REPORT" type of requests. This * is not a standard USB chapter 9 request, and * therefore not handled by usb_device.c. Instead * this request should be handled by class specific * firmware, such as that contained in usb_ function_hid.c. * * Note: None *******************************************************************/ void USBCBCheckOtherReq(void) { USBCheckCDCRequest(); }//end /******************************************************************* * Function: void USBCBStdSetDscHandler(void) * * PreCondition: None *

* Input: None * * Output: None * * Side Effects: None * * Overview: The USBCBStdSetDscHandler() callback function is * called when a SETUP, bRequest: SET_DESCR IPTOR request * arrives. Typically SET_DESCRIPTOR reque sts are * not used in most applications, and it is * optional to support this type of request . * * Note: None *******************************************************************/ void USBCBStdSetDscHandler(void) { // Must claim session ownership if supporting this request }//end /******************************************************************* * Function: void USBCBInitEP(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: This function is called when the device becomes * initialized, which occurs after the host sends a * SET_CONFIGURATION (wValue not = 0) reque st. This * callback function should initialize the endpoints * for the device's usage according to the current * configuration. * * Note: None *******************************************************************/ void USBCBInitEP(void) { CDCInitEP(); } /******************************************************************** * Function: void USBCBSendResume(void) * * PreCondition: None * * Input: None * * Output: None *

* Side Effects: * * Overview: * (such * M state). * e * mote * "power" * hat the * and then * p. * * n is used * h wakes * by * This * e host if * * * upports * * icates * ble in the * * g, * ice a SET * d" the * * * p, * * * * * * * l that * *

None The USB specifications allow some types of USB peripheral devices to wake up a host PC as if it is in a low power suspend to RA This can be a very useful feature in som USB applications, such as an Infrared re control receiver. If a user presses the button on a remote control, it is nice t IR receiver can detect this signalling, send a USB "command" to the PC to wake u The USBCBSendResume() "callback" functio to send this special USB signalling whic up the PC. This function may be called application firmware to wake up the PC. function will only be able to wake up th all of the below are true: 1. The USB driver used on the host PC s the remote wakeup capability. 2. The USB configuration descriptor ind the device is remote wakeup capa bmAttributes field. 3. The USB host PC is currently sleepin and has previously sent your dev FEATURE setup packet which "arme remote wakeup capability. If the host has not armed the device to perform remote wakeu then this function will return without actually performing a remote wakeup sequence. This is the required behavior, as a USB device that has not been armed to perform remote wakeup must not drive remote wakeup signalling onto the bus; doing so will cause USB compliance testing failure. This callback should send a RESUME signa has the period of 1-15ms.

* Note: This function does nothing and returns quickly, if the USB * bus and host are not in a suspended condition, or are * otherwise not in a remote wakeup ready state. Therefore, it * is safe to optionally call this function regularly, ex: * anytime application stimulus occurs, as the function will * have no effect, until the bus really is in a state ready * to accept remote wakeup. * * When this function executes, it may perform clock switching, * depending upon the application specific code in * USBCBWakeFromSuspend(). This is needed, since the USB * bus will no longer be suspended by the time this function * returns. Therefore, the USB module will need to be ready * to receive traffic from the host. * * The modifiable section in this routine may be changed * to meet the application needs. Current implementation * temporary blocks other functions from executing for a * period of ~3-15 ms depending on the core frequency. * * According to USB 2.0 specification section 7.1.7.7, * "The remote wakeup device must hold the resume signaling * for at least 1 ms but for no more than 15 ms." * The idea here is to use a delay counter loop, using a * common value that would work over a wide range of core * frequencies. * That value selected is 1800. See table below: * ========================================================== * Core Freq(MHz) MIP RESUME Signal Period (ms) * ========================================================== * 48 12 1.05 * 4 1 12.6 * ========================================================== * * These timing could be incorrect when using code * optimization or extended instruction mode, * or when having other interrupts enabled. * Make sure to verify using the MPLAB SIM's Stopwatch * and verify the actual signal on an oscilloscope. *******************************************************************/ void USBCBSendResume(void) { static WORD delay_count; //First verify that the host has armed us to perform remote wakeup. //It does this by sending a SET_FEATURE request to enable remote wakeup, //usually just before the host goes to standby mode (note: it will only //send this SET_FEATURE request if the configuration descriptor declares //the device as remote wakeup capable, AND, if the feature is enabled //on the host (ex: on Windows based hosts, in the device manager //properties page for the USB device, power management tab, the //"Allow this device to bring the computer out of standby." checkbox //should be checked). if(USBGetRemoteWakeupStatus() == TRUE) { //Verify that the USB bus is in fact suspended, before we send //remote wakeup signalling. if(USBIsBusSuspended() == TRUE) { USBMaskInterrupts();

//Clock switch to settings consistent with normal USB operation. USBCBWakeFromSuspend(); USBSuspendControl = 0; USBBusIsSuspended = FALSE; //So we don't execute this code again, //until a new suspend condition is detec ted. //Section 7.1.7.7 of the USB 2.0 specifications indicates a USB //device must continuously see 5ms+ of idle on the bus, before it se nds //remote wakeup signalling. One way to be certain that this paramet er //gets met, is to add a 2ms+ blocking delay here (2ms plus at //least 3ms from bus idle to USBIsBusSuspended() == TRUE, yeilds //5ms+ total delay since start of idle). delay_count = 3600U; do { delay_count--; }while(delay_count); //Now drive the resume K-state signalling onto the USB bus. USBResumeControl = 1; // Start RESUME signaling delay_count = 1800U; // Set RESUME line for 1-13 ms do { delay_count--; }while(delay_count); USBResumeControl = 0; //Finished driving resume signalling USBUnmaskInterrupts(); } } } /******************************************************************* * Function: void USBCBEP0DataReceived(void) * * PreCondition: ENABLE_EP0_DATA_RECEIVED_CALLBACK must be * defined already (in usb_config.h) * * Input: None * * Output: None * * Side Effects: None * * Overview: This function is called whenever a EP0 data * packet is received. This gives the user (and * thus the various class examples a way to get * data that is received via the control endpoint. * This function needs to be used in conjunction * with the USBCBCheckOtherReq() function since * the USBCBCheckOtherReq() function is the apps * method for getting the initial control transfer * before the data arrives. * * Note: None *******************************************************************/

#if defined(ENABLE_EP0_DATA_RECEIVED_CALLBACK) void USBCBEP0DataReceived(void) { } #endif /******************************************************************* * Function: BOOL USER_USB_CALLBACK_EVENT_HANDLER( * USB_EVENT event, void *pdata, WORD size) * * PreCondition: None * * Input: USB_EVENT event - the type of event * void *pdata - pointer to the event data * WORD size - size of the event data * * Output: None * * Side Effects: None * * Overview: This function is called from the USB stack to * notify a user application that a USB event * occured. This callback is in interrupt context * when the USB_INTERRUPT option is selected. * * Note: None *******************************************************************/ BOOL USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, WORD size) { switch(event) { case EVENT_TRANSFER: //Add application specific callback task or callback function here i f desired. break; case EVENT_SOF: USBCB_SOF_Handler(); break; case EVENT_SUSPEND: USBCBSuspend(); break; case EVENT_RESUME: USBCBWakeFromSuspend(); break; case EVENT_CONFIGURED: USBCBInitEP(); break; case EVENT_SET_DESCRIPTOR: USBCBStdSetDscHandler(); break; case EVENT_EP0_REQUEST: USBCBCheckOtherReq(); break; case EVENT_BUS_ERROR: USBCBErrorHandler(); break; case EVENT_TRANSFER_TERMINATED: //Add application specific callback task or callback function here i f desired. //The EVENT_TRANSFER_TERMINATED event occurs when the host performs

a CLEAR //FEATURE (endpoint halt) request on an application endpoint which w as //previously armed (UOWN was = 1). Here would be a good place to: //1. Determine which endpoint the transaction that just got termina ted was // on, by checking the handle value in the *pdata. //2. Re-arm the endpoint if desired (typically would be the case fo r OUT // endpoints). break; default: break; } return TRUE; } /** EOF main.c *************************************************/

También podría gustarte