STM32 USB提供双缓冲接收方式,以解决对时序和速度要求较高的场合,如使用同步传输的音/视频流、接近线速的Bulk传输等。最近在用F103C8T6做声卡,在调试时发现收到的数据总是最后一对采样错误,导致声音播放时有毛刺。反复找问题和调试无果,遂怀疑芯片有问题,更换后仍无果。最后一统乱试发现,判断当前用户使用的缓冲区的标志位反了,具体如下:
voidEP3_OUT_Callback(void)
{
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);
}
}
以上是搬运的网上的一个例程,可以看到通过判断端点的EP_DTOG_RX/EP_DTOG_TX标志位来确定当前用户所使用的缓冲区,此例程是接收方向的双缓冲中断处理函数,当EP_DTOG_TX标志位置1时表示使用用户使用BUFF0而USB IP核使用BUFF1,反之用户使用BUFF1而USB使用BUFF0。我在编写声卡的程序时也按照此思路,接收方向判断EP_DTOG_TX来交换Buffer,但此时收到的数据总有错误。而无意中将EP_DTOG_TX改为EP_DTOG_RX,则问题消失,数据正常,播放声音正常。遂仔细翻阅STM32器件手册,发现:
即对于接收方向上使用EP_DTOG_RX判断缓冲区而发送方向用EP_DTOG_TX(从宏定义字面意思上也能看懂的~),但这里并没有说明接收方向和发送方向是以谁为参考,即对于OUT端点是当做接收方向(对单片机)还是发送方向(对主机)。但仔细看下OUT端点,使用的缓冲区均以RX结尾,也就是说理论上应该是和DTOG_RX对应的。如果确实是这样,那么网上的例程应该全是错误的,按照他们的写法根本收不到正确的数据。但确实是改为RX后,声卡工作正常了,Debug Watch看到数据流也正确了。
待有空写一个Bulk传输的例程来验证下再来跟大家分享!
引用 蓬莱的鹰:I2C的问题是因为本身硬件BUG导致的吧?然后新的固件库从软件上回避了这个BUG,硬件本身并没有修正好像。。。
I2c库函数才是真坑
200字以内,仅用于支线交流,主线讨论请采用回复功能。