STM32_USB之完全双缓存(包括发送和接收) -- 更新中断处理
扫描二维码
随时随地手机看文章
STM32的USB双缓存接收代码其实已经可以在ST提供的USB示例代码中找到,只要稍加修改,就可以得到将近1MB的数据接收性能。虽然Datasheet中说明USB发送也同样可以使用双缓存,但并没有示例代码,由于为了测试性能,自己做了一个,测试中没有发现问题,虽然对性能的提升不如在USB接收上实现双缓存那么多。
注意:
FreeUserBuffer的作用是切换当前的USB缓存。
1.接收双缓冲:
EPX_OUT_Callback中,此代码只是在ST的示例程序的基础上稍加修改,并且不是偶写的,而是一个网友测试的:
if(GetENDPOINT(ENDP3) & EP_DTOG_TX)
{
FreeUserBuffer(ENDP3, EP_DBUF_OUT);
pkg_len = GetEPDblBuf0Count(ENDP3);
PMAToUserBufferCopy(buffer_out + count_out, ENDP3_RXADDR0, pkg_len);
}
else
{
FreeUserBuffer(ENDP3, EP_DBUF_OUT);
pkg_len = GetEPDblBuf1Count(ENDP3);
PMAToUserBufferCopy(buffer_out + count_out, ENDP3_RXADDR1, pkg_len);
}
2.发送双缓冲:
发送双缓冲也可以类似的实现,不过代码要比接收双缓冲复杂得多。不过了解原理的话,应该也差不多。
ST的STM32论坛里,也有人提出这个问题:http://www.st.com/mcu/forums-cat-7768-23.html,不过一直都没有人回答。
不过他的代码还有一些问题,或者可以说,他对原理还不够了解。实际代码还要比他的这个复杂。
中断处理代码:
// 有发送程序计算总共的数据表数量(包括ZLP)
// 每次IN中断,则把总共要发送的数据包数量-1
usb_in_numofpackage--;
if(GetENDPOINT(ENDP2) & EP_DTOG_RX)
{
if(usb_in_numofpackage > 0)
{
// enable next package
// FreeUserBuffer的作用是切换当前的缓存
// 如果还有数据包要发送,则切换缓存(数据已经准备好了)
FreeUserBuffer(ENDP2, EP_DBUF_IN);
}
// usb_in_data_remain是需要放入缓存的数据长度
//在USB发送函数中,首先会填充2个缓冲,usb_in_data_remain为总长度-2个缓冲的长度
if(usb_in_data_remain > 0)
{
// 还有数据要发送
if(usb_in_data_remain > VIRTUAL_COM_PORT_DATA_SIZE)
{
len = VIRTUAL_COM_PORT_DATA_SIZE;
}
else
{
len = usb_in_data_remain;
}
//把数据拷贝到空闲的缓冲区中,并且设置长度
UserToPMABufferCopy(buffer_in, ENDP2_TXADDR0, len);
SetEPDblBuf0Count(ENDP2, EP_DBUF_IN, len);
// usb_in_data_remain减去已经放入缓冲区的长度
usb_in_data_remain -= len;
//更新数据指针
buffer_in += len;
}
else
{
// 数据都已放入缓冲,设置空闲缓冲区长度为0
SetEPDblBuf0Count(ENDP2, EP_DBUF_IN, 0);
}
}
else
{
if(usb_in_numofpackage > 0)
{
// enable next package
FreeUserBuffer(ENDP2, EP_DBUF_IN);
}
if(usb_in_data_remain > 0)
{
if(usb_in_data_remain > VIRTUAL_COM_PORT_DATA_SIZE)
{
len = VIRTUAL_COM_PORT_DATA_SIZE;
}
else
{
len = usb_in_data_remain;
}
UserToPMABufferCopy(buffer_in, ENDP2_TXADDR1, len);
SetEPDblBuf1Count(ENDP2, EP_DBUF_IN, len);
usb_in_data_remain -= len;
buffer_in += len;
}
else
{
SetEPDblBuf1Count(ENDP2, EP_DBUF_IN, 0);
}
}