本帖最后由 zzwj5120 于 2014-12-21 11:44 编辑
USB通信及串口DMA发送部分源代码,usb_endp.c
/**
******************************************************************************
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usb_lib.h"
#include "usb_desc.h"
#include "usb_mem.h"
#include "hw_config.h"
#include "usb_istr.h"
#include "usb_pwr.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Interval between sending IN packets in frame number (1 frame = 1ms) */
#define VCOMPORT_IN_FRAME_INTERVAL 5
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint8_t USB_Rx_Buffer[VIRTUAL_COM_PORT_DATA_SIZE];
extern uint8_t VCP1_Tx_Buffer1[]; /* VCP1 DMA发送缓冲1 */
extern uint8_t VCP2_Tx_Buffer1[]; /* VCP2 DMA发送缓冲1 */
extern uint8_t VCP3_Tx_Buffer1[]; /* VCP3 DMA发送缓冲1 */
extern uint8_t VCP1_Tx_Buffer2[]; /* VCP1 第二缓冲(临时存放来自PC主机的数据包) */
extern uint8_t VCP2_Tx_Buffer2[]; /* VCP2 第二缓冲(临时存放来自PC主机的数据包) */
extern uint8_t VCP3_Tx_Buffer2[]; /* VCP3 第二缓冲(临时存放来自PC主机的数据包) */
extern uint8_t Flag_VCP1_Tx_Buf_Use; /* 1: 表示DMA发送已启动,VCP1_Tx_Buffer1被锁定 */
extern uint8_t Flag_VCP1_Tx_Buf_Full; /* 1: 表示VCP1_Tx_Buffer2数据可能已放满,暂时不能再从主机接收数据 */
extern uint16_t VCP1_Tx_Buffer_Cnt; /* VCP1 第二缓冲 收到的字符总数 */
extern uint8_t Flag_VCP2_Tx_Buf_Use; /* 1: 表示DMA发送已启动,VCP2_Tx_Buffer1被锁定 */
extern uint8_t Flag_VCP2_Tx_Buf_Full; /* 1: 表示VCP2_Tx_Buffer2数据可能已放满,暂时不能再从主机接收数据 */
extern uint16_t VCP2_Tx_Buffer_Cnt; /* VCP2 第二缓冲 收到的字符总数 */
extern uint8_t Flag_VCP3_Tx_Buf_Use; /* 1: 表示DMA发送已启动,VCP3_Tx_Buffer1被锁定 */
extern uint8_t Flag_VCP3_Tx_Buf_Full; /* 1: 表示VCP3_Tx_Buffer2数据可能已放满,暂时不能再从主机接收数据 */
extern uint16_t VCP3_Tx_Buffer_Cnt; /* VCP3 第二缓冲 收到的字符总数 */
extern uint8_t VCP1_Rx_Buffer[];
extern uint32_t VCP1_Rx_ptr_in;
extern uint32_t VCP1_Rx_ptr_out;
extern uint32_t VCP1_Rx_length;
extern uint8_t CDC1_Tx_State;
extern uint8_t VCP2_Rx_Buffer[];
extern uint32_t VCP2_Rx_ptr_in;
extern uint32_t VCP2_Rx_ptr_out;
extern uint32_t VCP2_Rx_length;
extern uint8_t CDC2_Tx_State;
extern uint8_t VCP3_Rx_Buffer[];
extern uint32_t VCP3_Rx_ptr_in;
extern uint32_t VCP3_Rx_ptr_out;
extern uint32_t VCP3_Rx_length;
extern uint8_t CDC3_Tx_State;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* 带参数的宏功能(预编译展开): USB的IN端点 发送数据到PC主机 */
#define EPx_IN_Callback(ENDPx, CDCx_Tx_State, VCPx_Rx_Buffer, VCPx_Rx_ptr_out, VCPx_Rx_length) {\
uint16_t USB_Tx_ptr;\
uint16_t USB_Tx_length;\
if (CDCx_Tx_State == 1) {\
USB_Tx_ptr = VCPx_Rx_ptr_out;\
if (VCPx_Rx_length == 0) {\
CDCx_Tx_State = 0;\
SetEPTxCount(ENDPx,0);\
SetEPTxValid(ENDPx);\
} else {\
if (VCPx_Rx_length > VIRTUAL_COM_PORT_DATA_SIZE) {\
USB_Tx_length = VIRTUAL_COM_PORT_DATA_SIZE;\
VCPx_Rx_ptr_out += VIRTUAL_COM_PORT_DATA_SIZE;\
VCPx_Rx_length -= VIRTUAL_COM_PORT_DATA_SIZE;\
} else {\
USB_Tx_length = VCPx_Rx_length;\
VCPx_Rx_ptr_out += VCPx_Rx_length;\
VCPx_Rx_length = 0;\
}\
USB_SIL_Write(ENDPx, &VCPx_Rx_Buffer[USB_Tx_ptr], USB_Tx_length);\
SetEPTxValid(ENDPx);\
}\
}\
}
/* 带参数的宏功能(预编译展开): USB的OUT端点 通过物理串口向外发送数据(阻塞方式) */
#define EPx_OUT_Callback(ENDPx, USARTx, GPIOx, GPIO_Pin_x) {\
uint32_t i;\
uint16_t USB_Rx_Cnt;\
USB_Rx_Cnt = USB_SIL_Read(ENDPx | 0x00, USB_Rx_Buffer); \
GPIOx->BSRR = GPIO_Pin_x;\
for (i = 0; i < USB_Rx_Cnt; i++) {\
USARTx->DR = *(USB_Rx_Buffer + i);\
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);\
}\
SetEPRxValid(ENDPx);\
while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);\
USART_ClearFlag(USARTx, USART_FLAG_TC);\
GPIOx->BRR = GPIO_Pin_x;\
}
/* 带参数的宏功能(预编译展开): USB的OUT端点 通过物理串口向外发送数据(DMA方式) */
#define EPx_OUT_Callback_DMA(Flag_VCPx_Tx_Buf_Use, ENDPx, VCPx_Tx_Buffer1,VCPx_Tx_Buffer2,\
GPIOx, GPIO_Pin_x, DMA1_Channelx, VCPx_Tx_Buffer_Cnt, Flag_VCPx_Tx_Buf_Full) {\
uint16_t USB_Rx_Cnt;\
if(Flag_VCPx_Tx_Buf_Use == 0){\
USB_Rx_Cnt = GetEPRxCount(ENDPx & 0x7F);\
PMAToUserBufferCopy(&VCPx_Tx_Buffer1[0], GetEPRxAddr(ENDPx & 0x7F), USB_Rx_Cnt);\
SetEPRxValid(ENDPx);\
GPIOx->BSRR = GPIO_Pin_x;\
DMA1_Channelx->CNDTR = USB_Rx_Cnt;\
DMA_Cmd(DMA1_Channelx, ENABLE);\
Flag_VCPx_Tx_Buf_Use = 1;\
VCPx_Tx_Buffer_Cnt = 0;\
} else {\
USB_Rx_Cnt = GetEPRxCount(ENDPx & 0x7F);\
if(VCPx_Tx_Buffer_Cnt < (1024-128)){\
PMAToUserBufferCopy(&VCPx_Tx_Buffer2[VCPx_Tx_Buffer_Cnt], GetEPRxAddr(ENDPx & 0x7F), USB_Rx_Cnt);\
VCPx_Tx_Buffer_Cnt += USB_Rx_Cnt;\
SetEPRxValid(ENDPx);\
} else {\
PMAToUserBufferCopy(&VCPx_Tx_Buffer2[VCPx_Tx_Buffer_Cnt], GetEPRxAddr(ENDPx & 0x7F), USB_Rx_Cnt);\
VCPx_Tx_Buffer_Cnt += USB_Rx_Cnt;\
Flag_VCPx_Tx_Buf_Full = 1;\
}\
}\
}
/*******************************************************************************
* Function Name : EP2_IN_Callback
* Description :
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void EP2_IN_Callback (void) {
EPx_IN_Callback(ENDP2,CDC1_Tx_State,VCP1_Rx_Buffer,VCP1_Rx_ptr_out,VCP1_Rx_length);
}
/*******************************************************************************
* Function Name : EP4_IN_Callback
* Description :
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void EP4_IN_Callback(void)
{
EPx_IN_Callback(ENDP4,CDC2_Tx_State,VCP2_Rx_Buffer,VCP2_Rx_ptr_out,VCP2_Rx_length);
}
/*******************************************************************************
* Function Name : EP6_IN_Callback
* Description : VCP3 向PC主机发送数据
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void EP6_IN_Callback(void)
{
EPx_IN_Callback(ENDP6,CDC3_Tx_State,VCP3_Rx_Buffer,VCP3_Rx_ptr_out,VCP3_Rx_length);
}
/*******************************************************************************
* Function Name : EP2_OUT_Callback
* Description : VCP1 通过USART1向外送数据
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void EP2_OUT_Callback(void) {
#ifdef USB_DMA_SEND
EPx_OUT_Callback_DMA(Flag_VCP1_Tx_Buf_Use, ENDP2, VCP1_Tx_Buffer1,VCP1_Tx_Buffer2,\
GPIOB, GPIO_Pin_9, DMA1_Channel4, VCP1_Tx_Buffer_Cnt, Flag_VCP1_Tx_Buf_Full);
// 使用带参数的宏,可避免书写错误,便于后期维护,测试验证已通过
#else
EPx_OUT_Callback(ENDP2,USART1, GPIOB, GPIO_Pin_9); // DR1 PB9
#endif
}
/*******************************************************************************
* Function Name : EP4_OUT_Callback
* Description : VCP2 通过USART2向外送数据
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void EP4_OUT_Callback(void)
{
#ifdef USB_DMA_SEND
EPx_OUT_Callback_DMA(Flag_VCP2_Tx_Buf_Use, ENDP4, VCP2_Tx_Buffer1,VCP2_Tx_Buffer2,\
GPIOB, GPIO_Pin_8, DMA1_Channel7, VCP2_Tx_Buffer_Cnt, Flag_VCP2_Tx_Buf_Full);
#else
EPx_OUT_Callback(ENDP4,USART2, GPIOB, GPIO_Pin_8); // DR2 PB8
#endif
}
/*******************************************************************************
* Function Name : EP6_OUT_Callback
* Description : VCP3 通过USART3向外送数据
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void EP6_OUT_Callback(void){
#ifdef USB_DMA_SEND
EPx_OUT_Callback_DMA(Flag_VCP3_Tx_Buf_Use, ENDP6, VCP3_Tx_Buffer1,VCP3_Tx_Buffer2,\
GPIOA, GPIO_Pin_5, DMA1_Channel2, VCP3_Tx_Buffer_Cnt, Flag_VCP3_Tx_Buf_Full);
#else
EPx_OUT_Callback(ENDP6,USART3,GPIOA,GPIO_Pin_5); // DR3 PA5
#endif
}
/*******************************************************************************
* Function Name : SOF_Callback / INTR_SOFINTR_Callback
* Description :
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void SOF_Callback(void)
{
static uint32_t FrameCount = 0;
static uint32_t Led_Count = 0;
//uint8_t bitstatus = 0x00;
if (bDeviceState == CONFIGURED) {
if (FrameCount++ >= VCOMPORT_IN_FRAME_INTERVAL) {
/* Reset the frame counter */
FrameCount = 0;
/* Check the data to be sent through IN pipe */
Handle_USBAsynchXfer();
}
}
if (++Led_Count > 999) {
Led_Count = 0;
//bitstatus = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_2);
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_2) == 0) {
GPIOB->BSRR = GPIO_Pin_2; // PB2 H
} else {
GPIOB->BRR = GPIO_Pin_2; // PB2 L
}
}
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |