⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb_main.c

📁 上位机与下位机的USB通讯
💻 C
字号:
//-----------------------------------------------------------------------------
// USB_MAIN.c
//-----------------------------------------------------------------------------
// Copyright 2002 Silicon Laboratories, Inc.
//
// AUTH: JS
// DATE: 22 FEB 02
//
//
// Target: C8051F34x
// Tool chain: KEIL C51 6.03 / KEIL EVAL C51
//
// REVISIONS:
// 10/11/06 - PKC: Changed port I/O and ADC Mux settings to accommodate
//            potentiometer at P2.5 on the 'F340 Target Board; Changed
//            USBXpress API interrupt to 17.
// 1/24/06  - PKC: Changed 'F320.h to 'F340.h
// 11/22/02 - DM:  Added support for switches and sample USB
//            interrupt application.
// 4/4/03   - DM:   Ported code to use USB_API.lib instead of custom solution.
// 5/6/03   - DM: Made changes to use new driver with better throughput.
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f340.h>
#include <stddef.h>
#include "USB_API.h"

//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F32x
//-----------------------------------------------------------------------------

sfr16 TMR2RL   = 0xca;                   // Timer2 reload value
sfr16 TMR2     = 0xcc;                   // Timer2 counter
sfr16 ADC0     = 0xbe;
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------

sbit Led1 = P2^2;                         // LED='1' means ON
sbit Led2 = P2^3;

#define Sw1 0x01                          // These are the port2 bits for Sw1
#define Sw2 0x02                          // and Sw2 on the development board
BYTE Switch1State = 0;                    // Indicate status of switch
BYTE Switch2State = 0;                    // starting at 0 == off

BYTE Toggle1 = 0;                         // Variable to make sure each button
BYTE Toggle2 = 0;                         // press and release toggles switch

BYTE Potentiometer = 0x00;                // Last read potentiometer value
BYTE Temperature = 0x00;                  // Last read temperature sensor value

BYTE Out_Packet[8] = {0,0,0,0,0,0,0,0};   // Last packet received from host
BYTE In_Packet[8]  = {0,0,0,0,0,0,0,0};   // Next packet to sent to host

/*** [BEGIN] USB Descriptor Information [BEGIN] ***/
code const UINT USB_VID = 0x10C4;
code const UINT USB_PID = 0xEA61;
code const BYTE USB_MfrStr[] = {0x1A,0x03,'S',0,'i',0,'l',0,'i',0,'c',0,'o',0,'n',0,' ',0,'L',0,'a',0,'b',0,'s',0};                       // Manufacturer String
code const BYTE USB_ProductStr[] = {0x10,0x03,'U',0,'S',0,'B',0,' ',0,'A',0,'P',0,'I',0}; // Product Desc. String
code const BYTE USB_SerialStr[] = {0x0A,0x03,'1',0,'2',0,'3',0,'4',0};
code const BYTE USB_MaxPower = 15;            // Max current = 30 mA (15 * 2)
code const BYTE USB_PwAttributes = 0x80;      // Bus-powered, remote wakeup not supported
code const UINT USB_bcdDevice = 0x0100;       // Device release number 1.00
/*** [ END ] USB Descriptor Information [ END ] ***/

code const BYTE TEMP_ADD = 112;           // This constant is added to Temperature

void Timer_Init(void);                       // Start timer 2 for use by ADC and to check switches
void Adc_Init(void);
void Port_Init(void);
void Suspend_Device(void);
void Initialize(void);
//-----------------------------------------------------------------------------
// Main Routine
//-----------------------------------------------------------------------------
void main(void)
{

   PCA0MD &= ~0x40;                       // Disable Watchdog timer

   USB_Clock_Start();                     // Init USB clock *before* calling USB_Init
   USB_Init(USB_VID,USB_PID,USB_MfrStr,USB_ProductStr,USB_SerialStr,USB_MaxPower,USB_PwAttributes,USB_bcdDevice);

   Initialize();
   USB_Int_Enable();
   while (1)
   {


    // It is possible that the contents of the following packets can change
    // while being updated.  This doesn't cause a problem in the sample
    // application because the bytes are all independent.  If data is NOT
    // independent, packet update routines should be moved to an interrupt
    // service routine, or interrupts should be disabled during data updates.
      if (Out_Packet[0] == 1) Led1 = 1;   // Update status of LED #1
      else Led1 = 0;
      if (Out_Packet[1] == 1) Led2 = 1;   // Update status of LED #2
      else Led2 = 0;
      P1 = (Out_Packet[2] & 0x0F);        // Set Port 1 pins


      In_Packet[0] = Switch1State;        // Send status of switch 1
      In_Packet[1] = Switch2State;        // and switch 2 to host
      In_Packet[2] = (P0 & 0x0F);         // Port 0 [0-3] (make sure j9 & j10 jumpered)
      In_Packet[3] = Potentiometer;       // Potentiometer value
      In_Packet[4] = Temperature;         // Temperature sensor value

   }
}

//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-------------------------
// Port_Init
//-------------------------
// Port Initialization
// - Configure the Crossbar and GPIO ports.
//
void Port_Init(void)
{
   P2MDIN   = 0xDF;                        // Port 2 pin 5 set as analog input
   P0MDOUT |= 0x0F;                        // Port 0 pins 0-3 set high impedence
   P1MDOUT |= 0x0F;                        // Port 1 pins 0-3 set high impedence
   P2MDOUT |= 0x0C;                        // Port 2 pins 0,1 set high impedence
   P2SKIP   = 0x20;                        // Port 1 pin 7 skipped by crossbar
   XBR0     = 0x00;
   XBR1     = 0x40;                        // Enable Crossbar
}

//-------------------------
// Timer_Init
//-------------------------
// Timer initialization
// - 1 mhz timer 2 reload, used to check if switch pressed on overflow and
// used for ADC continuous conversion
//
void Timer_Init(void)
{
   TMR2CN  = 0x00;                        // Stop Timer2; Clear TF2;

   CKCON  &= ~0xF0;                       // Timer2 clocked based on T2XCLK;
   TMR2RL  = -(24000000 / 12);              // Initialize reload value
   TMR2    = 0xffff;                      // Set to reload immediately

   ET2     = 1;                           // Enable Timer2 interrupts
   TR2     = 1;                           // Start Timer2
}

//-------------------------
// Adc_Init
//-------------------------
// ADC initialization
// - Configures ADC for single ended continuous conversion or Timer2
//
void Adc_Init(void)
{
   REF0CN  = 0x0E;                        // Enable voltage reference VREF
   AMX0P = 0x1E;                        // Positive input starts as temp sensor
   AMX0N = 0x1F;                        // Single ended mode(negative input = gnd)

   ADC0CF  = 0xF8;                        // SAR Period 0x1F, Right adjusted output

   ADC0CN  = 0xC2;                        // Continuous converion on timer 2 overflow
                                          // with low power tracking mode on

   EIE1   |= 0x08;                        // Enable conversion complete interrupt
}

//-------------------------
// Suspend_Device
//-------------------------
// Called when a DEV_SUSPEND interrupt is received.
// - Disables all unnecessary peripherals
// - Calls USB_Suspend()
// - Enables peripherals once device leaves suspend state
//
void Suspend_Device(void)
{
   // Disable peripherals before calling USB_Suspend()
   P0MDIN = 0x00;                       // Port 0 configured as analog input
   P1MDIN = 0x00;                       // Port 1 configured as analog input
   P2MDIN = 0x00;                       // Port 2 configured as analog input
   P3MDIN = 0x00;                       // Port 3 configured as analog input
   ADC0CN &= ~0x80;                     // Disable ADC0
   ET2 = 0;                             // Disable Timer 2 Interrupts


   USB_Suspend();                       // Put the device in suspend state

   // Once execution returns from USB_Suspend(), device leaves suspend state.
   // Reenable peripherals
   ADC0CN |= 0x80;                      // Enable ADC0
   P0MDIN = 0xFF;
   P1MDIN = 0x7F;                       // Port 1 pin 7 set as analog input
   P2MDIN = 0xFF;
   P3MDIN = 0x01;
   ET2 = 1;                             // Enable Timer 2 Interrupts
}

//-------------------------
// Initialize
//-------------------------
// Called when a DEV_CONFIGURED interrupt is received.
// - Enables all peripherals needed for the application
//
void Initialize(void)
{
   Port_Init();                           // Initialize crossbar and GPIO
   Timer_Init();                          // Initialize timer2
   Adc_Init();                            // Initialize ADC

}


//-------------------------
// Timer2_ISR
//-------------------------
// Called when timer 2 overflows, check to see if switch is pressed,
// then watch for release.
//
void Timer2_ISR(void) interrupt 5
{
   if (!(P2 & Sw1))                      // Check for switch #1 pressed
   {
      if (Toggle1 == 0)                   // Toggle is used to debounce switch
      {                                   // so that one press and release will
         Switch1State = ~Switch1State;    // toggle the state of the switch sent
         Toggle1 = 1;                     // to the host
      }
   }
   else Toggle1 = 0;                      // Reset toggle variable

   if (!(P2 & Sw2))                       // This is the same as above, but for Switch2
   {
      if (Toggle2 == 0)
      {
         Switch2State = ~Switch2State;
         Toggle2 = 1;
      }
   }
   else Toggle2 = 0;

   TF2H = 0;                              // Clear Timer2 interrupt flag
}

//-------------------------
// Adc_ConvComplete_ISR
//-------------------------
// Called after a conversion of the ADC has finished
// - Updates the appropriate variable for either potentiometer or temperature sensor
// - Switches the Adc multiplexor value to switch between the potentiometer and temp sensor
//
void Adc_ConvComplete_ISR(void) interrupt 10
{
   if (AMX0P == 0x1E)                  // This switches the AMUX between
   {                                     // the temperature sensor and the
      Temperature   = ADC0L;             // potentiometer pin after each
     Temperature += TEMP_ADD;
      AMX0P       = 0x04;              // switch to potentiometer ('F340 - P2.5)
     ADC0CF      = 0xFC;              // place ADC0 in left-adjusted mode
   }
   else
   {
      Potentiometer = ADC0H;
      AMX0P       = 0x1E;             // switch to temperature sensor
     ADC0CF      = 0xF8;             // place ADC0 in right-adjusted mode
   }

   AD0INT = 0;
   Block_Write(In_Packet, 8);
}


// Example ISR for USB_API
void  USB_API_TEST_ISR(void) interrupt 17
{
   BYTE INTVAL = Get_Interrupt_Source();

   if (INTVAL & RX_COMPLETE)
   {
      Block_Read(Out_Packet, 8);
   }

   if (INTVAL & DEV_SUSPEND)
   {
        Suspend_Device();
   }

   if (INTVAL & DEV_CONFIGURED)
   {
      Initialize();
   }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -