1、EF必须置 1 CNTR=0 x0001;/强制复位 CNTR=0 x0000;/退出复位 ISTR=0 x0000;/清除可能产生的假中断 CNTR=(I_CTR|I_RESET);/使能一些中断,为了简单这里只使能了【总线复位中断】和【数据正确传输中断】ISTR=0 x0000;/清除可能产生的假中断 自此 USB模块初始化完毕。以后的流程就在 USB 中断的驱动下执行。USB中断函数:void USB_LP_CAN1_RX0_IRQHandler(void)u16 wIstr;/USB中断状态寄存器 wIstr=(u16)ISTR;/【USB复位中断】if(wIstr&I_RESET)U
2、SB_RST_Process();return;/【正确传输中断】if(wIstr&I_CTR)USB_CTR_Process();在 USB中断函数中就是判断中断源,并转向相应的中断服务函数。USB总线复位后,USB相关的一些寄存器会复位。在 USB总线复位中要配置一下寄存器和数据收发的缓冲区。程序如下 void USB_RST_Process(void)/清除中断 ISTR=(u16)(I_RESET);/清除 ISTR 寄存器中断 RESET 位。写 0清除,写 1寄存器位内容不变。/USART_send_str(【USB】【复】【位】【中】【断】rn);usb_status=0;/复位
3、处理 DADDR=0 x0080;EF必须置 1 BTABLE=0;/复位后默认为 0 EP0REG=(u16)(0 x0220);/0000 0010 0010 0000 端点 0初始化:控制端点,NAK主机的 IN令牌,端点号 0 /设置 TX/RX起始地址 USB_ADDR0_TX=32;/32-95 端点 0 的发送缓冲区从 32开始到 95,共 64字节 USB_ADDR0_RX=96;/96-159 端点 0 的接收缓冲区从 96开始到 159,共 64字节 /设置端点 0接收缓冲区大小:64Byte USB_CNT0_RX=0 x8400;/1000,0100,0000,0000
4、 /【端点 1】EP1REG=(u16)(0 x0621);/0000 0110 0010 0001 端点 0初始化:中断端点,NAK主机的 IN令牌,端点号 1 /设置 TX/RX起始地址 USB_ADDR1_TX=160;/160-223 端点 1的发送缓冲区从 160开始到 223,共 64字节 USB_ADDR1_RX=224;/224-287 端点 1 的接收缓冲区从 224开始到 287,共 64字节 /设置端点 1接收缓冲区大小:64Byte USB_CNT1_RX=0 x8400;/1000,0100,0000,0000 /设置 RX Valid.端点 0 可用于接收 u16
5、t=EP0REG;/读出端点 0寄存器值 t&=0 x8F8F;/1000 1111 1000 1111 由于 t 位写 0不影响原来的值,写 1 翻转,所以把 t 位都设置为 0 t|=0 x8080;/1000 0000 1000 0000 由于 w0 位写 0清除,写 1 无影响,所以 w0位都设置为 1 t|=0 x3000;/0011 0000 0000 0000 把 SRAT_RX1:0设置为 1,通过写 1翻转来实现。EP0REG=t;下面是正确传输中断/USB分组正确传输处理 void USB_CTR_Process(void)/*【端点 0】*/if(ISTR&0 x0F)=
6、0)/端点 0 if(ISTR&0 x10)=0)/in 分组 /USART_send_str(*端点 0的 IN分组发送完成*rn);if(usb_status=1)usb_status=2;DADDR=0 x80|(usb_addr&0 xFF);/设置地址一定要找控制传输的状态完成后写入地址寄存器/USART_send_str(rn【写入地址完成】rn);/发送剩余数据 USB_ep0_send();/清除 CTR_TX u16 t=EP0REG;t&/1000 1111 1000 1111 把 t 位都设置为 0 t|=0 x8080;/1000 0000 1000 0000 把 w0
7、位都设置为 1 t&=0 xFF7F;/1111 1111 0111 1111 把 CTR_TX 设置为 0,清除 CTR_RX 位 EP0REG=t;if(ISTR&0 x10)/【OUT】分组 or【SETUP】分组 u16 ep0r=EP0REG;/清除 CTR_RX u16 t=EP0REG;=0 x7FFF;/0111 1111 1111 1111 把 CTR_RX 设置为 0,清除 CTR_RX 位 EP0REG=t;if(ep0r&0 x0800)/SETUP 令牌包 /USART_send_str(端点 0收到【SETUP】分组rn);/默认控制端点处理枚举处理 ep0_set
8、up_Process();memset(USB_rcv_buffer,0 x00,sizeof(USB_rcv_buffer);USB_enable_ep0_rx();else /USART_send_str(控制读传输:状态阶段rn);USB_read_EP0_buf(USB_rcv_buffer,(u32*)(PMAAddr+96*2);/else/【IN分组传输成功】/*【端点 1】*/else if(ISTR&0 x0F)=1)USART_send_str(端点 1 数据完成传输rn);0 x10)/【OUT分组】/清除 CTR_RX u16 t=EP1REG;/0111 1111 1
9、111 1111 把 CTR_RX 设置为 0,清除 CTR_RX位 EP1REG=t;USB_read_EP1_buf(USB_rcv_buffer,(u32*)(PMAAddr+224*2);/【读 取】端点 1数据 /【处 理】端点 1 数据 USB_enable_ep1_rx();/【继续接受】端点 1数据 else/【IN分组】/清除 CTR_TX u16 t=EP1REG;/1111 1111 0111 1111 把 CTR_TX 设置为 0,清除 CTR_RX 位 EP1REG=t;/标记发送完成 /*【端点 ERR】*/else USART_send_str(出错!端点号是没有
10、开启对端点。rn);其他代码:/设置 RX Valid.使端点继续接收 void USB_enable_ep0_rx(void)u16 t=EP0REG;/USART_send_str(EP0REG=);USART_send_HEX(t8);USART_send_HEX(t&0 xff);USART_send_str(rn);/1000 0000 1000 0000 把 w0位都设置为 1 switch(EP0REG&0 x3000)case 0 x0000:t|=0 x3000;break;case 0 x1000:t|=0 x2000;case 0 x2000:t|=0 x1000;cas
11、e 0 x3000:t|=0 x0000;/t=EP0REG;/设置 RX Valid.使端点继续接收 void USB_enable_ep1_rx(void)u16 t=EP1REG;/1000 0000 1000 0000 把 w0位都设置为 1 switch(EP1REG&EP1REG=t;/读取端点 0收到的数据 u8 USB_read_EP0_buf(u8*buf,u32*USB_buf)u16 rcv_num;u8 read_cnt;u8 i;u16 temp;u8 j=0;/接收到的数据 rcv_num=USB_CNT0_RX&0 x03FF;/unsigned char s32
12、=0;/sprintf(char*)s,端点 0读取【%d】字节数据:,rcv_num);/USART_send_str(s);/USART_send_str(rn-rn);/读取次数 read_cnt=(rcv_num+1)1;for(i=0;i 8;/for(i=0;i1;ij;i+)USART_send_HEX(bufi);if(i+1)%16=0)USART_send_str(rn);USART_send_str(rn-rnrn);return(j);/通过端点 0发送数据 void USB_write_EP0_buf(u8*buf,u32*USB_buf,u8 len)u8 send
13、_cnt;u16 h,l;/sprintf(char*)s,端点 0发送【%d】字节数据:,len);/USART_send_str(rn+rn);i 1;isend_cnt;i+)l=bufj+;h=bufj+8;*USB_buf=(h|l);USB_buf+;/要发送数据的长度 USB_CNT0_TX=len;/使能发送:设置 VALID u16 t=EP0REG;0 x0030)case 0 x0000:t|=0 x0030;case 0 x0010:t|=0 x0020;case 0 x0020:t|=0 x0010;case 0 x0030:/通过端点 1发送数据 void USB_
14、write_EP1_buf(u8*buf,u32*USB_buf,u8 len)u8 send_cnt;unsigned char s32=0;sprintf(char*)s,端点 1发送【%d】字节数据:USART_send_str(s);USART_send_str(rn+rn);h=bufj+dev_d7)/如果需要发送数据长度大于端点 0 的最大长度:分包发送 USB_write_EP0_buf(p_send_ep0,(u32*)(PMAAddr+32*2),dev_d7);send_len_ep0-=dev_d7;p_send_ep0+=dev_d7;else/需要发送的数据长度小于
15、等于端点 0的最大包长 if(send_len_ep0!=0)/一次能够发送完成 USB_write_EP0_buf(p_send_ep0,(u32*)(PMAAddr+32*2),send_len_ep0);send_len_ep0=0;else/等于 0 if(need_0_pack_ep0=1)need_0_pack_ep0=0;USB_write_EP0_buf(p_send_ep0,(u32*)(PMAAddr+32*2),0);/端点 0枚举过程处理 void ep0_setup_Process(void)/读取接收到的数据 USB_read_EP0_buf(USB_rcv_buf
16、fer,(u32*)(PMAAddr+96*2);req_type=USB_rcv_buffer0;req=USB_rcv_buffer1;w_value=(USB_rcv_buffer38)|USB_rcv_buffer2;w_index=(USB_rcv_buffer58)|USB_rcv_buffer4;w_length=(USB_rcv_buffer75)&0 x03)/请求的类型 case 0:/标准请求.省略了对“请求的接收者”的判断 /USART_send_str(USB 标准输入请求:);switch(req)/标准请求代码 case 0:/获取状态 /USART_send_s
17、tr(获取状态rn);case 6:/获取描述符 /USART_send_str(获取描述符);switch(w_value8)&0 xFF)/描述符类型 case 1:/设备描述符 /USART_send_str(设备描述符rn);p_send_ep0=(u8*)dev_d;/设备描述符数组 if(w_length dev_d0)/如果请求的数据大于描述符长度,返回描述符长度最大长度 send_len_ep0=dev_d0;/18 if(send_len_ep0%dev_d7)=0)need_0_pack_ep0=1;/是包长的整数倍,需要发送 0长度数据包 else/请求长度小于等于描述符
18、长度,则返回请求长度 send_len_ep0=w_length;USB_ep0_send();case 2:/配置描述符 /USART_send_str(配置描述符rn);p_send_ep0=(u8*)cfg_d;/设备描述符数组 send_len_ep0=(cfg_d3 send_len_ep0)/如果请求的数据大于端点 0,返回端点 0最大长度 if(send_len_ep0%dev_d7)=0)need_0_pack_ep0=1;/是包长的整数倍,需要发送 0长度数据包 else/请求小于等于端点 0,返回请求长度 send_len_ep0=w_length;case 3:/字符串描
19、述符 /USART_send_str(字符串描述符rn);case 0 x22:/报告描述符 /USART_send_str(报告描述符rn);p_send_ep0=(u8*)rpt_d;send_len_ep0=sizeof(rpt_d);if(w_length send_len_ep0)/如果请求的长度大于实际长度 if(send_len_ep0%dev_d7)=0)need_0_pack_ep0=1;/是包长的整数倍,需要发送 0长度数据包 else send_len_ep0=w_length;/返回长度等于请求长度 USB_ep0_send();default:/其他描述符 /USAR
20、T_send_str(其他描述符:/USART_send_HEX(w_value8)&/USART_send_str(rn);case 8:/获取配置 /USART_send_str(获取配置rn);case 10:/获取接口 /USART_send_str(获取接口rn);case 12:/帧同步 /USART_send_str(帧同步rn);/USART_send_str(USB未定义输入请求rn);case 1:/类请求 /USART_send_str(USB 类输入请求rn);/厂商请求 /USART_send_str(厂商输入请求rn);/保留 /USART_send_str(USB
21、 输入请求:保留rn);else/*输出请求*/switch(req_type5)&/标准请求.省略了对“请求的接收者”的判断 /USART_send_str(USB 标准输出请求:switch(req)/标准请求代码【GET】case 1:/清除特性 /USART_send_str(清除特性rn);need_0_pack_ep0=1;/发送数据 break;case 5:/设置地址 USART_send_str(设置地址rn);/USART_send_HEX(w_value&usb_status=1;/表示主机设置了地址 usb_addr=w_value&0 xFF;case 9:/设置配置
22、 USART_send_str(设置配置rn);/设置 RX Valid.【端点 1】可用于接收 u16 t=EP1REG;/1000 0000 1000 0000 把 w0 位都设置为 1 t|=0 x3000;0设置为 1 EP1REG=t;/发送剩余数据 usb_status=3;case 7:/设置描述符 /USART_send_str(设置描述符rn);/设置特性 /USART_send_str(设置特性rn);case 11:/设置接口 /USART_send_str(设置接口rn);/出错 /USART_send_str(标准输出请求代码出错rn);/类请求 /USART_sen
23、d_str(USB 类输出请求:switch(req)case 0 x0A:USART_send_str(设置空闲rn);/发送剩余数据 break;#ifdef HEEY_DEBUG /UART_send_str(未知请求rn);#endif break;/厂商请求 /USART_send_str(厂商输出请求rn);/保留 /USART_send_str(输出请求:/描述符的话用数组实现的这里就不给出来。源程序的 kile 4-arm 写的,可以向我要。奋斗 STM32 迷你板应该下载后可以直接使用。上位机软件使用 vb。一下是枚举过程 USB断开 USB连接【U】【S】【B】【复】【位】
24、【中】【断】【U】【S】【B】【复】【位】【中】【断】端点 0【SETUP】分组接收完成 端点 0读取【8】字节数据:-0 x80 0 x06 0 x00 0 x01 0 x00 0 x00 0 x40 0 x00 -USB标准输入请求:获取描述符设备描述符 端点 0发送【18】字节数据:+0 x12 0 x01 0 x10 0 x01 0 x00 0 x00 0 x00 0 x40 0 xAA 0 xAA 0 x02 0 x00 0 x00 0 x01 0 x00 0 x00 0 x00 0 x01 +0 x62 0 x60 tx=2 tx2=3 rx=2 rx2=3*端点 0的 IN分组发送完成*rx=0 rx2=0 端点 0的【OUT】分组接收完成 端点 0读取【0】字节数据:-rx=0 rx2=0【U】【S】【B】【复】【位】【中】【断】端点 0【