历史上的今天
返回首页

历史上的今天

今天是:2024年11月05日(星期二)

正在发生

2020年11月05日 | 使用STM32的USB模块中后对USB缓冲区的认识

2020-11-05 来源:eefocus

最近在使用STM32的USB模块开发个项目,还以为挺简单,结果搞了快两天才把USB的包缓冲区的访问搞定,在此做个小总结吧。


STM32的USB模块包缓冲区有512B,但是在STM32的参考手册中的存储器映像中却表明0x40006000-0x400063ff,整整多了512B,怎么会这样呢,同时在尝试着编程时也遇到了一个问题:


在usb_core.c文件的Setup0_Process(void)这个函数中,有这么一段:


uint16_t offset = 1; 

if (pInformation->ControlState != PAUSE)

  {

    pInformation->USBbmRequestType = *pBuf.b++; /* bmRequestType */

    pInformation->USBbRequest = *pBuf.b++; /* bRequest */

    pBuf.w += offset;  /* word not accessed because of 32 bits addressing */

    pInformation->USBwValue = ByteSwap(*pBuf.w++); /* wValue */

    pBuf.w += offset;  /* word not accessed because of 32 bits addressing */

    pInformation->USBwIndex  = ByteSwap(*pBuf.w++); /* wIndex */

    pBuf.w += offset;  /* word not accessed because of 32 bits addressing */

    pInformation->USBwLength = *pBuf.w; /* wLength */

  }  


这其中又不太明白为什么需要pBuf.w += offset;而且后面的解释也不太懂 /* word not accessed because of 32 bits addressing */

,我于是在这段之前加入调试以显示收到什么数

        #ifdef DEBUG

        UARTSend_String("***  端点0收到SETUP数据  ***rn");

        for(offset=0;offset<16;offset++)

        {

                UARTSend_Hex(*pBuf.b++);

        }

        #endif

结果串口调试显示如下:

***  USB总线复位  ***

***  USB总线CTR置位  ***

***  进入端点0  ***

***  端点0收到SETUP包  ***

***  端点0收到SETUP数据  ***

0x80 0x06 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x40 0x00 0x00 0x00


本来应该显示0x80 0x06 0x00 0x01 0x00 0x000x40 0x00才对,不太明白怎么0x80 0x06和0x00 0x01 后面多了两个 0x00 ,难道USB模块还会将收到的数据跳着放吗?


 后来反复看参考手册,问了些人,才知道原来STM32的USB缓冲区是一个双端口的RAM,CPU一端需要使用32位方式访问,但USB模块一端使用16位方式访问。也就是说每个USB模块中的地址*2才能对应到控制器中的实际地址,这样每四个字节地址空间后两个字节地址空间是空的。所以上面串口调试显示的数据每正确两个字节就会多出两个字节的0x00。


这里也对STM32的USB库函数中对缓冲区的操作函数做个说明:


在usb_men.c文件有这么一个函数


void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)


  uint32_t n = (wNBytes + 1) >> 1;/* /2*/

  uint32_t i;

  uint32_t *pdwVal;

  pdwVal = (uint32_t *)(wPMABufAddr * 2 + PMAAddr);

  for (i = n; i != 0; i--)

  {

    *(uint16_t*)pbUsrBuf++ = *pdwVal++;

    pbUsrBuf++;

  }


它的作用是将缓冲区中的数据拷贝到你所定义的uint8_t Receive_Buffer[];数组中。其它地方都好理解,这里说说


  pdwVal = (uint32_t *)(wPMABufAddr * 2 + PMAAddr);

  for (i = n; i != 0; i--)

  {

    *(uint16_t*)pbUsrBuf++ = *pdwVal++;

    pbUsrBuf++;

  }


首先是pdwVal = (uint32_t *)(wPMABufAddr * 2 + PMAAddr);这里wPMABufAddr * 2之所以要*2就是前面所述的USB模块中的地址*2才能对应到控制器中的实际地址,在取得对应端点的缓冲区首地址后,将其(uint32_t*)强制指向uint32_t型,这样每次*pdwVal++,pdwVal的地址都增加4个字节,并且每次都会有四个字节的数据读出。


在for循环中,*(uint16_t*)pbUsrBuf++ = *pdwVal++;这句重点说说,++与指针*同优先级,结合顺序为至右向左结合,因此相当于*((uint16_t*)pbUsrBuf++),先*(uint16_t*)pbUsrBuf赋值只取*pdwVal++的32位数据的前16位,然后再将pbUsrBuf加上1个字节。到这里,前面定义的uint8_tReceive_Buffer[];数组中就有两个数组变量被赋值了,但这时地址还指增加一个字节,因此还需要pbUsrBuf++;让其指向Receive_Buffer[];的下下个数组变量。一次循环,知道读出所有数据。


推荐阅读

史海拾趣

友盟(AP)公司的发展小趣事

友盟(AP)公司的发展,也离不开与众多合作伙伴的紧密合作。公司始终坚持开放、合作的理念,积极寻求与各行各业的合作机会。通过与手机厂商、应用开发者、广告商等建立合作关系,友盟成功将自身的技术优势和数据分析能力转化为商业价值。同时,友盟也通过合作伙伴的支持和反馈,不断优化产品和服务,实现了与合作伙伴的共赢发展。

AOS公司的发展小趣事

随着技术的不断发展和市场的扩大,AOS公司开始积极寻求全球扩张的机会。1998年,AOS在南京独资成立了中国总部,开始了其在中国的深耕之旅。通过多年的努力,AOS在中国建立了完善的产研基地和销售网络,其产品横跨家用和商用两大领域,赢得了广大消费者的信任和喜爱。如今,AOS已成为中国市场上备受推崇的热水设备品牌之一。

Global Specialties公司的发展小趣事

在电子技术的不断推动下,Global Specialties始终保持对新技术的高度敏感。公司不断投入研发资源,对现有产品进行升级换代,并推出了一系列具有创新性的新产品。例如,公司开发的智能测试仪器能够自动完成复杂的测试任务,大大提高了测试效率和准确性。这些技术创新不仅巩固了Global Specialties在业内的领先地位,还为公司带来了更多的商业机会。

AZM [Arizona Microtek, Inc]公司的发展小趣事

AZM公司成立于电子行业的蓬勃发展时期,创始人凭借对微电子技术的深刻理解和敏锐的市场洞察力,决定投身于这一领域。创业初期,公司面临着资金短缺、技术瓶颈和市场认可度低等多重挑战。然而,创始人凭借坚定的信念和不懈的努力,带领团队攻克了一个又一个技术难题,成功研发出了具有竞争力的微电子产品,并逐渐在市场上获得了认可。

Capax Technologies Inc公司的发展小趣事

随着国内市场的饱和,Capax Technologies Inc开始积极拓展海外市场。公司制定了详细的国际化战略,通过设立海外研发中心、建立销售网络等方式,逐步进入国际市场。在国际化的过程中,Capax Technologies Inc不仅提升了自身的技术水平和市场竞争力,还积累了丰富的国际经验,为公司的长远发展奠定了坚实基础。

Digital公司的发展小趣事

随着业务的不断发展和市场的不断扩大,DIALIGHT公司逐渐实现了全球化布局。他们在美国、英国、丹麦、德国、马来西亚、新加坡、澳大利亚、墨西哥和巴西等地设立了分支机构或办事处,为全球客户提供及时、高效的服务。此外,DIALIGHT还积极寻求与其他企业的合作与共赢,通过战略合作协议的签署,为双方带来新的业务机遇和合作空间。这些举措不仅增强了DIALIGHT的市场竞争力,也为其未来的发展奠定了坚实的基础。

请注意,由于篇幅限制,以上三个故事仅为DIALIGHT公司发展历程的简要概述。如需更详细的信息和更多故事,建议查阅相关资料或访问公司官网。

问答坊 | AI 解惑

学习rfid必须知道的六个问题

  问题一:RFID是什么?RFID是Radio Frequency Identification的缩写,即射频识别,俗称电子标签。  问题二:什么是RFID技术?  RFID射频识别是一种非接触式的自动识别技术,它通过射频信号自动识别目标对象并获取相关数据,识别工作无须人工 ...…

查看全部问答>

编制了利用EXCEL为运算平台,能够自动计算的《经纬仪导线测量计算簿》

测量工作是煤矿生产的眼睛,它为矿山建设的设计和施工提供了必要的基础数据和资料。矿山测量工作分为外业和内业两项,内业计算工作需要进行大量的函数和数据运算,稍不注意就可能出现错误,将给矿山的安全生产工作造成损失。另外,随着地质测量标准化工 ...…

查看全部问答>

想要学习FPGA,希望推荐款合适的学习板

大家好,我想学习FPGA,对它很感兴趣。 所以想买一块学习板,请大家推荐一款比较适合初学者的。价格的话在800以内就行。 如果可以的话,推荐几本经典的书就更好了。 小弟在此先谢过了 …

查看全部问答>

WINCE中同一个flash显示两个flash文件夹?

在WINCE显示设备里出现连个flash设备:Nandflash,Nandflash2,而两个FLASH文件夹都是指向同一个flash。查了下注册表,里 面就有一个FLASH项。请问这是哪里设置不对造成的?…

查看全部问答>

doc/view架构下的消息响应

新建了一个wince下的单文档工程,在CMainFrame里添加了EraseBkgnd的消息响应,设置断点发现程序并没有进入响应。 后来又新建了一个windows下的单文档工程,同样添加消息响应,发现程序有响应EraseBkgnd。 不知道为什么。麻烦高手解答。…

查看全部问答>

C8051F版数字湿度计调试3---硬件SMbus与SHT21通信

硬件SMbus与SHT21通信     [ 本帖最后由 sdjntl 于 2010-8-18 16:43 编辑 ]…

查看全部问答>

50HZ交流转直流,直流电压随交流幅值变

大神们 求帮帮忙吧,   把50hz左右交流转成直流,AD给单片机测其电压,交流幅值变换在0到15v左右吧,直流电压最好就是交流有效值,要有比例关系。要精确点的,大家给点意见吧,最好是以前做过的。…

查看全部问答>

AM335X的Arduino开发板不知道大家敢不感兴趣

助力电子爱好者开发更小型、更友好、更低成本解决方案 信用卡大小的开发板支持便捷硬件扩展、通过单线缆以及 10 秒钟 Linux 启动便可实现快速开发 北京2011年11月2日电  -- 日前,BeagleBoard.org 高兴地宣布推出其深受青睐产品系列中 ...…

查看全部问答>

场效应管知识-共源极放大器

  场效应管共源极放大器实验 一、实验目的1、明确场效应管的性能和特点2、明确场效应管共源极放大器的特点3、进一步熟悉放大器静态工作点和动态参数的调试方法 二、预习要求1、熟悉有关场效应管部分内容,并根据提供的实验电路参数,分别用 ...…

查看全部问答>

【TI资料下载】UCD3028 数字电源软件设计说明

摘 要 UCD3028 数字电源功能丰富,可以完成两个独立功率支路的控制;软件配置灵活,可以实现多种功能包括多种故障的检测和处理。本文基于一款1/8 砖模块产品对UCD3028 的软件设计进行了详细说明,内容包括外界模拟信号的采集与转换,副边电流的采 ...…

查看全部问答>