详情:http://bbs.21ic.com/forum.php?mod=viewthread&tid=109584

 
USB 1.0的最高12Mbps.
USB 2.0的高速模式480Mbps,全速模式12Mbps,低速模式1.5Mbps

而是设置STM32端的USART的波特率。PC与STM32传输速度是以USB1.1的理论速度传输的,是不能设置的。

接收到数据,置NAK->将缓冲区数据拷贝到用户区(用户处理过程)->发ACK通知主机完成了完整的接收可以发送下一个->主机发送下一个,
 
. 
 
 前天测试自己编写的USB驱动程序时候发现从主机到STM32的OUT传输(主机到设备)速率竟然只有最高33KB/S,实在是晕死了。经过研究后发现是 驱动程序中设置的PIPE MaxTransferSize参数的关系,原先设置64只能33KB/S,后参考其他USB设备驱动程序的值,设置成了65535,再测试USB OUT的速度,达到了500KB/S,终于解决了驱动程序的瓶颈。不过算下USB 2.0全速的通讯速率是12Mb/S,排除掉CRC、令牌、SOF等等开销怎么也应该不止最大500KB/S啊。到网上看了看,基本上应该能达到 600KB/S~700KB/S以上,我现在的速度应该还有很大的提升才是。
    看看程序,发现
void EP3_OUT_Callback(void)//EP3 OUT的回调函数,当EP3接收到数据时候中断调用该函数
{
  count_out = GetEPRxCount(ENDP3);//获得接收到的数据长度
  PMAToUserBufferCopy(buffer_out, ENDP3_RXADDR, count_out);//将数据从USB EP3 RX的缓冲区拷贝到用户指定的数组中
  SetEPRxValid(ENDP3); //完成拷贝后置有效状态,从而EP3发送ACK主机可以进行下一个数据包的发送
}
    试着将PMAToUserBufferCopy这句注释掉(这样STM32就不处理接收到的数据了)后再测试速度,惊奇地发现速度竟然达到了 997KB/S!晚上仔细想了想,数据肯定是要使用的,这个数据拷贝的过程的时间消费总是少不了的;由于通常情况下USB设备BULK数据接收的步骤就 是:接收到数据,置NAK->将缓冲区数据拷贝到用户区(用户处理过程)->发ACK通知主机完成了完整的接收可以发送下一个->主机 发送下一个,按照以上的步骤USB接收一步步的进行,只要STM32不完成数据处理,状态就一直是NAK,主机就会不停地发送该数据包,浪费了带宽,因此 就会导致我上面最大速度500KB/S难以再增加的情况!不甘心啊~~
    昨天晚上又仔细研究了STM32的技术参考手册的USB章节内容,里面提到BULK可以采用双缓冲机制(PING-PONG)进行处理,正好可以解决上面 的情况。双缓冲机制的原理就是分配2块接收缓冲,STM32的用户处理和USB接口可以分别交替占用2个缓冲区,当USB端点接收数据写其中一个缓冲区的 时候,用户的应用程序可以同时处理另一个缓冲区,这样缓冲区依次交换占有者,只要用户处理程序在USB端点接收的时间片段内完成处理,就能够完全不影响 USB的通讯速度!
    程序部分修改
一、EP3_OUT的设置修改,
//ZYP:修改EP3为BULK双缓冲方式-------------------------
  SetEPType(ENDP3, EP_BULK);
  SetEPDoubleBuff(ENDP3);
  SetEPDblBuffAddr(ENDP3, ENDP3_BUF0Addr, ENDP3_BUF1Addr);
  SetEPDblBuffCount(ENDP3, EP_DBUF_OUT, VIRTUAL_COM_PORT_DATA_SIZE);
  ClearDTOG_RX(ENDP3);
  ClearDTOG_TX(ENDP3);
  ToggleDTOG_TX(ENDP3);
  SetEPRxStatus(ENDP3, EP_RX_VALID);
  SetEPTxStatus(ENDP3, EP_TX_DIS);
//------------------------------------------------------
二、EP3_OUT回调函数的修改
void EP3_OUT_Callback(void)
{
//ZYP:以下是修改成EP3双缓冲OUT后的处理函数
  if (GetENDPOINT(ENDP3) & EP_DTOG_TX)//先判断本次接收到的数据是放在哪块缓冲区的
  {
    FreeUserBuffer(ENDP3, EP_DBUF_OUT); //先释放用户对缓冲区的占有,这样的话USB的下一个接收过程可以立刻进行,用另一块缓冲区,同时用户并行进行下面处理,在另一块接收完之前,处理完用户数据就行,否则缓冲区竞争。
    count_out = GetEPDblBuf0Count(ENDP3);//读取接收到的字节数,
    PMAToUserBufferCopy(buffer_out, ENDP3_BUF0Addr, count_out);
  }
  else
  {
    FreeUserBuffer(ENDP3, EP_DBUF_OUT);
    count_out = GetEPDblBuf1Count(ENDP3);
    PMAToUserBufferCopy(buffer_out, ENDP3_BUF1Addr, count_out);
  }
}
    经过上面的修改,终于解决了STM32在处理接收数据时导致主机等待的情况,用BUS HOUND软件测试了下
 

PS:上面的FreeUserBuffer(ENDP3, EP_DBUF_OUT); 这句话的上下位置是关键,如果放到函数的后面,则仍旧会有主机等待STM32处理数据的情况,速度仍然是500KB/S!

    把这句话放在拷贝函数的前面的话就真正把双缓冲PING-PONG机制用起来了。大致算了下 PMAToUserBufferCopy(buffer_out, ENDP3_BUF1Addr, count_out);这句话当count_out为最大值64的时候STM32执行需要302个周期,72MHZ情况下约4.2微秒执行时间,而USB 传输按照12Mb/s的线速度传输64字节的数据至少也得40微秒,因此只要PMAToUserBufferCopy的时间不超过40微秒,就不会导致缓 冲区竞争的情况。 

STM32的bulk双缓冲传输速度的讨论,硬件的坑永远填不完的更多相关文章

  1. 双缓冲(Double Buffer)原理和使用

    转自双缓冲(Double Buffer)原理和使用 一.双缓冲作用            双缓冲甚至是多缓冲,在许多情况下都很有用.一般需要使用双缓冲区的地方都是由于"生产者"和& ...

  2. 双缓冲(Double Buffer)原理和使用【转】

    转自:http://blog.csdn.net/acs713/article/details/16359551 原文出自:http://blog.csdn.net/xiaohui_hubei/arti ...

  3. C++双缓冲多线程分析大文件词频

    实习生活告一段落,我正式从一名.NET程序员转入Java阵营,不得不说刚开始用Java的东西是多么的不习惯,但是经过三个月的使用与开发,我也发现了Java的优势:不在于语言,而在于开源.这意味着有更多 ...

  4. OpenGL的消隐与双缓冲

    首先是大家可能已经发现,在我们之前提到的所有例子中,在图形的旋转过程中整个图形都有一定程度的闪烁现象,显得图形的过渡极不平滑,这当然不是我们所要的效果,幸好opengl 支 持一个称为双缓存的技术,可 ...

  5. Win32 GDI 非矩形区域剪裁,双缓冲技术

    传统的Win32通过GDI提供图形显示的功能,包括了基本的绘图功能,如画线.方块.椭圆等等,高级功能包括了多边形和Bezier的绘制.这样app就不用关心那些图形学的细节了,有点类似于UNIX上的X- ...

  6. 双缓冲技术(Double Buffering)(1、简介和源代码部分)

    这一节实在是有些长,翻译完后统计了一下,快到2w字了.考虑到阅读的方便和网络的速度,打算把这节分为5个部分,第一部分为双缓冲技术的一个 简介和所有的代码,如果能够看懂代码,不用看译文也就可以了.第二部 ...

  7. c++双缓冲技术,以避免闪烁绘图

    当数据量非常大时,画图可能须要几秒钟甚至更长的时间,并且有时还会出现闪烁现象,为了解决这些问题.可採用双缓冲技术来画图. 双缓冲即在内存中创建一个与屏幕画图区域一致的对象,先将图形绘制到内存中的这个对 ...

  8. 干货---stm32f103之DMA双缓冲__也算我为网络贡献的微薄之力

    思考再三:终究是要拿出一些干货--单片机基础核心代码,串口的高效率使用请这里开始.--举一反三,我只列出串口一的双dma缓冲应用范例,剩下的自己扩展.并给与了我迄今觉得最好的串口配置架构-感谢野火的高 ...

  9. 【MFC】MFC绘图不闪烁——双缓冲技术

    MFC绘图不闪烁——双缓冲技术[转] 2010-04-30 09:33:33|  分类: VC|举报|字号 订阅 [转自:http://blog.163.com/yuanlong_zheng@126/ ...

随机推荐

  1. mysql ---复制表结构---创建新表

    1.复制表结构及数据到新表CREATE TABLE 新表SELECT * FROM 旧表这种方法会将oldtable中所有的内容都拷贝过来,当然我们可以用delete from newtable;来删 ...

  2. mysql连接其他表删除某个表的数据

    delete a from TableA a left join TableB b on a.XX = b.YY left join TableC c on c.ZZ = a.XX where 条件

  3. Safari5及以下版本不支持Date的横杠字符串格式

    Date构造器有多种方式创建方式 一.new Date() // 当天 var date = new Date() 二.new Date(value) // value 为一个整数 var date ...

  4. Debian

    一.简介 https://zh.wikipedia.org/wiki/Debian 二.下载 https://www.debian.org/ 三.配置 1)挂载iso镜像 mount /dev/cdr ...

  5. hdu 1398 Square Coins(简单dp)

    Square Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Pro ...

  6. Ubuntu14.04安装中文输入法以及解决Gedit中文乱码问题[转载]

    转载自:http://www.cnblogs.com/zhcncn/p/4032321.html 写在前面:解决gedit 在txt文件格式出现乱码的问题,在我自己的操作中是需要把系统设置成中文显示环 ...

  7. linux—【绝对路径与相对路径】与【【文件基本操作】】(4)

    [绝对路径与相对路径] 绝对路径:我们在获得一个文件的时候,从根目录到二级到更多级目录都写全了, 终才找到这个文件,这种方式就是“绝对路径” 相对路径:目标文件与我本身文件的相对位置 当前目录:./  ...

  8. Hive UDF’S addMonths

    our project use hive 0.10 , and in the hiveql , we need use addMonths function builtin in hive-0.11. ...

  9. [原创]cin、cin.get()、cin.getline()、getline()、gets()、getchar()的区别

    这几个输入函数经常搞不清具体特点和用法,这里稍作总结 一.cin>> 1.最基本用法,输入一个变量值 2.输入字符串,遇“空格”.“TAB”.“回车”结束,比如输入“hello world ...

  10. ZOJ 3157 Weapon --计算几何+树状数组

    题意:给一些直线,问这些直线在直线x=L,x=R之间有多少个交点. 讲解见此文:http://blog.sina.com.cn/s/blog_778e7c6e0100q64a.html 首先将直线分别 ...