📄 usb_main.c
字号:
//-----------------------------------------------------------------------------
// USB_MAIN.c
//-----------------------------------------------------------------------------
// Copyright 2003 ZZLXKJ, Inc.
//
// AUTH: WHL
// DATE: 22 FEB 02
//
//
// Target: C8051F32x
// Tool chain: KEIL C51 6.03 / KEIL EVAL C51
//
// REVISIONS: 11/22/02 - DM: Added support for switches and sample USB
// interrupt application.
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f320.h>
#include "USB_REGISTER.h"
#include "USB_MAIN.h"
#include "USB_DESCRIPTOR.h"
#include "math.h"
//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F32x
//-----------------------------------------------------------------------------
sfr16 TMR2RL = 0xca; // Timer2 reload value
sfr16 TMR2 = 0xcc; // Timer2 counter
sfr16 TMR3RL = 0x92; // Timer2 reload registers
sfr16 TMR3 = 0x94; // Timer3 counter registers
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
//
//25AA040 instruction set
//
#define READ_25AA 0x03 //Read data from memory array beginning at selected address
#define WRITE_25AA 0x02 //Write data to memory array beginning at selected address
#define WRDI_25AA 0x04 //Reset the write enable latch(disable write operation)
#define WREN_25AA 0x06 //set the write enagle latch(enable write operations)
#define RDSR_25AA 0x05 //Read status register
#define WRSR_25AA 0x01 //Write status registet
sbit CS_25AA =P2^3;
// This example demonstrates how the C8051F32x SMBus interface can communicate
// with a 128 byte I2C Serial EEPROM (Microchip 24LC01B) .
// - Interrupt-driven SMBus implementation
// - Only master states defined (no slave or arbitration)
// - Timer1 used as SMBus clock source
// - Timer2 used by SMBus for SCL low timeout detection
// - SCL frequency defined by <SMB_FREQUENCY> constant
// - Pinout:
// P1.0 -> SDA (SMBus)
// P1.1 -> SCL (SMBus)
/*
//24CXX instruction set
#define READ_24LC 0x01 // SMBus READ command
#define WRITE_24LC 0x00 // SMBus WRITE command
// Device addresses (7 bits, lsb is a don't care)
#define EEPROM_ADDR 0xA0 // Device address for slave target Note: This address is specified
// in the Microchip 24LC01B datasheet.
// SMBus Buffer Size
#define SMB_BUFF_SIZE 0x08 // Defines the maximum number of bytes
// that can be sent or received in a single transfer
// Status vector - top 4 bits only
#define SMB_MTSTA 0xE0 // (MT) start transmitted
#define SMB_MTDB 0xC0 // (MT) data byte transmitted
#define SMB_MRDB 0x80 // (MR) data byte received
//unsigned char whl;
unsigned char* pSMB_DATA_IN; // Global pointer for SMBus data All receive data is written here
unsigned char SMB_SINGLEBYTE_OUT; // Global holder for single byte writes.
unsigned char* pSMB_DATA_OUT; // Global pointer for SMBus data. All transmit data is read from here
unsigned char SMB_DATA_LEN; // Global holder for number of bytes
// to send or receive in the current SMBus transfer.
unsigned char WORD_ADDR; // Global holder for the EEPROM word address that will be accessed in
// the next transfer
unsigned char TARGET; // Target SMBus slave address
bit SMB_BUSY = 0; // Software flag to indicate when the
// EEPROM_ByteRead() or EEPROM_ByteWrite() functions have claimed the SMBus
bit SMB_RW; // Software flag to indicate the direction of the current transfer
bit SMB_SENDWORDADDR; // When set, this flag causes the ISR to send the 8-bit <WORD_ADDR> after sending the slave address.
bit SMB_RANDOMREAD; // When set, this flag causes the ISR to send a START signal after sending the word address.
bit SMB_ACKPOLL; // When set, this flag causes the ISR to send a has acknowledged its slave address
*/
#define SYSCLK_EXT 24000000 // SYSCLK External frequency in Hz
#define BAUDRATE 460800 // 961200 // Baud rate of UART in bps
#define TIMER2_RATE 20000 // Timer 2 overflow rate in Hz
#define SMB_FREQUENCY 100000 // Target SCL clock rate
sbit Led1 = P2^0; // LED='1' means ON
sbit Led2 = P2^1;
#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
// BYTE SCIOut_Packet[8] = {0,0,0,0,0,0,0,0}; // Last packet received from host
// BYTE SCIIn_Packet[8] = {0,0,0,0,0,0,0,0}; // Next packet to sent to host
//-----------------------------------------------------------------------------
// Main Routine
//-----------------------------------------------------------------------------
void main(void)
{
int y;
char in_buff[8] = {0}; // incoming data buffer
char out_buff[8] = "abcdefg"; // outgoing data buffer
unsigned char temp_char; // temporary variable
PCA0MD &= ~0x40; // Disable Watchdog timer
Sysclk_Init(); // Initialize oscillator
Port_Init(); // Initialize crossbar and GPIO
Usb0_Init(); // Initialize USB0
Timer2_Init(SYSCLK_EXT/TIMER2_RATE); // Init Timer 2
Adc_Init(); // Initialize ADC
UART0_Init(); // Initialize UART
// SPI0_Init(); // Initialize SPI
// Timer0_Init (); // Configure Timer0 for use as SMBus clock source
Timer1_Init (); // Configure Timer1 for use as UART0 clock source
// Timer3_Init (); // Configure Timer3 for use with SMBus low timeout detect
// SMBus_Init(); // Initialize IIC
// EIE1 |= 0x80; // Timer3 interrupt enable
IE |= 0x20; // Timer2 interrupt enable
EA = 1; // Global interrupt enable
/* EEPROM_ByteWrite(0x25, 0xAA); // Write the value 0xBB to location 0x25 in the EEPROM
temp_char = EEPROM_ByteRead(0x25); // Read the value at location 0x25 in the EEPROM
EEPROM_ByteWrite(0x25, 0xBB); // Write the value 0xBB to location 0x25 in the EEPROM
EEPROM_ByteWrite(0x38, 0xCC); // Write the value 0xCC to location 0x38 in the EEPROM
temp_char = EEPROM_ByteRead(0x25); // Read the value at location 0x25 in the EEPROM
temp_char = EEPROM_ByteRead(0x38); // Read the value at location 0x38 in the EEPROM
EEPROM_WriteArray(0x50, (unsigned char) out_buff, sizeof(out_buff)); // Store the outgoing data buffer at EEPROM address 0x50
EEPROM_ReadArray((unsigned char) in_buff, 0x50, sizeof(in_buff)); // Fill the incoming data buffer with data starting at EEPROM address 0x50
*/
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
// Led2 = 0;
Out_Packet[0] = 0;
for(y=0;y<100;y++)
Delay();
// Delay();
}
else
{ Led1 = 0;
Out_Packet[0] = 1;
// Led2 = 1;
for(y=0;y<200;y++)
// Delay();
Delay();
}
// 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] = Read_25aa_status();
Write_25aa_enable();
Write_25aa_data(00,0x21);
In_Packet[1] = Read_25aa_data(00);
*/
/* 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
//-----------------------------------------------------------------------------
//-------------------------
// Sysclk_Init
//-------------------------
// SYSLCK Initialization
// - Initialize the system clock and USB clock
//
void Sysclk_Init(void)
{
#ifdef _USB_LOW_SPEED_
OSCICN |= 0x03; // Configure internal oscillator for
// its maximum frequency and enable
// missing clock detector
CLKSEL = SYS_INT_OSC; // Select System clock
CLKSEL |= USB_INT_OSC_DIV_2; // Select USB clock
#else
#ifdef _INT_OSC_
OSCICN |= 0x03; // Configure internal oscillator for
// its maximum frequency and enable
// missing clock detector
CLKMUL = 0x00; // Select internal oscillator as
// input to clock multiplier
CLKMUL |= 0x80; // Enable clock multiplier
CLKMUL |= 0xC0; // Initialize the clock multiplier
Delay(); // Delay for clock multiplier to begin
while(!(CLKMUL & 0x20)); // Wait for multiplier to lock
CLKSEL = SYS_INT_OSC; // Select System clock
CLKSEL |= USB_4X_CLOCK; // Select USB clock
#else
P0MDIN &=0xF3; // p0.2,p0.3 XTAL1 XTAL2
P0SKIP |=0x0C; // p0.2,p0.3 skipped by crossbar
XBR0 |=0x08;
// XBR1 |=0x40; //Enable Crossbar
OSCXCN |=0x67;
Delay(); // Delay for clock multiplier to begin
while(!(OSCXCN & 0x80)); // Wait for multiplier to lock
CLKSEL = SYS_EXT_OSC; // Select system clock External oscillator
OSCICN = 0x00; // internal oscillator OFF
CLKMUL = 0x02; // Select External oscillator/2 as input to clock multiplier
CLKMUL |= 0x80; // Enable clock multiplier
CLKMUL |= 0xC0; // Initialize the clock multiplier
Delay(); // Delay for clock multiplier to begin
while(!(CLKMUL & 0x20)); // Wait for multiplier to lock
CLKSEL |= USB_4X_CLOCK; // Select USB clock
#endif
#endif /* _USB_LOW_SPEED_ */
}
//-------------------------
// Port_Init
//-------------------------
// Port Initialization
// - Configure the Crossbar and GPIO ports.
//
void Port_Init(void)
{
P0MDIN |= 0x30; // P0.4,P0.5 set as UTAR0 TX0,RX0
P0MDOUT |= 0x10; // enable UTX as push-pull output
P0MDIN |= 0xC3; // P0.0,P0.1 P0.6,P0.7 set as SPI0 SCK,MISO MOSI NSS
P0MDOUT |= 0x41; // enable SPI_MOSI,SCK as push-pull output
P1MDIN |= 0x03; // P0.0,P0.1 set as SMBus SDA,SCL
P1MDOUT |= 0x03; // enable SMBus_SDA,SCL as push-pull output
P1MDIN &= 0x3F; // Port 1 pin 7,6 set as analog input
P2MDOUT |= 0x0F; // Port 2 pins 0,1 set high impedence
P0SKIP |= 0x80;
P1SKIP = 0xC0; // Port 1 pin 7,6 skipped by crossbar
XBR0 |= 0x07; // Enable UART0,SPI0,SMBus
XBR1 = 0x40; // Enable Crossbar
CS_25AA =1;
}
//-------------------------
// Usb0_Init
//-------------------------
// USB Initialization
// - Initialize USB0
// - Enable USB0 interrupts
// - Enable USB0 transceiver
// - Enable USB0 with suspend detection
//
void Usb0_Init(void)
{
POLL_WRITE_BYTE(POWER, 0x08); // Force Asynchronous USB Reset
POLL_WRITE_BYTE(IN1IE, 0x07); // Enable Endpoint 0-2 in interrupts
POLL_WRITE_BYTE(OUT1IE, 0x07); // Enable Endpoint 0-2 out interrupts
POLL_WRITE_BYTE(CMIE, 0x07); // Enable Reset, Resume, and Suspend interrupts
#ifdef _USB_LOW_SPEED_
USB0XCN = 0xC0; // Enable transceiver; select low speed
POLL_WRITE_BYTE(CLKREC, 0xA0); // Enable clock recovery; single-step mode
// disabled; low speed mode enabled
#else
USB0XCN = 0xE0; // Enable transceiver; select full speed
POLL_WRITE_BYTE(CLKREC, 0x80); // Enable clock recovery, single-step mode
// disabled
#endif /* _USB_LOW_SPEED_ */
EIE1 |= 0x02; // Enable USB0 Interrupts
EA = 1; // Global Interrupt enable
// Enable USB0 by clearing the USB Inhibit bit
POLL_WRITE_BYTE(POWER, 0x01); // and enable suspend detection
}
//-------------------------
// Timer_Init
//-------------------------
// Timer initialization
// - Timer 2 reload, used to check if switch pressed on overflow and
// used for ADC continuous conversion
//
void Timer2_Init (int counts)
{
TMR2CN = 0x00; // STOP Timer2; Clear TF2H and TF2L; // disable low-byte interrupt; disable // split mode; select internal timebase CKCON |= 0x10; // Timer2 uses SYSCLK as its timebase TMR2RL = -counts; // Init reload values TMR2 = TMR2RL; // Init Timer2 with reload value ET2 = 0; // disable 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
// REF0CN = 0x03; //Enable voltage reference VREF from p0.7
// AMX0P = 0x07; // Positive input starts as temp sensor
AMX0P = 0x06; // Positive input starts as temp sensor
AMX0N = 0x1F; // Single ended mode(negative input = gnd)
// AMX0P = 0x07;
// AMX0N = 0x06;
ADC0CF = (SYSCLK/3000000) << 3; // ADC conversion clock <= 3MHz
ADC0CF |= 0x04; // Make ADC0 right-justified
ADC0CN = 0xC2; // Continuous converion on timer 2 overflow
// with low power tracking mode on
EIE1 |= 0x08; // Enable conversion complete interrupt
}
//-----------------------------------------------------------------------------// UART0_Init//-----------------------------------------------------------------------------//// Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1.// void UART0_Init (void){ SCON0 = 0x10; // SCON0: 8-bit variable bit rate level of STOP bit is ignored // RX enabled ninth bits are zeros clear RI0 and TI0 bits if (SYSCLK_EXT/BAUDRATE/2/256 < 1)
{ TH1 = -(SYSCLK_EXT/BAUDRATE/2); CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -