
STM32的USB中断是1ms执行一次,ST官方的代码并不立即将收到的数据发往USB主机,而是定义了一个接收缓冲,接收缓冲的存在就是避免漏接字符,在回调函数中5ms发送一次数据到USB主机,这个时间间隔使得STM32有足够的时间向USB主机传输数据。RS485的情况需另行考虑。注意这是在STM32中实现超时自动添加换行字符,由于Windows并非实时系统,想要在Windows上位机中实现这个功能,那将是几乎是不可能完成的任务。 在ST官方例程Virtual_COM_Port中增加的函数如下 /******************************************************************************* * Function Name : TIMx_Base_Configration * Description : 定时器基础应用配置 * Input : TIMx,Period,TIM_Prescaler * Output : None. * Return : None. *******************************************************************************/ void TIMx_Base_Configration(TIM_TypeDef* TIMx, uint16_t Period, uint16_t TIM_Prescaler) { // TIM_Prescaler 72 分频则为1M, 计数加1为1us, 7200分频则为10K, 计数加1为100us TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period = Period - 1; // 定时器计时总数,最大65535 TIM_TimeBaseStructure.TIM_Prescaler = TIM_Prescaler - 1; // 定时器预分频 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 定时器时钟输入分频 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式 TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure); // 初始化定时器 TIM_ClearFlag(TIMx, TIM_FLAG_Update); // 清除中断标志 TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE); // 使能定时器中断 TIM_SetCounter(TIMx, 0); // 设置定时器初始值 TIM_Cmd(TIMx, ENABLE); } /* Enable TIM2 clocks */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能定时器2 TIMx_Base_Configration(TIM2, 10, 7200); // 设定周期为1ms /******************************************************************************* * Function Name : EVAL_COM1_IRQHandler * Description : This function handles EVAL_COM1 global interrupt request. * Input : None * Output : None * Return : None *******************************************************************************/ void EVAL_COM1_IRQHandler(void) { if (USART_GetITStatus(EVAL_COM1, USART_IT_RXNE) != RESET) { /* Send the received data to the PC Host*/ USART_To_USB_Send_Data(); /* 最后两个字节为0x0d,0x0a, 这是一个符合微软标准的换行字符 如果最后两个字节不为0x0d,0x0a, 超时1毫秒则自动添加0x0d,0x0a */ last_char[0] = last_char[1]; last_char[1] = USART_Rx_Buffer[USART_Rx_ptr_in-1]; if((last_char[0] == 0x0d)&&(last_char[1] == 0x0a)){ Flag_CR_CN = 0; TIM_Cmd(TIM2, DISABLE); }else{ TIM_SetCounter(TIM2, 0); TIM_Cmd(TIM2, ENABLE); Flag_CR_CN = 1; } } /* If overrun condition occurs, clear the ORE flag and recover communication */ if (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_ORE) != RESET) { (void)USART_ReceiveData(EVAL_COM1); } } /******************************************************************************* * Function Name : TIM2_IRQHandler * Description : This function handles TIM2 global interrupt request. * Input : None * Output : None * Return : None *******************************************************************************/ void TIM2_IRQHandler(void) { TIM_Cmd(TIM2, DISABLE); TIM_ClearITPendingBit(TIM2, TIM_IT_Update); if(Flag_CR_CN){ Flag_CR_CN = 0; USART_Rx_Buffer[USART_Rx_ptr_in] = 0x0d; USART_Rx_ptr_in++; if(USART_Rx_ptr_in == USART_RX_DATA_SIZE) { USART_Rx_ptr_in = 0; } USART_Rx_Buffer[USART_Rx_ptr_in] = 0x0a; USART_Rx_ptr_in++; if(USART_Rx_ptr_in == USART_RX_DATA_SIZE) { USART_Rx_ptr_in = 0; } } } 基于ST官方原版例程Virtual_COM_Port修改,添加智能换行功能 下载地址: ![]() |
最全USB HID开发资料,悉心整理一个月,亲自测试
实战经验 | 选择USBX模块生成USB CDC ACM无PD的项目
STM32 USB HID键盘例程
刘氓兔的杂谈【001】-片上USB 高速PHY
【经验分享】在进行 USB CDC 类开发时,无法发送 64整数倍的数据
【源码】STLINK-V3MINI 高速USB仿真器,成功改刷【高速CMSIS-DAP】
在线直播|无需编写任何代码即可在STM32上实现USB-C Power Delivery
STM32 USB CDC 虚拟多串口
圈圈发布USB图书第二版有感,以及分享一些我学习USB过程...
USB Audio设计与实现
可以,上拉D+为全速设备,上拉D-为低速设备,要作为高速设备使用时,才需要使用三极管控制上拉
回复:【MCU实战经验】+ 利用ST官方STM32_USB-FS-Device_Lib_V4.0.0例程实现USB-TO-TTL232的数据包添加智能换行的功能
将64字节的定义改为63字节,可以解决64字节不响应的bug,以上所有例程都有这个bug
可以解决64字节不响应的bug,以上所有例程都有这个bug