📄 main.c
字号:
/*
Copyright 2003 Cygnal Integrated Products, Inc.
File: main.c
Author: JS
Created: JAN 03
Modified: JUL 03 -- BW (changed 'while(!(CLKMUL & 0x20));')
Target Device: C8051F320
Source file for USB firmware. Includes main routine and
all hardware initialization routines.
This is the main routine file for the USBProgramGuide.wsp project,
which includes the following source files:
main.c
usb_desc.c
usb_isr.c
usb_stdreq.c
usb_utils.c
This firmware is intended to work with the Cygnal USB Test Application,
implementing two Interrupt pipes with 8-byte transfers. The endpoints
used are as follows:
Endpoint1 IN - Interrupt IN
Endpoint2 OUT - Interrupt OUT
The transmit buffer (used with IN packets) is the 8-byte array
<IN_PACKET>. This buffer is updated in the main loop. The receive
buffer (used with OUT packets) is the 8-byte array <OUT_PACKET>. The
information in received packets is used to update Port I/O in the
main loop.
******************************************/
#include <c8051f320.h> // SFR declarations
#include "usb_regs.h"
#include "usb_structs.h"
#include "usb_main.h"
#include "usb_desc.h"
//------------------------------------------------------------------------
// Global Constants
//------------------------------------------------------------------------
sbit LED1 = P2^2; // LED='1' means ON
sbit LED2 = P2^3;
sbit BTN1 = P2^0; // Target board button 1
sbit BTN2 = P2^1; // Target board button 2
//------------------------------------------------------------------------
// Local Function Prototypes
//------------------------------------------------------------------------
void USB0_Init (void);
void USB0_Enable (void);
void PORT_Init (void);
void SYSCLK_Init (void);
void Timer2_Init (void);
void ADC_Init (void);
//------------------------------------------------------------------------
// Global Variables
//------------------------------------------------------------------------
DEVICE_STATUS gDeviceStatus;
EP_STATUS gEp0Status;
EP_STATUS gEp1InStatus;
EP_STATUS gEp2OutStatus;
EP0_COMMAND gEp0Command;
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
//------------------------------------------------------------------------
// Main Routine
//------------------------------------------------------------------------
void main (void)
{
BYTE LastBTN1, LastBTN2 = 0;
PCA0MD &= ~0x40; // Disable Watchdog timer
PORT_Init (); // Initialize Crossbar and GPIO
SYSCLK_Init (); // Initialize oscillator
Timer2_Init (); // Initialize timer2
ADC_Init (); // Initialize ADC
USB0_Init (); // Initialize USB0
EA = 1; // Enable global interrupts
USB0_Enable (); // Enable USB0
// Main loop updates the IN_PACKET with Port I/O and analog
// measurement status, and updates Port I/O with information
// from the OUT_PACKET.
while (1)
{
LED1 = OUT_PACKET[0]; // Update status of LED #1
LED2 = OUT_PACKET[1]; // Update status of LED #2
P1 = (OUT_PACKET[2] & 0x0F); // Update Port1 outputs
// If button 1 is pressed and its previous state was open,
// toggle the button 1 flag.
if ((BTN1 == 0) && (LastBTN1 == 1))
{
IN_PACKET[0] = ~IN_PACKET[0];
}
LastBTN1 = BTN1; // Store the current button state
// If button 2 is pressed and its previous state was open,
// toggle the button 2 flag.
if ((BTN2 == 0) && (LastBTN2 == 1))
{
IN_PACKET[1] = ~IN_PACKET[1];
}
LastBTN2 = BTN2; // Store the current button state
IN_PACKET[2] = (P0 & 0x0F); // Update Port0 [0-3] indicators
// ADC data updated in ADC0 ISR
}
}
//------------------------------------------------------------------------
// Interrupt Service Routines (non-usb)
//------------------------------------------------------------------------
//---------------------------
// ADC0_ISR
//---------------------------
// - Record conversion data
// - Update MUX for next conversion
//
void ADC0_ISR (void) interrupt 10
{
// Handle Temperature Sensor measurement
if (AMX0P == AMX_TEMP_SENSE)
{
IN_PACKET[4] = ADC0H; // Update IN packet
AMX0P = AMX_P1_7; // Update AMUX
}
// Handle Potentiometer measurement
else
{
IN_PACKET[3] = ADC0H; // Update IN packet
AMX0P = AMX_TEMP_SENSE; // Update AMUX
}
AD0INT = 0;
}
//------------------------------------------------------------------------
// Initialization Routines
//------------------------------------------------------------------------
//---------------------------
// SYSCLK_Init
//---------------------------
// SYSLCK Initialization
// - Initialize the system clock and USB clock
//
void SYSCLK_Init (void)
{
unsigned char delay = 100;
OSCICN |= 0x03; // Configure internal oscillator for
// its maximum frequency
CLKMUL = 0x00; // Select internal oscillator as
// input to clock multiplier
CLKMUL |= 0x80; // Enable clock multiplier
while (delay--); // Delay for >5us
CLKMUL |= 0xC0; // Initialize the clock multiplier
while(!(CLKMUL & 0x20)); // Wait for multiplier to lock
CLKSEL |= USB_4X_CLOCK; // Select USB clock
CLKSEL |= SYS_INT_OSC; // Select system clock
}
//---------------------------
// USB0_Init
//---------------------------
// USB Initialization
// - Initialize USB0
// - Enable USB0 interrupts
// - Enable USB0 transceiver
// - USB0 left disabled
//
void USB0_Init (void)
{
UWRITE_BYTE(POWER, 0x08); // Asynch. reset
UWRITE_BYTE(IN1IE, 0x0F); // Enable Endpoint0 Interrupt
UWRITE_BYTE(OUT1IE, 0x0F);
UWRITE_BYTE(CMIE, 0x04); // Enable Reset interrupt
USB0XCN = 0xC0; // Enable transceiver
USB0XCN |= FULL_SPEED; // Select device speed
UWRITE_BYTE(CLKREC, 0x80); // Enable clock recovery,
// single-step mode disabled
EIE1 |= 0x02; // Enable USB0 Interrupts
}
//---------------------------
// USB0_Enable
//---------------------------
// USB Enable
// - Enable USB0
//
void USB0_Enable (void)
{
UWRITE_BYTE(POWER, 0x00); // Enable USB0 by clearing the
// USB Inhibit bit
// Suspend mode disabled
}
//---------------------------
// ADC_Init
//---------------------------
// ADC initialization
// - Single-ended mode
// - Conversions on Timer2 overflows
// - Left-justified data
// - Low power tracking mode
// - Interrupts enabled
//
void ADC_Init (void)
{
REF0CN = 0x0E; // Temperature sensor enabled,
// internal bias enabled,
// internal voltage reference
// enabled
AMX0P = AMX_TEMP_SENSE; // Temp sensor as positive input
AMX0N = AMX_GND; // GND as negative input
// (single-ended)
ADC0CF = (SYSCLK/2000000) << 3; // SAR clock set to 2MHz
ADC0CF |= 0x04; // Left-justified data
ADC0CN = 0xC2; // ADC0 enabled, low power
// tracking mode,
// Timer2 conversions
EIE1 |= 0x08; // Enable conversion complete
// interrupt
}
//---------------------------
// Timer2_Init
//---------------------------
// Timer initialization
// - Timer2 configured to overflow at the frequency defined
// by <SAMPLERATE> for ADC conversions
//
void Timer2_Init ()
{
TMR2CN = 0x00; // Stop Timer2; Clear TF2;
CKCON |= 0x10; // SYSCLK as Timer2 clock source
TMR2RL = -(SYSCLK/SAMPLERATE); // Timer2 overflows at <SAMPLERATE>
TMR2 = 0xFFFF; // set to reload immediately
TR2 = 1; // start Timer2
}
//---------------------------
// PORT_Init
//---------------------------
// Port Initialization
// - Configure the Crossbar and GPIO ports.
//
void PORT_Init (void)
{
P1MDIN = 0x7F; // P0.7: analog input
P0MDOUT = 0x0F; // P0.0-P0.3: push-pull
P1MDOUT = 0x0F; // P1.0-P1.3: push-pull
P2MDOUT = 0x0C; // P2.3-P2.2: push-pull
P1SKIP = 0x80; // P1.7 skipped by Crossbar
XBR0 = 0x00; //
XBR1 = 0x40; // Enable Crossbar
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -