?? usb_main.c
字號(hào):
//-----------------------------------------------------------------------------
// 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();
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -