3. 验证测试
下面我利用HAL库,基于STM32F429芯片演示实现过程,重点在接收处理代码。我使用STM32F429 Discovery开发板,使用HS USB模块并令其工作在FS MODE,这样我们就可以方便地使用片内USB FSPHY。
我使用STM32CubeMX工具进行配置,生成基于STM32 HAL库的工程。使用ST提供的STM32CubeIDE进行编译调试。有关配置就不截图了。
另外,我还配置了1个按键并开启相应外部中断。每发生按键事件时,F429 USB设备向PC主机发送一段打招呼的字符串,并通过串口助手显示出来。
我在main.c文件里定义了下面几个变量。
图3 变量截图
其中,Flag_KeyPressed和Flag_DataReceived分别标示按键操作和收到从主机发过来的数据的情况。Rx_buffer【】数组用来存放接收来自主机的数据,我这里的定义长度为512字节【具体使用时按需设置】。下图是Main.c里的主循环代码截图,见图4。
图4 主循环代码截图
主循环里检查按键标志和收到数据的标志,如有按键发生,则向主机发送前面提到的打招呼的字符串;如有收到来自主机的数据,则向主机回送过去。
今天的重点是讨论USB设备如何从主机接收64字节以上的数据。基于现有HAL库,对于USB设备的接收,我们只需关注一个USB中断接收回调函数,那就是CDC_Receive_HS()函数。该函数在usbd_cdc_if.c文件里。我具体编写的函数代码如下面两幅截图所示。
图5 接收回调函数中相关变量
图6 接收回调函数处理代码截图
代码很简单,我在库代码的基础上增加了橙色方框内的代码。基本功能就是,先读取当前收到的数据长度【SinglePackLength】,分整包和非整包两种情况鉴**再处理。若是接收的整包数据,继续等待接收下一包;若是非整包,视为此次传输结束,并设置收到标志Flag_DataReceived为非0值,然后在主循环里将收到的数据回送给主机。
其中,Max_Pack_Size是当前CDC类BULK传输端点的最长传输包长,这里为64字节。
Num_Rx_Data表示接收到数据个数,Num_Out_Pack表示接收到的数据包个数,Num_Packet跟Num_Out_Pack内容一样,不过,Num_Packet等于0还表示准备开始新一轮传输的接收。这里多定义基于上面的接收处理代码,我们来验证结果:
图7 接收5个字符的结果截图
借助PC端的串口助手向STM32F429设备发送了5个字符,我们通过STM32CubeIDE调试环境可以清晰地从上图看到设备收到的数据个数为5,数据包个数为1。显然没问题。那个Rx_buffer数组是我用来存放接收数据的,若在调试窗口打开,数据较多列表显示会很长,这里就没打开了。事实上接收的数据内容也是没问题的。
下图是借助PC端的串口助手向STM32F429 USB设备发送了305个字符的接收情况。
图8 接收305个字符的结果截图
显然,对于305个字符,PC主机端要分成5包才能发送完毕,即4整包【每包64字节】再加1个非完整包。所以USB设备接收结果也正好是5包,即上图中Num_Out_pack的数据,接收到的数据量为305,即上图中Num_Rx_Data的数据。同样,结果OK。
下图是PC端刚好发送一个完整包64字节数据的USB设备接收情况,也一切正常。
图9 接收64个字符的结果截图
也就是说,使用我上面编写的接收处理代码,对主机发送的数据的个数不再局限于64字节以内了。当然,具体应用时我们还可以根据主机端单次传输数据的大小情况及提取数据的方式适当调整这里的Rx_buffer[]数组大小。【注:上面测试时我临时关闭了设备端的数据回送功能,是为了避免截图后数据混乱,让人分不清原始数据和回显数据】
|