📄 usb_main.c
字号:
//-----------------------------------------------------------------------------
// USB_Main.c
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "USB_Type.h"
#include "USB_Configuration.h"
#include "USB_Register.h"
#include "USB_Descriptor.h"
#include "USB_Standard_Requests.h"
#include "USB_ISR.h"
#include "USB_CDC_UART.h"
#include "FIFO_RW.h"
#include "USB_Main.h"
#if defined KEIL
#include <intrins.h> // for _testbit_(), _nop_()
#endif // KEIL
//-----------------------------------------------------------------------------
// Definitions
//-----------------------------------------------------------------------------
#if defined C8051F320_H
#define SYSCLK 24000000L // SYSCLK frequency in Hz
#endif
#if defined C8051F340_H
#define SYSCLK 48000000L // SYSCLK frequency in Hz
#endif
//-----------------------------------------------------------------------------
// 16-bit SFR Definitions
//-----------------------------------------------------------------------------
#if defined KEIL
sfr16 TMR2RL = 0xca; // Timer2 reload value
sfr16 TMR2 = 0xcc; // Timer2 counter
#endif // KEIL
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
// port assignment
#if defined KEIL
sbit Sw1 = P2^0;
sbit Sw2 = P2^1;
sbit Led1 = P2^2; // LED='1' means ON
sbit Led2 = P2^3;
#endif // KEIL
#if defined SDCC
#define Sw1 P2_0
#define Sw2 P2_1
#define Led1 P2_2 // LED='1' means ON
#define Led2 P2_3
#endif // SDCC
static bit Switch1State = FALSE; // Indicate status of switch
static bit Switch2State = FALSE; // starting at 0 == off
static bit Toggle1 = FALSE; // Variable to make sure each button
static bit Toggle2 = FALSE; // press and release toggles switch
volatile bit switch_changed = FALSE;
//-----------------------------------------------------------------------------
// Static variables in this file
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Local Prototypes
//-----------------------------------------------------------------------------
// Initialization Routines
void Sysclk_Init(void); // Initialize the system clock
void Port_Init(void); // Configure ports
void Timer_Init(void); // Timer 2 for use by ADC and swtiches
//-----------------------------------------------------------------------------
// ISR prototype
//-----------------------------------------------------------------------------
#if defined SDCC
extern void Usb_ISR(void) interrupt 8;
extern void Timer2_ISR(void) interrupt 5;
#endif // SDCC
//------------------------------------------------------------------------
// startup routine
//------------------------------------------------------------------------
#if defined SDCC
unsigned char _sdcc_external_startup ( void )
{
PCA0MD &= ~0x40; // Disable Watchdog timer
return 0;
}
#endif // SDCC
//-----------------------------------------------------------------------------
// Main Routine
//-----------------------------------------------------------------------------
void main(void)
{
#if defined KEIL
PCA0MD &= ~0x40; // Disable Watchdog timer temporarily
#endif // KEIL
Sysclk_Init(); // Initialize oscillator
Port_Init(); // Initialize crossbar and GPIO
Timer_Init(); // Initialize timer2
Flush_COMbuffers(); // Initialize COM ring buffer
Led1 = FALSE;
Led2 = FALSE;
Usb0_Init(); // Initialize USB0 - at the end of initizaliation
EIE1 |= 0x02; // Enable USB0 interrupt
IE |= 0xA0; // Enable Timer2 and Global Interrupt enable
while ( 1 ) { // main loop
{ // task1 - CDC support
BYTE dt;
BYTE line_state;
CDC_Handle_Bulk_IN(); // Poll IN/OUT EP2 and handle transaction
CDC_Handle_Bulk_OUT();
if ( switch_changed ) // Reflect the switch status to DSR and CTS signaling
{
switch_changed = FALSE;
line_state = 0;
if ( Switch1State ) line_state |= CDC_DSR;
// if ( Switch2State ) line_state |= CDC_CTS; // CTS is not supported in generic CDC
Update_Line_State( line_state );
}
while (TXReady && RXReady) // loop back TX to RX
{
dt = COMGetByte();
COMPutByte( dt );
}
Led1 = uart_DTR; // output line status
Led2 = uart_RTS;
}
}
}
//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Sysclk_Init
//-----------------------------------------------------------------------------
//
// Initialize the system clock and USB clock
//
//-----------------------------------------------------------------------------
#if defined KEIL
#include <intrins.h>
#endif
static void Sysclk_Init(void)
{
CLKSEL = 0x00; // Set SYSCLK to 12 / 8 MHz
OSCICN &= ~0x03;
CLKMUL = 0x00; // Select internal oscillator as
// input to clock multiplier
CLKMUL |= 0x80; // Enable clock multiplier
// delay about 5 us (8 clock)
#if defined KEIL
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
#endif
#if defined SDCC
_asm
DIV AB
_endasm;
#endif
CLKMUL |= 0xC0; // Initialize the clock multiplier
while(!(CLKMUL & 0x20)); // Wait for multiplier to lock
#if defined C8051F320_H
CLKSEL = USB_4X_CLOCK | SYS_4X_DIV_2; // Select system clock and USB clock
#endif // C8051F320_H
#if defined C8051F340_H
FLSCL |= 0x10; // set FLRT for 48MHz SYSCLK
CLKSEL = USB_4X_CLOCK | SYS_4X; // Select system clock and USB clock
#endif // C8051F340_H
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// This function configures the crossbar and GPIO ports.
//
// F320DB
// P1.7 analog Potentiometer
// P2.2 digital push-pull LED
// P2.3 digital push-pull LED
//
// F340DB
// P2.2 digital push-pull LED
// P2.3 digital push-pull LED
// P2.5 analog Potentiometer
//-----------------------------------------------------------------------------
static void Port_Init(void)
{
#if defined C8051F320_H
P1MDIN = 0x7F; // Port 1 pin 7 set as analog input
P0MDOUT |= 0x0F; // Port 0 pins 0-3 set push-pull
P1MDOUT |= 0x0F; // Port 1 pins 0-3 set push-pull
P2MDOUT |= 0x0C; // P2.2 and P2.3 set to push-pull
P1SKIP = 0x80; // Port 1 pin 7 skipped by crossbar
XBR0 = 0x00;
XBR1 = 0x40; // Enable Crossbar
#endif // C8051F320_H
#if defined C8051F340_H
P2MDIN = ~(0x20); // 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 empedence
P2SKIP = 0x20; // Port 2 pin 5 skipped by crossbar
XBR0 = 0x00;
XBR1 = 0x40; // Enable Crossbar
#endif // C8051F340_H
}
//-----------------------------------------------------------------------------
// Usb_Suspend
//-----------------------------------------------------------------------------
//
// Enter suspend mode after suspend signalling is present on the bus
// - called from USB ISR
//
//-----------------------------------------------------------------------------
//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma save
#pragma nooverlay
#endif // SDCC
#ifdef ENABLE_SUSPEND_RESUME
void Usb_Suspend(void)
{
// Put the device in a low power configuration
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
// REF0CN = 0x00; // Disable voltage reference
OSCICN |= 0x20; // Put oscillator to suspend
// When the device receives a non-idle USB event, it will resume execution
// on the instruction that follows OSCICN |= 0x20.
// Re-enable everything that was disabled when going into Suspend
#if defined C8051F320_H
P0MDIN = 0xFF; // Port 0 configured as diital input
P1MDIN = 0x7F; // Port 1 pin 7 set as analog input
P2MDIN = 0xFF; // Port 2 configured as diital input
P3MDIN = 0xFF; // Port 3 configured as diital input
#endif // C8051F320_H
#if defined C8051F340_H
P0MDIN = 0xFF; // Port 0 configured as diital input
P1MDIN = 0xFF; // Port 1 configured as diital input
P2MDIN = ~(0x20); // Port 2 pin 5 set as analog input
P3MDIN = 0xFF; // Port 3 configured as diital input
#endif // C8051F340_H
// REF0CN = 0x0E; // Enable voltage reference VREF
// ADC0CN |= 0x80; // Re-enable ADC
}
#endif // ENABLE_SUSPEND_RESUME
//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma restore
#endif // SDCC
//-----------------------------------------------------------------------------
// Usb_Resume
//-----------------------------------------------------------------------------
//
// Resume normal USB operation
// - called from USB ISR
//
//-----------------------------------------------------------------------------
//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma save
#pragma nooverlay
#endif // SDCC
#ifdef ENABLE_SUSPEND_RESUME
// In this implementation, suspend/resume is supported by the oscillator suspend (OSCICN.5)
// Then, the resume process is also coded in Usb_Suspend(), just after "OSCICN |= 0x20"
/*
void Usb_Resume(void)
{
}
*/
#endif // ENABLE_SUSPEND_RESUME
//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma restore
#endif // SDCC
//-----------------------------------------------------------------------------
// Timer_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// 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 = 0; // Initialize reload value
TMR2 = 0xffff; // Set to reload immediately
TR2 = 1; // Start Timer2
}
//-----------------------------------------------------------------------------
// Timer2_ISR
//-----------------------------------------------------------------------------
//
// Called when timer 2 overflows, check to see if switch is pressed,
// then watch for release.
//
//-----------------------------------------------------------------------------
void Timer2_ISR(void) interrupt 5
{
TF2H = 0; // Clear Timer2 interrupt flag
if ( !Sw1 ) // Check for switch #1 pressed
{
if ( !Toggle1 ) // Toggle is used to debounce switch
{ // so that one press and release will
Switch1State = !Switch1State; // toggle the state of the switch sent
Toggle1 = TRUE; // to the host
switch_changed = TRUE;
}
}
else Toggle1 = FALSE; // Reset toggle variable
if ( !Sw2 ) // Same as above, but Switch2
{
if ( !Toggle2 )
{
Switch2State = !Switch2State;
Toggle2 = TRUE;
switch_changed = TRUE;
}
}
else Toggle2 = FALSE;
}
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -