标签:
USB 单片机 固件
看到头都大了,虽然不是全都明白,但起码走了一遍程序,附上我读完主程序涉及的所有注释.直接一句句往下读就行了,函数都在程序的后面的,找不到就用查找功能找一下.
void main(void)
{
unsigned short ID;
unsigned char high,low;
init_port();
init_special_interrupts();
init_flags();
ID=D12_ReadChipID();
high=(unsigned char)(ID>>8);
low=(unsigned char)ID;
reconnect_USB();
while( TRUE )
{
if (bEPPflags.bits.bus_reset) //总线复位处理
{
DISABLE;
bEPPflags.bits.bus_reset = 0; //清总线复位标志
ENABLE;
// D12SUSPD = 1; //释放 PDIUSBD12 挂起控制
}
/* if (bEPPflags.bits.suspend) //挂起改变处理
{
DISABLE;
bEPPflags.bits.suspend= 0; //清除挂起改变标志
ENABLE;
if(D12SUSPD == 1) //进入挂起处理
{
D12SUSPD = 0; //唤醒 PDIUSBD12,使得USB器件在
//MCU进入低功耗模式后再进入挂起
P0 = 0xFF;
P1 = 0xFF;
P2 = 0xFF;
P3 = 0xFF;
D12SUSPD = 1; //释放挂起控制
PCON |= 0x02; //进入掉电模式
while (1); //芯片进入死循环,因为标志51进入掉电
} //后,只有复位才可以唤醒芯片
} // if suspend change*/
if (bEPPflags.bits.setup_packet) //Setup 包处理
{
DISABLE;
bEPPflags.bits.setup_packet = 0;
ENABLE;
control_handler(); //调用请求处理子程序
// D12SUSPD = 1; //释放挂起控制
} // if setup_packet
if(bEPPflags.bits.configuration)
IspControl();
} // Main Loop
}
void init_port()
{
P0 = 0xFF;
P1 = 0xFF;
P2 = 0xFF;
P3 = 0xFF;
// D12SUSPD = 0;
}
void init_special_interrupts(void)
{
EA=1;
IT1=0;
EX1=1;
PX1=1;
}
void init_flags()
{
bEPPflags.bits.bus_reset=0;
bEPPflags.bits.suspend=0;
bEPPflags.bits.setup_packet=0;
bEPPflags.bits.remote_wakeup=0;
bEPPflags.bits.in_isr=0;
bEPPflags.bits.control_state=0;
bEPPflags.bits.configuration=0;
bEPPflags.bits.ep1_rxdone=0;
bEPPflags.bits.main_rxdone=0;
}
/*
//*************************************************************************
// structure and union definitions
//*************************************************************************
*/
typedef union _epp_flags
{
struct _flags
{
// unsigned char timer : 1; //时间溢出
unsigned char bus_reset : 1; //总线复位标志
unsigned char suspend : 1; //挂起改变标志
unsigned char setup_packet : 1; //收到 setup 包
unsigned char remote_wakeup : 1; //远程唤醒标志(未使用)
unsigned char in_isr : 1; //USB中断标志
unsigned char control_state : 2; //控制端点处理状态
//0: 空闲
//1: 数据发送
//2: 数据接收
unsigned char configuration : 1; //配置标志(0:未配置;1:已经配置)
// unsigned char verbose : 1;
unsigned char ep1_rxdone : 1; //端点1收到数据标志
unsigned char main_rxdone : 1; //主端点收到数据标志
unsigned char setup_dma : 2; // V2.3
// unsigned char dma_state : 2;
// unsigned char power_down : 1; // Smart Board
} bits;
unsigned short value;
} EPPFLAGS;
unsigned short D12_ReadChipID(void)
{
unsigned short i,j;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND, 0xFD); // #define D12_COMMAND 0x03
i=inportb(D12_DATA); // #define D12_DATA 0x02
j=inportb(D12_DATA);
i += (j<<8);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
return i;
}
//向PDIUSBD12发送数据或命令的子程序
void outportb(unsigned char port,unsigned char val)
{
unsigned char xdata *ext_address;
MCU_D12CS=0; //片选信号,低有效
ext_address=0xff00 + port;
*ext_address = val;
MCU_D12CS=1;
}
//从PDIUSBD12读取数据
unsigned char inportb(unsigned char port)
{
unsigned char c;
unsigned char xdata *ext_address;
MCU_D12CS=0;
ext_address=0xff00 + port;
c = *ext_address ;
MCU_D12CS=1;
return c;
}
void reconnect_USB(void)
{
// D12SUSPD = 0; //唤醒 PDIUSBD12
disconnect_USB(); //断开芯片与USB总线连接
connect_USB();
}
void disconnect_USB(void)
{
// 初始化 PDIUSBD12 工作状态(断开 Soft Connet 上拉电阻)
D12_SetMode(D12_NOLAZYCLOCK, D12_SETTOONE | D12_CLOCK_12M); //#define D12_NOLAZYCLOCK 0x02
} //#define D12_SETTOONE 0x40
//#define D12_CLOCK_12M 0x03
/*设置模式命令:F3H*/
void D12_SetMode(unsigned char bConfig, unsigned char bClkDiv)
{
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND, 0xF3);
outportb(D12_DATA, bConfig);
outportb(D12_DATA, bClkDiv);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
}
void connect_USB(void)
{
D12_SetDMA(D12_ENDP4INTENABLE | D12_ENDP5INTENABLE); //#define D12_ENDP4INTENABLE 0x40
//#define D12_ENDP5INTENABLE 0x80
D12_SetMode(D12_NOLAZYCLOCK|D12_SOFTCONNECT, D12_SETTOONE | D12_CLOCK_12M);
//#define D12_SOFTCONNECT 0x10
}
/*设置DMA命令:FBH*/
void D12_SetDMA(unsigned char bMode)
{
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND, 0xFB);
outportb(D12_DATA, bMode);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
}
while( TRUE )
{
if (bEPPflags.bits.bus_reset) //总线复位处理
{
DISABLE;
bEPPflags.bits.bus_reset = 0; //清总线复位标志
ENABLE;
// D12SUSPD = 1; //释放 PDIUSBD12 挂起控制
}
/* if (bEPPflags.bits.suspend) //挂起改变处理
{
DISABLE;
bEPPflags.bits.suspend= 0; //清除挂起改变标志
ENABLE;
if(D12SUSPD == 1) //进入挂起处理
{
D12SUSPD = 0; //唤醒 PDIUSBD12,使得USB器件在
//MCU进入低功耗模式后再进入挂起
P0 = 0xFF;
P1 = 0xFF;
P2 = 0xFF;
P3 = 0xFF;
D12SUSPD = 1; //释放挂起控制
PCON |= 0x02; //进入掉电模式
while (1); //芯片进入死循环,因为标志51进入掉电
} //后,只有复位才可以唤醒芯片
} // if suspend change*/
if (bEPPflags.bits.setup_packet) //Setup 包处理
{
DISABLE;
bEPPflags.bits.setup_packet = 0;
ENABLE;
control_handler(); //调用请求处理子程序
// D12SUSPD = 1; //释放挂起控制
} // if setup_packet
if(bEPPflags.bits.configuration)
IspControl();
} // Main Loop
}
void control_handler()
{
unsigned char type, req;
//读取请求类型,保留bit5和bit6
//#define USB_REQUEST_TYPE_MASK (unsigned char)0x60
//#define USB_REQUEST_MASK (unsigned char)0x0F
type = ControlData.DeviceRequest.bmRequestType & USB_REQUEST_TYPE_MASK;
////读取请求代码,保留低4位
req = ControlData.DeviceRequest.bRequest & USB_REQUEST_MASK;
if (type == USB_STANDARD_REQUEST) //标准请求处理
(*StandardDeviceRequest[req])();
else
stall_ep0(); //无效请求,返回STALL
}
//USB设备请求寄存器
typedef struct _device_request
{
unsigned char bmRequestType; //请求类型(数据传输方向,类型,接收器)
unsigned char bRequest; //USB请求
unsigned short wValue; //USB请求值
unsigned short wIndex; //USB请求索引
unsigned short wLength; //计数长度
} DEVICE_REQUEST;
extern CONTROL_XFER ControlData;
#define MAX_CONTROLDATA_SIZE 8
//Setup 包数据缓冲区
typedef struct _control_xfer
{
DEVICE_REQUEST DeviceRequest; //USB设备请求结构体,8个字节
unsigned short wLength; //传输数据的总字节数
unsigned short wCount; //传输字节数统计
unsigned char * pData; //传输数据的指针
unsigned char dataBuffer[MAX_CONTROLDATA_SIZE]; //请求的数据
} CONTROL_XFER;
/************************************************************
USB标准设备请求子程序入口地址表
************************************************************/
//USB标准设备请求入口地址指针表
code void (*StandardDeviceRequest[])(void) =
{
get_status,
clear_feature,
reserved,
set_feature,
reserved,
set_address,
get_descriptor,
reserved,
get_configuration,
set_configuration,
get_interface,
set_interface,
reserved,
reserved,
reserved,
reserved
};
#define NUM_ENDPOINTS 4
#define CONFIG_DESCRIPTOR_LENGTH sizeof(USB_CONFIGURATION_DESCRIPTOR) \
+ sizeof(USB_INTERFACE_DESCRIPTOR) \
+ (NUM_ENDPOINTS * sizeof(USB_ENDPOINT_DESCRIPTOR))
extern CONTROL_XFER ControlData;
//extern IO_REQUEST idata ioRequest;
extern EPPFLAGS bEPPflags;
/*
USB 标准请求程序调用到的子程序
*/
//保留子程序
void reserved(void)
{
stall_ep0();
}
void stall_ep0(void)
{
D12_SetEndpointStatus(0, 1);
D12_SetEndpointStatus(1, 1);
}
/*设置端点状态命令:40~45H*/
void D12_SetEndpointStatus(unsigned char bEndp, unsigned char bStalled)
{
if(bEPPflags.bits.in_isr == 0) //USB 中断服务标志
DISABLE;
outportb(D12_COMMAND, 0x40 + bEndp);
outportb(D12_DATA, bStalled);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
}
/*
//*************************************************************************
// USB设备标准请求服务程序
//*************************************************************************
*/
//获取状态
void get_status(void)
{
unsigned char endp, txdat[2];
unsigned char bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
unsigned char c;
if (bRecipient == USB_RECIPIENT_DEVICE) { //返回设备状态
if(bEPPflags.bits.remote_wakeup == 1)
txdat[0] = 3; //支持远程唤醒,自供电
else
txdat[0] = 1;
txdat[1]=0;
single_transmit(txdat, 2); //发送数据
} else if (bRecipient == USB_RECIPIENT_INTERFACE) { //返回接口状态
txdat[0]=0;
txdat[1]=0;
single_transmit(txdat, 2);
} else if (bRecipient == USB_RECIPIENT_ENDPOINT) { //返回端点状态
//#define MAX_ENDPOINTS (unsigned char)0x3
endp = (unsigned char)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
//#define USB_ENDPOINT_DIRECTION_MASK 0x80
if (ControlData.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
c = D12_SelectEndpoint(endp*2 + 1); /* 读取输入端点状态 */
else
c = D12_SelectEndpoint(endp*2); /* 读取输出端点状态 */
if(c & D12_STALL)
txdat[0] = 1; //端点禁止
else
txdat[0] = 0; //端点有效
txdat[1] = 0;
single_transmit(txdat, 2);
} else
stall_ep0(); //非标准请求,发STALL
}
void single_transmit(unsigned char * buf, unsigned char len)
{
if( len <= EP0_PACKET_SIZE) { //#define EP0_PACKET_SIZE 16
D12_WriteEndpoint(1, len, buf);
}
}
/*选择端点命令:00~05H*/
unsigned char D12_SelectEndpoint(unsigned char bEndp)
{
unsigned char c;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND, bEndp);
c = inportb(D12_DATA);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
return c;
}
/*写端点缓冲区同时使缓冲区有效,包含写缓冲区命令:F0H*/
/*以及使缓冲区有效命令:FAH*/
unsigned char D12_WriteEndpoint(unsigned char endp, unsigned char len,unsigned char * buf)
{
unsigned char i;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND, endp);
inportb(D12_DATA);
outportb(D12_COMMAND, 0xF0);
outportb(D12_DATA, 0);
outportb(D12_DATA, len);
for(i=0; i<len; i++)
outportb(D12_DATA, *(buf+i));
outportb(D12_COMMAND, 0xFA);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
return len;
}
//清除特性
void clear_feature(void)
{
unsigned char endp;
//读取请求类型中的接收方
unsigned char bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
if (bRecipient == USB_RECIPIENT_DEVICE
&& ControlData.DeviceRequest.wValue == USB_FEATURE_REMOTE_WAKEUP) {
//清除远程唤醒特性
DISABLE;
bEPPflags.bits.remote_wakeup = 0;
ENABLE;
single_transmit(0, 0); //返回应答
}
else if (bRecipient == USB_RECIPIENT_ENDPOINT
&& ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_STALL) {
//清除端点禁止特性,恢复其使用
endp = (unsigned char)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
if (ControlData.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
/* 清除输入端点STALL特性 */
D12_SetEndpointStatus(endp*2 + 1, 0);
else
/* 清除输出端点STALL特性*/
D12_SetEndpointStatus(endp*2, 0);
single_transmit(0, 0); //发送响应
} else
stall_ep0(); //没有该要求
}
/*设置端点状态命令:40~45H*/
void D12_SetEndpointStatus(unsigned char bEndp, unsigned char bStalled)
{
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND, 0x40 + bEndp);
outportb(D12_DATA, bStalled);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
}
//设置特性
void set_feature(void)
{
unsigned char endp;
//读取请求类型中的接收方
unsigned char bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
if (bRecipient == USB_RECIPIENT_DEVICE
&& ControlData.DeviceRequest.wValue == USB_FEATURE_REMOTE_WAKEUP) {
//设置远程唤醒特性
DISABLE;
bEPPflags.bits.remote_wakeup = 1;
ENABLE;
single_transmit(0, 0); //发送响应
}
else if (bRecipient == USB_RECIPIENT_ENDPOINT
&& ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_STALL) {
endp = (unsigned char)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
if (ControlData.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
/* 设置输入端点禁止 */
D12_SetEndpointStatus(endp*2 + 1, 1);
else
/* 设置输出端点禁止 */
D12_SetEndpointStatus(endp*2, 1);
single_transmit(0, 0);
} else
stall_ep0();
}
//设置地址
void set_address(void)
{
D12_SetAddressEnable((unsigned char)(ControlData.DeviceRequest.wValue &
DEVICE_ADDRESS_MASK), 1);
//#define DEVICE_ADDRESS_MASK 0x7F
single_transmit(0, 0);
}
/*设置/使能地址命令:D0H*/
void D12_SetAddressEnable(unsigned char bAddress, unsigned char bEnable)
{
if(bEPPflags.bits.in_isr == 0)
DISABLE;//EA=0
outportb(D12_COMMAND, 0xD0);
if(bEnable)
bAddress |= 0x80;
outportb(D12_DATA, bAddress);
if(bEPPflags.bits.in_isr == 0)
ENABLE;//EA=1
}
//获取描述符
void get_descriptor(void)
{ //读取请求的描述符类型
//#define MSB(x) (((x) >> 8) & 0xFF)
unsigned char bDescriptor = MSB(ControlData.DeviceRequest.wValue);
if (bDescriptor == USB_DEVICE_DESCRIPTOR_TYPE) {
//获取设备描述符
code_transmit((unsigned char code *)&DeviceDescr, sizeof(USB_DEVICE_DESCRIPTOR));
} else if (bDescriptor == USB_CONFIGURATION_DESCRIPTOR_TYPE) {
//获取配置描述符+配置描述符+接口描述符+端点描述符
code_transmit((unsigned char code *)&ConfigDescr, CONFIG_DESCRIPTOR_LENGTH);
} else
stall_ep0();
}
void code_transmit(unsigned char code * pRomData, unsigned short len)
{
ControlData.wCount = 0;
if(ControlData.wLength > len)
ControlData.wLength = len;
ControlData.pData = pRomData;
if( ControlData.wLength >= EP0_PACKET_SIZE) {
D12_WriteEndpoint(1, EP0_PACKET_SIZE, ControlData.pData);
ControlData.wCount += EP0_PACKET_SIZE;
DISABLE;
bEPPflags.bits.control_state = USB_TRANSMIT;
ENABLE;
}
else {
D12_WriteEndpoint(1, ControlData.wLength, pRomData);
ControlData.wCount += ControlData.wLength;
DISABLE;
bEPPflags.bits.control_state = USB_IDLE;
ENABLE;
}
}
//获取配置
void get_configuration(void)
{
unsigned char c = bEPPflags.bits.configuration;
single_transmit(&c, 1); //返回配置值
}
void single_transmit(unsigned char * buf, unsigned char len)
{
if( len <= EP0_PACKET_SIZE) {
D12_WriteEndpoint(1, len, buf);
}
}
void set_configuration(void)
{
if (ControlData.DeviceRequest.wValue == 0) {
/* 配置值不对,设备进入未配置状态 */
single_transmit(0, 0); //发送响应
DISABLE;
bEPPflags.bits.configuration = 0; //标志未配置
ENABLE;
init_unconfig(); //进入地址状态,禁止0 除外的所有端点
} else if (ControlData.DeviceRequest.wValue == 1) {
/* 配置设备 */
single_transmit(0, 0);
init_unconfig();
init_config(); //配置处理,允许端点收发
DISABLE;
bEPPflags.bits.configuration = 1; //标志已配置
ENABLE;
} else
stall_ep0(); //没有该请求,返回STALL
}
void init_unconfig(void)
{
// unsigned char i;
D12_SetEndpointEnable(0); /* Disable all endpoints but EPP0. */
}
/*设置端点使能命令:D8H*/
void D12_SetEndpointEnable(unsigned char bEnable)
{
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND, 0xD8);
if(bEnable)
outportb(D12_DATA, 1);
else
outportb(D12_DATA, 0);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
}
void init_config(void)
{
D12_SetEndpointEnable(1); /* Enable generic/iso endpoints. */
}
//获取接口信息
void get_interface(void)
{
unsigned char txdat = 0; /* 本设备只有一个接口 */
single_transmit(&txdat, 1);
}
//设置接口
void set_interface(void)
{
if (ControlData.DeviceRequest.wValue == 0 && ControlData.DeviceRequest.wIndex == 0)
single_transmit(0, 0); //发送响应
else
stall_ep0();
}
void IspControl(void)
{
P1=GenEpBuf[0];
}
unsigned char idata GenEpBuf[EP1_PACKET_SIZE]={0,0,0,0};
#define EP1_PACKET_SIZE 4
系统分类:
单片机 | 用户分类:
USB接口技术 | 来源:
原创 | 【推荐给朋友】 | 【添加到收藏夹】