1. 下位机
1.1 main函数中第一步,根据需要先设置watchdog,一般不用的话,必须禁止watchdog,禁止方法见下例;
1.2 main函数第二步,设置系统时钟,具体见下例;
1.3 USB的中断函数不能省略,如省略会出现上位机不能识别USB设备的现象。
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "compiler_defs.h"
#include "C8051f340_defs.h"
#include <stddef.h>
#include "USB_API.h"
#define INTERRUPT_USBXpress 17
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
U8 Out_Packet[8] = {0,0,0,0,0,0,0,0}; // Last packet received from host
U8 In_Packet[8] = {0,0,0,0,0,0,0,0}; // Next packet to sent to host
/*** [BEGIN] USB Descriptor Information [BEGIN] ***/
SEGMENT_VARIABLE(USB_VID, U16, SEG_CODE) = 0x10C4;
SEGMENT_VARIABLE(USB_PID, U16, SEG_CODE) = 0xEA61;
SEGMENT_VARIABLE(USB_MfrStr[], U8, SEG_CODE) = // Manufacturer String
{
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
};
SEGMENT_VARIABLE(USB_ProductStr[], U8, SEG_CODE) = // Product Desc. String
{
0x10,
0x03,
'U',0,
'S',0,
'B',0,
' ',0,
'A',0,
'P',0,
'I',0
};
SEGMENT_VARIABLE(USB_SerialStr[], U8, SEG_CODE) = // Serial Number String
{
0x0A,
0x03,
'V',0,
'S',0,
'M',0,
'.',0
};
SEGMENT_VARIABLE(USB_MaxPower, U8, SEG_CODE) = 15; // Max current = 30 mA
// (15 * 2)
SEGMENT_VARIABLE(USB_PwAttributes, U8, SEG_CODE) = 0x80; // Bus-powered,
// remote wakeup not
// supported
SEGMENT_VARIABLE(USB_bcdDevice, U16, SEG_CODE) = 0x0100; // Device release
// number 1.00
/*** [ END ] USB Descriptor Information [ END ] ***/
SEG_CODE const U8 TEMP_ADD = 112; // This constant is added to Temperature
//-----------------------------------------------------------------------------
// Global Constants (SPI)
//-----------------------------------------------------------------------------
#define SYSCLK 12000000 // Internal oscillator frequency in Hz
//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------
void PORT_Init (void);
void T0_Wait_ms (unsigned char ms);
//-----------------------------------------
//Sepcification Port Defination
//-----------------------------------------
sbit led2 = P2^7;
sbit led3 = P2^6;
//sbit CDS = P0^4; //P0.4 as CDS line
//-----------------------------------------------------------------------------
// Main Routine
//-----------------------------------------------------------------------------
void main(void)
{
int i;
PCA0MD &= ~0x40; // Disable the Watchdog Timer
PCA0MD = 0x00;
OSCICN = 0x83; // Set the internal oscillator to
// 12 MHz
PORT_Init();
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);
USB_Int_Enable();
OSCICN |=0x03;
EA = 1; //Enable all interrupt
while (1)
{
//-------------------------------------------------------------------
if (Out_Packet[0] == 0x01) // Receive tes1 command
{
led2 = 0;
led3 = 0;
}
else
{
if(Out_Packet[0] == 0x02) // Receive test2 command
{
led2 = 1;
led3 = 1;
}
else
{
if(Out_Packet[0] == 0x03) // Receive test3 command
{
led2 = 1;
led3 = 0;
}
else
{
if(Out_Packet[0] == 0x04) // Receive test4 command
{
led2 = 0;
led3 = 1;
}
else
{
if (Out_Packet[0] == 0x10) // Receive read from USB command
{
for(i=0; i<8; i++)
{
In_Packet[i] = Out_Packet[i];
}
Block_Write(In_Packet,8); // Send data to PC by USB
led2=0;
led3=1;
}
else
P4 = 0X00; // Led all open as default
}
}
}
}
T0_Wait_ms(1);
}
}
//********************************************************************
// Initialization Subroutines
//********************************************************************
void PORT_Init (void)
{
P2MDOUT = 0xFF; // Make the LED push-pull
XBR1 = 0x40; // Enable the XBAR and weak pull-ups
}
//********************************************************************
// USB ISR
//********************************************************************
// Example ISR for USB_API
INTERRUPT(USB_API_TEST_ISR, INTERRUPT_USBXpress)
{
U8 INTVAL = Get_Interrupt_Source();
if (INTVAL & RX_COMPLETE)
{
Block_Read(Out_Packet, 8);
}
}
//-------------------
// T0_Wait_ms
//-------------------
void T0_Wait_ms (unsigned char ms)
{
TCON &= ~0x30; // Stop Timer0; Clear TF0
TMOD &= ~0x0f; // 16-bit free run mode
TMOD |= 0x01;
CKCON |= 0x04; // Timer0 counts SYSCLKs
while (ms) {
TR0 = 0; // Stop Timer0
TH0 = -(SYSCLK/1000 >> 8); // Overflow in 1ms
TL0 = -(SYSCLK/1000);
TF0 = 0; // Clear overflow indicator
TR0 = 1; // Start Timer0
while (!TF0); // Wait for overflow
ms--; // Update ms counter
}
TR0 = 0; // Stop Timer0
}
2. 上位机注意事项:
2.1 使用上位机USB读写函数时,函数第二个参数的含义是,读写数据暂存的buffer指针。在参考Siliconlab实例时,其buffer是用的一个结构体,其中分别含有Input和Output,而使用实例中的读语句时,其实是将数据读到Ouput中,对编写上位机易造成困惑。
所以,最好修改实例的buffer,Input和Output统一成一个。详见下图:
参考例子中读写函数,第二个参数指的一样
3. 操作过程中出现上位机发送按键按几次后,下位机停住,但也没有返回写入错误的现象:
原因:上下位机USB buffer size不一致。
USB buffer size涉及三个位置:上位机USB buffer size大小;
下位机USB buffer size 大小;
下位机USB 读写函数中,第二个参数(即USB buffer size大小)
Block_Read(USB_Packet, USB_Buf_Size);
Block_Write(USB_Packet, USB_Buf_Size);
4. USB buffer size的设置:
最大值为64,超过64会报错。