




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、STM32-USB使用方法开发板买的是奋斗mini开发板,芯片是:STM32F103VET6. 如果需要源程序keil4-arm工程,上位机vb。加qq339396264要程序。USB开发涉及主机和设备,为了避免开发驱动程序,使用Windows自带的驱动程序。所以设备枚举成HID类设备。USB鼠标就是标准的USB-HID设备。不过操作系统阻止了应用程序直接访问USB鼠标返回的报告。所以本例使用自定义HID设备。一来免去了开发驱动程序,二来自定义的HID设备应用程序和设备可以自由收发数据(仅指数据内容)。本文主要介绍STM32的USB模块的简单使用,不会介绍USB协议。主要是介绍一下STM32F
2、103的USB模块使用。USB模块从初始化首先是配置和使能时钟下面是时钟的初始化:void Set_USBClock(void)/RCC_USBCLKSource_PLLCLK_1Div5表示【USB时钟 = PLL时钟除以1.5】【72/1.5=48MHz】 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);/【使能配置好了的USB时钟】 首先系统时钟要设置为72MHz,然后配置USB时钟为48MHz并使能。然后是配置中断void USB_Int
3、errupts_Config(void)#define USB_LP_CAN1_RX0_IRQn 20NVIC_InitTypeDef NVIC_InitStructure; /【使能USB中断】NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; /【USB低优先级中断】NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC
4、_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure); 然后初始化模块的一些寄存器USART_send_str(USB断开rn);USB_DISCONNECT/这是断开1.5k上拉电阻delay(0x7AFFFF);/延时一会USB_CONNECT/使能1.5K上拉电阻USART_send_str(USB连接rn);DADDR = 0x0080;/USB模块使能位。EF必须置1CNTR = 0x0001;/强制复位CNTR = 0x0000;/退出复位ISTR = 0x0000;/清除可能产生的假中断CNTR = (I_CTR | I_R
5、ESET);/使能一些中断,为了简单这里只使能了【总线复位中断】和【数据正确传输中断】ISTR = 0x0000;/清除可能产生的假中断自此USB模块初始化完毕。以后的流程就在USB中断的驱动下执行。USB中断函数:void USB_LP_CAN1_RX0_IRQHandler(void)u16 wIstr;/USB中断状态寄存器wIstr = (u16)ISTR;/【USB复位中断】 if(wIstr &I_RESET) USB_RST_Process();return;/【正确传输中断】if (wIstr & I_CTR) USB_CTR_Process();return;在USB中断函数
6、中就是判断中断源,并转向相应的中断服务函数。USB总线复位后,USB相关的一些寄存器会复位。在USB总线复位中要配置一下寄存器和数据收发的缓冲区。程序如下void USB_RST_Process(void)/清除中断ISTR = (u16)(I_RESET);/清除ISTR寄存器中断RESET位。写0清除,写1寄存器位内容不变。/USART_send_str(【USB】【复】【位】【中】【断】rn);usb_status = 0;/复位处理DADDR = 0x0080; /USB模块使能位。EF必须置1BTABLE = 0; /复位后默认为0EP0REG = (u16)(0x0220); /0
7、000 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接收缓冲区大小:64ByteUSB_CNT0_RX = 0x8400;/1000,0100,0000,0000/【端点1】EP1REG = (u16)(0x0621);/0000 0110 0010 0001 端点0初始化:中断端点,NAK主机的IN令牌,端点号1/设置TX/
8、RX起始地址USB_ADDR1_TX = 160;/160-223 端点1的发送缓冲区从160开始到223,共64字节USB_ADDR1_RX = 224;/224-287 端点1的接收缓冲区从224开始到287,共64字节/设置端点1接收缓冲区大小:64ByteUSB_CNT1_RX = 0x8400;/1000,0100,0000,0000/设置RX Valid .端点0可用于接收u16 t = EP0REG;/读出端点0寄存器值t &= 0x8F8F;/1000 1111 1000 1111 由于t位写0不影响原来的值,写1翻转,所以把 t位都设置为0t |= 0x8080;/1000
9、0000 1000 0000 由于w0位写0清除,写1无影响,所以w0位都设置为1t |= 0x3000;/0011 0000 0000 0000 把 SRAT_RX1:0设置为1,通过写1翻转来实现。EP0REG = t;下面是正确传输中断/USB分组正确传输处理void USB_CTR_Process(void)/*【端点0】*/if(ISTR & 0x0F) = 0)/端点0if(ISTR & 0x10) = 0)/in分组 /USART_send_str(*端点0的IN分组发送完成*rn);if(usb_status = 1)usb_status = 2;DADDR = 0x80 |
10、(usb_addr&0xFF);/设置地址一定要找控制传输的状态完成后写入地址寄存器/USART_send_str(rn【写入地址完成】rn);/发送剩余数据USB_ep0_send();/清除CTR_TXu16 t = EP0REG;t &= 0x8F8F;/1000 1111 1000 1111 把 t位都设置为0t |= 0x8080;/1000 0000 1000 0000 把w0位都设置为1t &= 0xFF7F;/1111 1111 0111 1111 把CTR_TX设置为0,清除CTR_RX位EP0REG = t;if(ISTR & 0x10)/【OUT】分组 or 【SETUP
11、】分组u16 ep0r= EP0REG;/清除CTR_RXu16 t = EP0REG;t &= 0x8F8F;/1000 1111 1000 1111 把 t位都设置为0t |= 0x8080;/1000 0000 1000 0000 把w0位都设置为1t &= 0x7FFF;/0111 1111 1111 1111 把CTR_RX设置为0,清除CTR_RX位EP0REG = t;if(ep0r & 0x0800)/SETUP令牌包/USART_send_str(端点0收到【SETUP】分组rn);/默认控制端点处理枚举处理ep0_setup_Process();memset(USB_rcv
12、_buffer, 0x00, sizeof(USB_rcv_buffer);USB_enable_ep0_rx();else/USART_send_str(控制读传输:状态阶段rn);USB_read_EP0_buf(USB_rcv_buffer, (u32*)(PMAAddr+96*2); USB_enable_ep0_rx();/else/【IN分组传输成功】/*【端点1】*/else if(ISTR & 0x0F) = 1)USART_send_str(端点1数据完成传输rn);if(ISTR & 0x10)/【OUT分组】/清除CTR_RXu16 t = EP1REG;t &= 0x8
13、F8F;/1000 1111 1000 1111 把 t位都设置为0t |= 0x8080;/1000 0000 1000 0000 把w0位都设置为1t &= 0x7FFF;/0111 1111 1111 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_TXu16 t = EP1REG;t &= 0x8F8F
14、;/1000 1111 1000 1111 把 t位都设置为0t |= 0x8080;/1000 0000 1000 0000 把w0位都设置为1t &= 0xFF7F;/1111 1111 0111 1111 把CTR_TX设置为0,清除CTR_RX位EP1REG = t;/标记发送完成/*【端点ERR】*/elseUSART_send_str(出错!端点号是没有开启对端点。rn);其他代码:/设置RX Valid .使端点继续接收void USB_enable_ep0_rx(void)u16 t = EP0REG;/USART_send_str(EP0REG = );USART_send_
15、HEX(t8);USART_send_HEX(t&0xff);USART_send_str(rn);t &= 0x8F8F;/1000 1111 1000 1111 把 t位都设置为0t |= 0x8080;/1000 0000 1000 0000 把w0位都设置为1switch(EP0REG & 0x3000)case 0x0000: t |= 0x3000;break;case 0x1000: t |= 0x2000;break;case 0x2000: t |= 0x1000;break;case 0x3000: t |= 0x0000;break;EP0REG = t;/t = EP0
16、REG;/USART_send_str(EP0REG = );USART_send_HEX(t8);USART_send_HEX(t&0xff);USART_send_str(rn);/设置RX Valid .使端点继续接收void USB_enable_ep1_rx(void)u16 t = EP1REG;t &= 0x8F8F;/1000 1111 1000 1111 把 t位都设置为0t |= 0x8080;/1000 0000 1000 0000 把w0位都设置为1switch(EP1REG & 0x3000)case 0x0000: t |= 0x3000;break;case 0x
17、1000: t |= 0x2000;break;case 0x2000: t |= 0x1000;break;case 0x3000: t |= 0x0000;break;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 & 0x03FF;/unsigned char s32 = 0;/sprintf(char*)s, 端点0读取【%d】字节数据:, rcv_num)
18、;/USART_send_str(s);/USART_send_str(rn-rn);/读取次数read_cnt = (rcv_num+1)1;for(i=0;i 8;/for(i=0;i1;for(i=0;i 8;for(i=0;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_cnt;u8 i;u8 j = 0;
19、u16 h,l;/unsigned char s32 = 0;/sprintf(char*)s, 端点0发送【%d】字节数据:, len);/USART_send_str(s);/USART_send_str(rn+rn);/for(i=0;i 1;for(i=0;isend_cnt;i+)l = bufj+;h = bufj+8; *USB_buf = (h|l);USB_buf+;/要发送数据的长度USB_CNT0_TX= len;/使能发送:设置VALIDu16 t = EP0REG;t &= 0x8F8F;/1000 1111 1000 1111 把 t位都设置为0t |= 0x808
20、0;/1000 0000 1000 0000 把w0位都设置为1switch(EP0REG & 0x0030)case 0x0000: t |= 0x0030;break;case 0x0010: t |= 0x0020;break;case 0x0020: t |= 0x0010;break;case 0x0030: t |= 0x0000;break;EP0REG = t;/通过端点1发送数据void USB_write_EP1_buf(u8 *buf, u32 *USB_buf, u8 len)u8 send_cnt;u8 i;u8 j = 0;u16 h,l;unsigned char
21、 s32 = 0;sprintf(char*)s, 端点1发送【%d】字节数据:, len);USART_send_str(s);USART_send_str(rn+rn);for(i=0;i 1;for(i=0;isend_cnt;i+)l = bufj+;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/需要发送的数据长度小于等于端点0的最
22、大包长if(send_len_ep0 != 0)/一次能够发送完成USB_write_EP0_buf(p_send_ep0, (u32*)(PMAAddr+32*2), send_len_ep0);send_len_ep0 = 0;else/等于0if(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_buffer,
23、 (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) & 0x03)/请求的类型case 0:/标准请求.省略了对“请求的接收者”的判断/USART_send_str(USB标准输入请求:);switch(req)/标准请求代码case 0:/获取状态/USART
24、_send_str(获取状态rn);break;case 6:/获取描述符/USART_send_str(获取描述符);switch(w_value8) & 0xFF)/描述符类型case 1:/设备描述符/USART_send_str(设备描述符rn);p_send_ep0 = (u8*)dev_d;/设备描述符数组if(w_length dev_d0)/如果请求的数据大于描述符长度,返回描述符长度最大长度send_len_ep0 = dev_d0;/18if(send_len_ep0 % dev_d7) = 0)need_0_pack_ep0 = 1;/是包长的整数倍,需要发送0长度数据包
25、else/请求长度小于等于描述符长度,则返回请求长度 send_len_ep0 = w_length;USB_ep0_send();break;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
26、_ep0 = w_length;USB_ep0_send();break;case 3:/字符串描述符/USART_send_str(字符串描述符rn);break;case 0x22:/报告描述符/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长度数据包elsesend_len_ep
27、0 = w_length;/返回长度等于请求长度USB_ep0_send();break;default:/其他描述符/USART_send_str(其他描述符:);/USART_send_HEX(w_value8)&0xFF);/USART_send_str(rn);break;break;case 8:/获取配置/USART_send_str(获取配置rn);break;case 10:/获取接口/USART_send_str(获取接口rn);break;case 12:/帧同步/USART_send_str(帧同步rn);break;default:/USART_send_str(USB
28、未定义输入请求rn);break;break;case 1:/类请求/USART_send_str(USB类输入请求rn);break;case 2:/厂商请求/USART_send_str(厂商输入请求rn);break;case 3:/保留/USART_send_str(USB输入请求:保留rn);break;else/*输出请求*/switch(req_type5) & 0x03)/请求的类型case 0:/标准请求.省略了对“请求的接收者”的判断/USART_send_str(USB标准输出请求:);switch(req)/标准请求代码【GET】case 1:/清除特性/USART_s
29、end_str(清除特性rn);send_len_ep0 = 0;need_0_pack_ep0 = 1;USB_ep0_send();/发送数据break;case 5:/设置地址USART_send_str(设置地址rn);/USART_send_HEX(w_value&0xFF);/USART_send_str(rn);usb_status = 1;/表示主机设置了地址usb_addr = w_value & 0xFF;send_len_ep0 = 0;need_0_pack_ep0 = 1;USB_ep0_send();/发送数据break;case 9:/设置配置USART_send
30、_str(设置配置rn);/设置RX Valid .【端点1】可用于接收u16 t = EP1REG;t &= 0x8F8F;/1000 1111 1000 1111 把 t位都设置为0t |= 0x8080;/1000 0000 1000 0000 把w0位都设置为1t |= 0x3000;/0011 0000 0000 0000 把 SRAT_RX1:0设置为1EP1REG = t;send_len_ep0 = 0;need_0_pack_ep0 = 1;USB_ep0_send();/发送剩余数据usb_status = 3;break;case 7:/设置描述符/USART_send_
31、str(设置描述符rn);break;case 3:/设置特性/USART_send_str(设置特性rn);break;case 11:/设置接口/USART_send_str(设置接口rn);break;default:/出错/USART_send_str(标准输出请求代码出错rn);break;break;case 1:/类请求/USART_send_str(USB类输出请求:);switch(req)case 0x0A:USART_send_str(设置空闲rn);send_len_ep0 = 0;need_0_pack_ep0 = 1;USB_ep0_send();/发送剩余数据br
32、eak;default:#ifdef HEEY_DEBUG/UART_send_str(未知请求rn);#endifbreak;break;case 2:/厂商请求/USART_send_str(厂商输出请求rn);break;case 3:/保留/USART_send_str(输出请求:保留rn);break;/描述符的话用数组实现的这里就不给出来。源程序的kile 4 - arm写的,可以向我要。奋斗STM32迷你板应该下载后可以直接使用。上位机软件使用vb。一下是枚举过程USB断开USB连接【U】【S】【B】【复】【位】【中】【断】【U】【S】【B】【复】【位】【中】【断】端点0【SETUP】分组接收完成端点0读取【8】字节数据:-0x80 0x06 0x00 0x01 0x00 0x00 0x40 0x00 -USB标准输入请求:获取描述符设备描述符端点0发送【18】字节数据:+0x12 0x01 0x10 0x01 0x00 0x00 0x00 0x40 0xAA 0
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 邯郸市人民医院骨盆骨折急救与确定性治疗考核
- 2025河南周口市西华县人民医院校园招聘33人考前自测高频考点模拟试题附答案详解(突破训练)
- 秦皇岛市中医院结石定位准确性考核
- 大学课件标准
- 2025中心医院支气管动脉栓塞考核
- 2025湖北华中科技大学同济医学院附属协和医院耳鼻咽喉头颈外科孙宇教授团队专职研究人员招聘模拟试卷及完整答案详解一套
- 张家口市中医院物资采购评估考核
- 2025中心医院血小板抗体检测与配型技术专项考核
- 邢台市人民医院细胞毒药物配置考核
- 衡水市中医院宫腔镜检查术操作资格分级认证
- 坚持人民至上 工会研讨发言
- 杭州师范大学2013年841无机化学考研真题
- 美学原理全套教学课件
- 期末复习(课件)新思维英语四年级上册
- 子宫脱垂试题及答案
- 中国政治思想史复习资料
- 高中音乐鉴赏 第一单元 学会聆听 第一节《音乐要素及音乐语言》
- 《中国民间故事》阅读指导课
- 20以内加减法口算题3500道直接打印
- 走好群众路线-做好群众工作(黄相怀)课件
- 北斗卫星导航系统(全套课件208P)
评论
0/150
提交评论