STM32学习笔记之USB数据接收和发送流程分析
来源:互联网 发布:淘宝宝贝如何上下架 编辑:程序博客网 时间:2024/06/10 11:18
既然学习了USB,那就必须的搞懂USB设备与USB主机数据是怎么通讯的。这里主要讲设备端,因为我们的代码是做USB设备用的。
我们需要必须要定义了USB中断。起始在STM32的中断向量表中给USB两个中断,我们可以在stm32f10x.h中找到这两个中断:
这两个中断是USB与CAN复用的中断,在做USB用时,表示USB设备的高优先级与低优先级中断。在我的工程中,我选择用低优先级的USB中断。代码如下:
中断服务程序很简单,就是在发生中断的时候调用USB_istr()函数。USB_istr()这个函数我们之前说过的,在usb_istr.c中定义的。这个函数处理ISTR中断状态寄存器中定义的中断,包括:CTR正确传输中断、RESET复位中断,DOVR分组缓冲溢出中断、ERR错误中断、WAKEUP中断、SUSP挂起中断、SOF帧首中断、ESOF期望帧首中断。这里重点是CTR中断,在USB在正确发送或正确接收数据后,USB模块自动回将ISTR寄存器的该位置1,触发中断CTR中断。在USB_istr()中CTR的处理代码如下:
#if (IMR_MSK & ISTR_CTR) 这句话。
首先要解释下 #define IMR_MSK (CNTR_CTRM | CNTR_WKUPM | CNTR_SUSPM | CNTR_ERRM | CNTR_SOFM \ | CNTR_ESOFM | CNTR_RESETM )
这是IMR_MSK的定义,表示包含所有中断的掩码,IMR_MSK & ISTR_CTR表示:如果ISTR_CTR是规定的中断类别,则编译#if与#endif之间的代码。很明显这里符合。然后,判断下从CNTR寄存器中读出来的中断值是CRT中断,且该中断已经在CNTR中使能了。接着调用CTR_LP()函数处理,如果定义了CTR_CALLBACK,则调用CTR_Callback()函数,该函数是个钩子函数,让用户在正确接收到数据后能够做些什么,比如说亮下灯或通过串口打印些消息。
这里需要着分析下CTR_LP()这个函数在usb_int.c中定义。代码如下:
这个函数首先会判断是否真的CTR中断,如果是,执行while()中的代码,用EPindex来保存产生中断的端点号。EPindex为0表示是端点0产生的中断,说明此时USB还处于枚举阶段。EPindex不为0,表示枚举已经成功了,USB处于正常工作状态。
在枚举阶段,SaveRState保存端点0寄存器的值,接着SaveTState = SaveRState & EPTX_STAT;和SaveRState &= EPRX_STAT;这两句,SaveTState保存当前发送端点0的状态, SaveRState 保存当前接收端点的状态。接着设置接收端点0为NAk状态,发送端点0也设置成NAK状态,也就是说当主机发送任何数据,从机只以NAK回应,从机也只能发送NAK数据,即不允许在数据处理阶段进行数据通讯。然后判断是输入还是输出。如果是输入(注意这里的输入是相对于主机来说的)则清除端点寄存器的EP_CTR_TX标志位,并且调用IN令牌包处理函数In0_Process()(在usb_core.c中定义)。如果是输出(注意这里的输出是相对于主机来说的),则还要判断接收到是SETUP包还是OUT令牌包,如果是SETUP包,清除端点0寄存器的EP_SETUP位,并且调动SETUP处理函数Setup0_Process(),同时还要回复原来的接发端点的状态,准备处理下一次的中断处理。如果是OUT令牌包,清除端点0寄存器的EP_CRT_RX位,调用OUT处理函数Out0_Process(),同时还要回复原来接法端口的状态,准备处理下一次的中断处理。
在工作阶段或者说是非枚举阶段,首先要判断下是EP_CTR_RX还EP_CTR_TX标志,如果是EP_CTR_RX正确接收标志,则清除该标志,调用对应端点的OUT处理函数(*pEpInt_OUT[EPindex-1])()(在usb_istr中有注册过),如果是EP_CTR_TX标志,则清除该标志,调用对应端点的IN处理函数(*pEpInt_IN[EPindex-1])()(在usb_istr中有注册过)。
在usb_istr.c中非别注册了7个端点输入函数和端点输出函数。如下:
而这些函数的定义在usb_endp.c中,我们拿EP1_OUT_Callback()函数分析。
这个函数的工作很简单,首先因为数输出端点,是接收数据的,而USB模块接收到的数据又是暂存在PAM双缓冲区中,所以要线把数据从PMA中读取出来,放到用户自己缓冲区中。接着设置端点接收状态有效,因为当接收数据后,端点就会被关闭。最后置位接收带数据标志。
以上就是USB设备的接收的流程。接下去讲讲发送流程。发送比接收简单多了看看下面的代码就知道了。
把要发送的数据拷贝到PMA中,之后设置端点计数,使能下端点,数据就发送出去了。
总结下:
数据发送:UserToPMABufferCopy--->SetEPTxCount--->SetEPTxValid
数据接收:USB_LP_CAN1_RX0_IRQHandler--->USB_Istr---->CTR_LP--->EPx_OUT_Callback
阅读全文
0 0
- STM32学习笔记之USB数据接收和发送流程分析
- STM32 USB数据接收与数据发送程序流程分析
- STM32 USB数据接收与数据发送程序流程分析
- [STM32/8经验] STM32 USB数据接收与数据发送
- STM32学习笔记之-串口中断接收不定数据buff
- STM32学习笔记之USB库文件分析
- STM32学习笔记之USB工程目录文件分析
- STM32学习笔记之 USB驱动usb_endp.c文件和usb_istr.c文件分析
- UDT4协议源码分析之数据的发送和接收
- 利用STM32 的串口来发送和接收数据实验
- STM32 USB学习笔记
- STM32 USB学习笔记
- STM32学习笔记之软件开发流程
- Android短信发送和接收流程源码分析
- 数据发送和接收
- STM32 UART(接收 ,发送数据)
- STM32 USB学习笔记1
- STM32 USB学习笔记2
- Android 利用AudioManager控制后台音乐播放器暂停,播放
- essilor 依视路 爱赞镜片使用体验
- Java事务处理全解析(六)—— 使用动态代理(Dynamic Proxy)完成事务
- 连接到 Linux 服务器时首先要运行的 5 个命令
- Android自定义控件之折线图
- STM32学习笔记之USB数据接收和发送流程分析
- maven入门:生命周期和插件Plugins(四)
- 计算两个数的平均值(按位与按位异或)
- datagrid不展示行号原因之一
- uva11076求全排列的和
- Java事务处理全解析(七)—— 像Spring一样使用Transactional注解(Annotation)
- String的常用方法
- 根据配货员筛选订单
- TCP: SYN ACK FIN RST PSH URG 详解