<p>#include <stm32f10x_lib.h> <p>#include <stm32f10x_map.h> <p>#include "usbreg.h" <p>#include "usbuser.h" <p>#include "usbcore.h" <p>#include "usb_hw.h" <p>#define _DEBUG_ <p>#include "debug.h" <p> <p>#define USB_EP_NUM 4 <p> <p>/*端点缓冲区的开始地址 <p> *因为每个缓冲块都需要一个端点描术表 <p> *而所有的端点描述表放在,USB缓冲区的首部 <p> *此地址是相对于USB缓冲区的地址,我认为加上Offset更好些 <p> *这里使用2个端点 <p> *端点0与端点1 <p> *此时EP_BUF_ADDR指向缓冲区的内容 <p> */ <p>#define EP_BUF_ADDR (sizeof(EP_BUF_DSCR)*USB_EP_NUM) <p> <p>/*USB缓冲区首地址包括缓冲区描述表,绝对地址*/ <p>EP_BUF_DSCR * pBUF_DSCR = (EP_BUF_DSCR *) USB_PMA_ADDR; <p> <p>/*端点空闲缓冲区地址 <p> *用于指示目前为止USB缓冲区中还没有分配的空闲地址的首地址*/ <p>WORD FreeBufAddr; <p> <p> <p>/*功能:用于初始化USB的时钟等部分 <p> *参数:无 <p> *返回值:无 <p> */ <p>void USB_Init(void) <p>{ <p> printf("进入USB_Init,进行初始化rn"); <p> //使能USB时钟 <p> RCC->APB1ENR |= (1<<23); <p> <p> //使能USB中断 <p> /*因为USB低优先级中断的中断号为20,而NVIC——IPRX <p> *<a href="https://www.eeworld.com.cn/zhuanti/4KSerL" style="color:#4595e6;" target="_blank">寄存器</a>用四位来存储中断优先级,所以20/4=5 , <p> *然后使能第20位中断*/ <p> NVIC->IPR[5] |=0x10; <p> NVIC->ISER[0]|=(1<<20); <p>} <p>/*功能:用于复位USB模块 <p> *参数:无 <p> *返回值:无 <p> */ <p>/*现在以我的水平还搞不懂双缓冲为何物,所以先不搞^-^*/ <p>/*一些资料: <p> *USB低优先级中断(通道20):可由所有USB事件触发(正确传输,USB复位等). <p> *USB高优先级中断(通道19):仅能由同步和双缓冲批量传输事件触发,目的是保证最大的传输速率. <p> *USB唤醒中断(通道42):由USB挂起模式的唤醒事件触发. <a href="https://www.eeworld.com.cn/zhuanti/fr90OS" style="color:#4595e6;" target="_blank">OTG</a>_FS_WKUP唤醒 <p> * <p> *复位要执行的内容可以参见rm0008 21.4.2节 <p> */ <p>void USB_Reset(void) <p>{ <p> PrintS("USB_Resetrn"); <p> /*复位了嘛,那所有以前产生的中断都没有用了,清了完事!*/ <p> ISTR=0; <p> <p> /*通过设置CNTR来控制stm32的USB模块的工作方式 <p> *所有的USB事件中断都是在低优先级中断(通道20)上处理的 <p> *好吧就先使能这么多吧,先跑起来再说! <p> */ <p> CNTR= CNTR_CTRM | // 使能正确传输中断 <p> CNTR_RESETM | //使能复位中断 <p> CNTR_SUSPM | //使能挂起中断 <p> CNTR_WKUPM ; //使能唤醒中断 <p> <p> FreeBufAddr = EP_BUF_ADDR; //此时FreeBuff指向第一个缓冲区首地址(不包括描述符表),相对地址 <p> <p> BTABLE = 0x00; //设置缓冲区描述表的位置仍是相对地址 <p> <p> /*为端点0设置缓冲区及各种控制位*/ <p> pBUF_DSCR->ADDR_TX = FreeBufAddr; <p> FreeBufAddr+=8; //端点0设置为8个字节,一般控制数据为8个字节 <p> pBUF_DSCR->ADDR_RX = FreeBufAddr; <p> FreeBufAddr+=8; <p> /*在count_Rx字段中10~14bit用来表示缓冲区字节的快数 <p> *而15bit用来表示块的大小 <p> *0---2byte <p> *1---1byte <p> *我们这里使用了8个字节,bit15为0,所以应该((8<<10)>>1)即8<<9; <p> *至于count_Rx我们在发送时再来赋值 <p> */ <p> pBUF_DSCR->COUNT_RX= 8 << 9; <p> /*设置端点0为控制端点,接收缓冲区有效 <p> *低四位代表端点地址 <p> */ <p> EPxREG(0) = EP_CONTROL | EP_RX_VALID; <p> <p> /*使能USB模块,并设置USB地址为0,以响应枚举*/ <p> DADDR = DADDR_EF | 0; <p>} <p> <p>/*功能:复位一个端点 <p> *参数: 端点号 <p> * EPNum:bit3~bit0 ----> 端点号 <p> * EPNum:bit7 ----> 端点方向 <p> * <p> *返回值:无 <p> */ <p> /*其实就是将下一个要发送的数据包变成DATA0*/ <p> void EP_Reset(DWORD EPNum) <p> { <p> DWORD num,var; <p> PrintS("EP_Resetrn"); <p> /*获得端点号,低四位为端点号*/ <p> num = EPNum & 0x0F; <p> var = EPxREG(num); <p> /*如果bit7为1则将此端点的发送toggle置为0, <p> *否则将此端点的接收toggle置为0 <p> *因为数据总是从data0数据包开始发送的 <p> */ <p> if(EPNum & 0x80) <p> EPxREG(num) = var & (EP_MASK | EP_DTOG_TX);/*输入端点*/ <p> else <p> EPxREG(num) = var & (EP_MASK | EP_DTOG_RX);/*输出端点*/ <p> <p> } <p> /*功能:连接或断开USB功能 <p> *参数:true -->连接USB <p> * false-->关闭USB <p> *返回值:无 <p> */ <p>void USB_Connect(BOOL turnon) <p>{ <p> /*需要注意一点的事,所有的USB寄存器尽量用=而不要用与或非 <p> *在编程手册上有明确表明,这样可能会导至出一些问题*/ <p> printf("进入连接USB程序rn"); <p> /*将USB强制复位*/ <p> CNTR = CNTR_FRES; <p>// printf("test1rn"); <p> /*因为刚连接所以应该跟才启动一样,将所有没有处理的中断给清理掉*/ <p> ISTR=0; <p>// printf("test2rn"); <p> if(turnon) <p> { <p>// printf("test3rn"); <p> /*使能GPIOA,然后将PA.8置低,使USB <p> *的D+加1.5K上接电阻,使USB集线器识别了高速设备 <p> *这样才能让USB识别 <p> */ <p> RCC->APB2ENR |= (1 << 2); /* enable clock for GPIOA */ <p> GPIOA->CRH &= ~(0x0f << 0 * 4); /* clear port PA8 */ <p> GPIOA->CRH |= (0x03 << 0 * 4); /* PA6 General purpose output open-drain, max speed 50 MHz */ <p> GPIOA->BRR = ( 1 << 8 ); /* reset PA8 (set to low) */ <p> /*经过调试发现,这个语句的本意是:复位USB模块 <p> *然后在此使能CNTR_RESETM即复位中断标志 <p> *至于端点0的初始化留在USB低优先级中进行处理 <p> *当然,我们也只开了低优先级中断^_^!*/ <p> CNTR = CNTR_RESETM; /*此处只使能了复位中断,*/ <p> } <p> else <p> CNTR = CNTR_FRES | CNTR_PDWN ;/*复位并关闭*/ <p> <p>} <p>/*功能:设置端点状态 <p> *参数:EPnum --->端点号 <p> * stat --->要设置的状态值 <p> *返回值:无 <p> */ <p> void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR * pEPD) <p> { <p> DWORD num,val; <p> <p> //取得端点号 <p> num = pEPD->bEndpointAddress & 0xf; <p> <p> val = pEPD->wMaxPacketSize; <p> //如果是IN端点 <p> if(pEPD->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) <p> { <p> //此处我只想说pBUF_DSCR是指针,剩下的就是语法问题了 <p> (pBUF_DSCR + num)->ADDR_TX = FreeBufAddr; <p> /*取2的倍数,因为缓冲区都是字对齐的,注意此处如果大于1023会出现浪费现象 <p> *因为USB_COUNTn_TX只能接收bit0~bit9 <p> */ <p> val = (val + 1)& ~1; <p> } <p> //输出端点 <p> else <p> { <p> (pBUF_DSCR + num)->ADDR_RX = FreeBufAddr; <p> /*因为USB_COUNTn_RX中存储只用bit10~bit14,如果BLSIZE=0(即块大小为2字节),那么只能是0~62个字节 <p> *所以如果大于62,则应将块大小设置为BLSIZE=1(即32个字节) <p> */ <p> if(val > 62 ) <p> { <p> //块大小为32,则大小应该为32的倍数 <p> val = (val +31)&~31; <p> /*关于此计算公式,参见rm0008,21,5.3节 <p> *(val >> 5)<<10 == val <<5 <p> */ <p> (pBUF_DSCR + num)->COUNT_RX = ((val << 5)-1) | 0x8000; <p> } <p> else <p> { <p> val = (val + 1) & ~1; <p> (pBUF_DSCR + num)->COUNT_RX = val << 9; <p> } <p> }
讯享网

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/170770.html