|
STM32的USB中断是1ms执行一次,ST官方的代码并不立即将收到的数据发往USB主机,而是定义了一个接收缓冲,接收缓冲的存在就是避免漏接字符,在回调函数中5ms发送一次数据到USB主机,这个时间间隔使得STM32有足够的时间向USB主机传输数据。RS485的情况需另行考虑。注意这是在STM32中实现超时自动添加换行字符,由于Windows并非实时系统,想要在Windows上位机中实现这个功能,那将是几乎是不可能完成的任务。9 E: |- k" Y9 n' l! ^ 在ST官方例程Virtual_COM_Port中增加的函数如下 /*******************************************************************************$ B/ `! V& N. P/ q * Function Name : TIMx_Base_Configration/ ~4 |9 l2 S9 ?2 g9 r f# L0 T) \4 u$ K * Description : 定时器基础应用配置 * Input : TIMx,Period,TIM_Prescaler' T- @; _; f! [% Q9 F9 h) b * Output : None. * Return : None.7 z- H5 ]4 B/ V, P" @2 z: Y *******************************************************************************/ 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;0 {4 T( k$ i! i U1 [ TIM_TimeBaseStructure.TIM_Period = Period - 1; // 定时器计时总数,最大655355 y2 |7 v& q2 P1 c/ {1 f% { TIM_TimeBaseStructure.TIM_Prescaler = TIM_Prescaler - 1; // 定时器预分频 o+ m9 V/ ]% F/ }$ m0 Z TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 定时器时钟输入分频 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式8 n/ i6 e: N- a" b# } TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure); // 初始化定时器& V- P6 D# \9 o+ c " ]: `: h5 E ]7 } TIM_ClearFlag(TIMx, TIM_FLAG_Update); // 清除中断标志 TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE); // 使能定时器中断9 c! u+ t. Y9 u4 \- L TIM_SetCounter(TIMx, 0); // 设置定时器初始值 TIM_Cmd(TIMx, ENABLE); " X" E) X3 r4 @6 e! }* H5 b } /* Enable TIM2 clocks */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能定时器2 TIMx_Base_Configration(TIM2, 10, 7200); // 设定周期为1ms$ Q5 s' Y' _2 b" w- z /*******************************************************************************8 o2 f4 C. t) Q * Function Name : EVAL_COM1_IRQHandler * Description : This function handles EVAL_COM1 global interrupt request. * Input : None * Output : None * Return : None2 R: x8 {$ x9 P% n4 {, O4 ? *******************************************************************************/ void EVAL_COM1_IRQHandler(void)( |, }$ F/ d5 M: j {; {; Y- [! R8 |6 { if (USART_GetITStatus(EVAL_COM1, USART_IT_RXNE) != RESET)& e; Y2 O" C" K8 T { /* Send the received data to the PC Host*/ USART_To_USB_Send_Data(); /*( R3 j i' V v7 X 最后两个字节为0x0d,0x0a, 这是一个符合微软标准的换行字符 如果最后两个字节不为0x0d,0x0a, 超时1毫秒则自动添加0x0d,0x0a* |. u1 u9 v& s */( v9 ]/ J( l/ X8 t) y. D 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)){6 w, Z { { i Flag_CR_CN = 0; TIM_Cmd(TIM2, DISABLE);: `" g) @. T1 y8 b! E$ |- E }else{ TIM_SetCounter(TIM2, 0);' {4 \5 Q; n& T. V+ ` TIM_Cmd(TIM2, ENABLE); Flag_CR_CN = 1;5 c5 `5 ?: y/ C: Y } }8 U$ h/ c) X6 K, t 1 H" w5 ]2 V; z" ~) L /* If overrun condition occurs, clear the ORE flag and recover communication */3 n, U& k8 A0 J if (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_ORE) != RESET)0 a& d g$ l/ k1 t; j {% e) J; w: a4 L0 i/ c (void)USART_ReceiveData(EVAL_COM1); }- P& h$ Y Z3 r$ | }* ^- v; m* n4 Q5 |8 z /*******************************************************************************( Z0 h3 w2 o; v' T4 W4 n * Function Name : TIM2_IRQHandler * Description : This function handles TIM2 global interrupt request.# E0 S2 [' D0 I4 _ * Input : None8 d: x- W# p: I& a * Output : None9 G- P- b, A8 D0 S) `4 M$ a * Return : None4 w9 M4 A& ~0 R5 j Y& C *******************************************************************************/ ! r G q1 Q. |. D' r, y void TIM2_IRQHandler(void) {7 [7 P; A8 H- R4 m* P TIM_Cmd(TIM2, DISABLE); TIM_ClearITPendingBit(TIM2, TIM_IT_Update); if(Flag_CR_CN){+ m7 `8 i7 [5 W" n Flag_CR_CN = 0;7 x- L/ x4 W! N0 t & c. }. |0 D+ a4 H5 x" ? USART_Rx_Buffer[USART_Rx_ptr_in] = 0x0d;# J1 J8 c! V6 t+ O USART_Rx_ptr_in++;1 ], M! i7 f. N: S if(USART_Rx_ptr_in == USART_RX_DATA_SIZE) {5 k+ v7 z3 d( \3 c0 {$ A 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) {' U; z/ r1 T8 u: ]$ Q USART_Rx_ptr_in = 0;1 l3 I; ?: H m% B5 k' M } } } + W) _$ a- y. @( v, j1 b9 s 基于ST官方原版例程Virtual_COM_Port修改,添加智能换行功能 下载地址:
STM32_USB-FS-Device_Lib_V4.0.0(æºè½æ¢è¡).rar
(5.65 MB, 下载次数: 6727)
|
最全USB HID开发资料,悉心整理一个月,亲自测试
【源码】STLINK-V3MINI 高速USB仿真器,成功改刷【高速CMSIS-DAP】
STM32 USB CDC 虚拟多串口
实战经验 | 选择USBX模块生成USB CDC ACM无PD的项目
STM32 USB HID键盘例程
刘氓兔的杂谈【001】-片上USB 高速PHY
【经验分享】在进行 USB CDC 类开发时,无法发送 64整数倍的数据
在线直播|无需编写任何代码即可在STM32上实现USB-C Power Delivery
圈圈发布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