历史上的今天
今天是:2024年11月05日(星期二)
2020年11月05日 | 关于stm32的USB学习笔记之USB_HW.c
2020-11-05 来源:eefocus
#include #include #include "usbreg.h" #include "usbuser.h" #include "usbcore.h" #include "usb_hw.h" #define _DEBUG_ #include "debug.h" #define USB_EP_NUM 4 /*端点缓冲区的开始地址 *因为每个缓冲块都需要一个端点描术表 *而所有的端点描述表放在,USB缓冲区的首部 *此地址是相对于USB缓冲区的地址,我认为加上Offset更好些 *这里使用2个端点 *端点0与端点1 *此时EP_BUF_ADDR指向缓冲区的内容 */ #define EP_BUF_ADDR (sizeof(EP_BUF_DSCR)*USB_EP_NUM) /*USB缓冲区首地址包括缓冲区描述表,绝对地址*/ EP_BUF_DSCR * pBUF_DSCR = (EP_BUF_DSCR *) USB_PMA_ADDR; /*端点空闲缓冲区地址 *用于指示目前为止USB缓冲区中还没有分配的空闲地址的首地址*/ WORD FreeBufAddr; /*功能:用于初始化USB的时钟等部分 *参数:无 *返回值:无 */ void USB_Init(void) { printf("进入USB_Init,进行初始化rn"); //使能USB时钟 RCC->APB1ENR |= (1<<23); //使能USB中断 /*因为USB低优先级中断的中断号为20,而NVIC——IPRX *寄存器用四位来存储中断优先级,所以20/4=5 , *然后使能第20位中断*/ NVIC->IPR[5] |=0x10; NVIC->ISER[0]|=(1<<20); } /*功能:用于复位USB模块 *参数:无 *返回值:无 */ /*现在以我的水平还搞不懂双缓冲为何物,所以先不搞^-^*/ /*一些资料: *USB低优先级中断(通道20):可由所有USB事件触发(正确传输,USB复位等). *USB高优先级中断(通道19):仅能由同步和双缓冲批量传输事件触发,目的是保证最大的传输速率. *USB唤醒中断(通道42):由USB挂起模式的唤醒事件触发. OTG_FS_WKUP唤醒 * *复位要执行的内容可以参见rm0008 21.4.2节 */ void USB_Reset(void) { PrintS("USB_Resetrn"); /*复位了嘛,那所有以前产生的中断都没有用了,清了完事!*/ ISTR=0; /*通过设置CNTR来控制stm32的USB模块的工作方式 *所有的USB事件中断都是在低优先级中断(通道20)上处理的 *好吧就先使能这么多吧,先跑起来再说! */ CNTR= CNTR_CTRM | // 使能正确传输中断 CNTR_RESETM | //使能复位中断 CNTR_SUSPM | //使能挂起中断 CNTR_WKUPM ; //使能唤醒中断 FreeBufAddr = EP_BUF_ADDR; //此时FreeBuff指向第一个缓冲区首地址(不包括描述符表),相对地址 BTABLE = 0x00; //设置缓冲区描述表的位置仍是相对地址 /*为端点0设置缓冲区及各种控制位*/ pBUF_DSCR->ADDR_TX = FreeBufAddr; FreeBufAddr+=8; //端点0设置为8个字节,一般控制数据为8个字节 pBUF_DSCR->ADDR_RX = FreeBufAddr; FreeBufAddr+=8; /*在count_Rx字段中10~14bit用来表示缓冲区字节的快数 *而15bit用来表示块的大小 *0---2byte *1---1byte *我们这里使用了8个字节,bit15为0,所以应该((8<<10)>>1)即8<<9; *至于count_Rx我们在发送时再来赋值 */ pBUF_DSCR->COUNT_RX= 8 << 9; /*设置端点0为控制端点,接收缓冲区有效 *低四位代表端点地址 */ EPxREG(0) = EP_CONTROL | EP_RX_VALID; /*使能USB模块,并设置USB地址为0,以响应枚举*/ DADDR = DADDR_EF | 0; } /*功能:复位一个端点 *参数: 端点号 * EPNum:bit3~bit0 ----> 端点号 * EPNum:bit7 ----> 端点方向 * *返回值:无 */ /*其实就是将下一个要发送的数据包变成DATA0*/ void EP_Reset(DWORD EPNum) { DWORD num,var; PrintS("EP_Resetrn"); /*获得端点号,低四位为端点号*/ num = EPNum & 0x0F; var = EPxREG(num); /*如果bit7为1则将此端点的发送toggle置为0, *否则将此端点的接收toggle置为0 *因为数据总是从data0数据包开始发送的 */ if(EPNum & 0x80) EPxREG(num) = var & (EP_MASK | EP_DTOG_TX);/*输入端点*/ else EPxREG(num) = var & (EP_MASK | EP_DTOG_RX);/*输出端点*/ } /*功能:连接或断开USB功能 *参数:true -->连接USB * false-->关闭USB *返回值:无 */ void USB_Connect(BOOL turnon) { /*需要注意一点的事,所有的USB寄存器尽量用=而不要用与或非 *在编程手册上有明确表明,这样可能会导至出一些问题*/ printf("进入连接USB程序rn"); /*将USB强制复位*/ CNTR = CNTR_FRES; // printf("test1rn"); /*因为刚连接所以应该跟才启动一样,将所有没有处理的中断给清理掉*/ ISTR=0; // printf("test2rn"); if(turnon) { // printf("test3rn"); /*使能GPIOA,然后将PA.8置低,使USB *的D+加1.5K上接电阻,使USB集线器识别了高速设备 *这样才能让USB识别 */ RCC->APB2ENR |= (1 << 2); /* enable clock for GPIOA */ GPIOA->CRH &= ~(0x0f << 0 * 4); /* clear port PA8 */ GPIOA->CRH |= (0x03 << 0 * 4); /* PA6 General purpose output open-drain, max speed 50 MHz */ GPIOA->BRR = ( 1 << 8 ); /* reset PA8 (set to low) */ /*经过调试发现,这个语句的本意是:复位USB模块 *然后在此使能CNTR_RESETM即复位中断标志 *至于端点0的初始化留在USB低优先级中进行处理 *当然,我们也只开了低优先级中断^_^!*/ CNTR = CNTR_RESETM; /*此处只使能了复位中断,*/ } else CNTR = CNTR_FRES | CNTR_PDWN ;/*复位并关闭*/ } /*功能:设置端点状态 *参数:EPnum --->端点号 * stat --->要设置的状态值 *返回值:无 */ void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR * pEPD) { DWORD num,val; //取得端点号 num = pEPD->bEndpointAddress & 0xf; val = pEPD->wMaxPacketSize; //如果是IN端点 if(pEPD->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) { //此处我只想说pBUF_DSCR是指针,剩下的就是语法问题了 (pBUF_DSCR + num)->ADDR_TX = FreeBufAddr; /*取2的倍数,因为缓冲区都是字对齐的,注意此处如果大于1023会出现浪费现象 *因为USB_COUNTn_TX只能接收bit0~bit9 */ val = (val + 1)& ~1; } //输出端点 else { (pBUF_DSCR + num)->ADDR_RX = FreeBufAddr; /*因为USB_COUNTn_RX中存储只用bit10~bit14,如果BLSIZE=0(即块大小为2字节),那么只能是0~62个字节 *所以如果大于62,则应将块大小设置为BLSIZE=1(即32个字节) */ if(val > 62 ) { //块大小为32,则大小应该为32的倍数 val = (val +31)&~31; /*关于此计算公式,参见rm0008,21,5.3节 *(val >> 5)<<10 == val <<5 */ (pBUF_DSCR + num)->COUNT_RX = ((val << 5)-1) | 0x8000; } else { val = (val + 1) & ~1; (pBUF_DSCR + num)->COUNT_RX = val << 9; } }
史海拾趣
|
大家好,我是一名大三的学生,学的是嵌入式方向的,但我们现在才学嵌入式操作系统,都TMD还是理论,学了等于没学,就上学期还学了个汇编,现在一学期都快过完了,感觉什么关于嵌入式方面的都没学到,如果靠下学期再来学点东西,以后出去就别想混了 ...… 查看全部问答> |
|
先详细解释一下标题的意思。 我的播放器运行在wince5.0中,我编写了各种各样的播放器,有使用WMP的,有使用TCPMP的,有使用用DSHOW的,都会有这么个情况: 我要跳转到视频的某个位置,比如说10s,不能准确的设置到10s,而 ...… 查看全部问答> |
|
用核心板做一款机器,最后做电源管理才发现PWREN给悬空了,且VDDi,VDDiarm和VDDalive一起供电,休眠省电基本不用想了,现在我想仅靠降低CLOCK时钟降低功耗,比如进入SLOW模式,能将2440电流降低到多少?哪位试验过? 另外在wince系统运行时候转换n ...… 查看全部问答> |
|
请教各位帮忙单步跟踪一下下面这个程序 #include \"stdafx.h\" #include #include using namespace &n ...… 查看全部问答> |
|
本公司(知名国企)正在寻求IPCamera(网络摄像机)的技术合作,包括嵌入式开发+硬件设计、中心 管理平台开发。有特色的产品,可提供整机、主板,或者能提供优秀的硬件方案的亦可。 合作方式多种,可技术转让、兼职或者全职。 &nb ...… 查看全部问答> |
|
程序先前一直没问题,后来改程序又加了几条语句,在编译过程中就有一个错误:Code size limit exceeded(4096 code bytes)for this version of the compiler 4212bytes of CODE memory 10bytes of CONST memory(+4bytes shared) 544bytes of DATA me ...… 查看全部问答> |




