你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【MCU实战经验】+ 利用ST官方STM32_USB-FS-Device_Lib_V4.0.0例程实现USB-TO-TTL232的数据包添加智能换行的功能。  

[复制链接]
wjandsq 发布时间:2014-4-16 14:38
STM32的USB中断是1ms执行一次,ST官方的代码并不立即将收到的数据发往USB主机,而是定义了一个接收缓冲,接收缓冲的存在就是避免漏接字符,在回调函数中5ms发送一次数据到USB主机,这个时间间隔使得STM32有足够的时间USB主机传输数据。RS485的情况需另行考虑。注意这是在STM32中实现超时自动添加换行字符,由于Windows并非实时系统,想要在Windows上位机中实现这个功能,那将是几乎是不可能完成的任务。
- J* ?* {1 {, ]9 e* y: b! h: h0 ~1 r1 o, x
在ST官方例程Virtual_COM_Port中增加的函数如下
5 f* h/ H9 n+ V$ |0 h/*******************************************************************************
3 w/ d1 I8 J! U  z% ~* Function Name  : TIMx_Base_Configration: k# D) D$ @0 X+ u9 H4 ]) l) A! p( d
* Description    : 定时器基础应用配置
# h- @9 J* P, C, r, H" d7 P, o' P4 `2 ]( A* Input          : TIMx,Period,TIM_Prescaler. E1 T9 U9 t  w5 `- C
* Output         : None.5 X) u+ C# E- v# I8 B' [
* Return         : None./ P; ^7 P! S$ S
*******************************************************************************/
- t$ o- a- |) Q8 }5 uvoid TIMx_Base_Configration(TIM_TypeDef* TIMx, uint16_t Period, uint16_t TIM_Prescaler)
9 b8 }6 R+ w- B. M{
; f+ v% f2 T. _  `+ D, l    // TIM_Prescaler  72 分频则为1M, 计数加1为1us, 7200分频则为10K, 计数加1为100us- V! V5 L4 n8 L$ G
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
7 J$ H5 u  [3 g/ |& q( z5 |( {& o, y / Q0 Z2 [: J  @6 P) S# K; A
    TIM_TimeBaseStructure.TIM_Period = Period - 1;                 // 定时器计时总数,最大655353 l1 N( ^1 l5 u; T0 j$ A7 J
    TIM_TimeBaseStructure.TIM_Prescaler = TIM_Prescaler - 1;       // 定时器预分频
0 Q4 x' F0 t- l- r    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;        // 定时器时钟输入分频: m) t& K/ j  H8 w. {
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;    // 向上计数模式
4 T3 |0 O- G4 d& K+ r    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;2 [' B4 |0 t2 e; P5 P  \2 T
    TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);                // 初始化定时器) W2 g6 K2 Z3 W! e9 [+ O( H" C9 C, t. C
 
2 X8 V1 i7 f8 `! J! o' t$ C    TIM_ClearFlag(TIMx, TIM_FLAG_Update);                          // 清除中断标志
5 @2 L" k" r$ H6 T' C2 @; M8 p    TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE);                   // 使能定时器中断4 t+ K, w9 z. U1 O) u. x$ ]
 $ r# K9 p2 r6 ~7 P9 t
    TIM_SetCounter(TIMx, 0);  // 设置定时器初始值1 n  Y1 z! z6 o
    TIM_Cmd(TIMx, ENABLE); 5 v/ Y! Q$ Z8 ~: o( M

! U$ i1 z3 g& g & R5 H; g( K: ?' S
 % i0 R5 {1 t  v8 P/ t8 P
  /* Enable TIM2 clocks */
2 F6 i2 F% i3 |; Y/ e0 c. B  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能定时器2
4 l; u' ~6 G0 s" i  TIMx_Base_Configration(TIM2, 10, 7200);  // 设定周期为1ms7 a% e# u3 D+ P" x
 
+ f: ^0 `$ o! V0 I$ i 
7 t9 C  p) O3 J  D1 z" A* ?/*******************************************************************************
) d8 U9 F9 B5 v  A+ u* Function Name  : EVAL_COM1_IRQHandler, G, ^# m, p# B5 h+ k1 R, I8 A
* Description    : This function handles EVAL_COM1 global interrupt request.
2 X7 U# g2 C& G* Input          : None& Y0 N; m. S( {, t) h
* Output         : None' p+ z- I" f+ P- r, O
* Return         : None: |5 g# `$ i8 c0 J
*******************************************************************************/' m  U9 ]/ |7 a6 ?* i# o
void EVAL_COM1_IRQHandler(void)
5 i5 s6 ~3 c7 s! j, w% ?. K# V{
3 J) ~' ~0 n( @* H9 R. L5 K  if (USART_GetITStatus(EVAL_COM1, USART_IT_RXNE) != RESET)- L- U6 w, n2 e4 U
  {; u- _% ^# u5 P; G
    /* Send the received data to the PC Host*/
* n! R" f6 f" ^7 f    USART_To_USB_Send_Data();/ K/ B( C0 O! P$ `; Q1 E2 B# V$ T
 
. R$ G- c' Y# f6 a    /*
( D$ a: R, [2 a2 x* u* V/ I" r: T    最后两个字节为0x0d,0x0a, 这是一个符合微软标准的换行字符5 M: l/ F9 ^% y& c! N# _
    如果最后两个字节不为0x0d,0x0a, 超时1毫秒则自动添加0x0d,0x0a
& u) C! |+ _* Y" D5 l! B    */
) {& B& h' D% d$ Q1 p4 ]    last_char[0] = last_char[1];& ?  Z' G! v) d! `. @
    last_char[1] =  USART_Rx_Buffer[USART_Rx_ptr_in-1];
  P4 N0 [4 ]4 t! u7 q    if((last_char[0] == 0x0d)&&(last_char[1] == 0x0a)){
8 Z. B! k0 T' m1 `6 x: J        Flag_CR_CN = 0;% }8 [& `: u3 Z1 Y4 t
        TIM_Cmd(TIM2, DISABLE);  ]' R. ^9 f3 N, a. c
    }else{
9 l. Z/ T# n( C/ [        TIM_SetCounter(TIM2, 0);  A$ [" @& b9 Y- \# C& x  L
        TIM_Cmd(TIM2, ENABLE);' w) q6 K- {, C' P+ m0 q
        Flag_CR_CN = 1;
* a; L  S0 n3 \1 T    }- a6 _1 R9 ~" G2 l3 `
  }
. n2 F) H, Y; `9 v& W; i% T 
9 F6 o1 e- X9 f! j% p& r$ s( L+ _  /* If overrun condition occurs, clear the ORE flag and recover communication */# x6 M2 }& ?, d7 }  z( e
  if (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_ORE) != RESET)
7 g8 G. ?( W* U' A2 }, C& v) F  {
/ v' t' n. G' @  H+ Z7 n- M- _    (void)USART_ReceiveData(EVAL_COM1);& p4 T2 w1 U, r8 H) Z& m" H
  }# k: o! I& b* j4 u/ k
}
, g2 ^" w) I% x/*******************************************************************************
1 X) f" M2 l/ Z1 [  {* B4 I$ Q* Function Name  : TIM2_IRQHandler 9 c  g8 Z, Y0 \  P4 n% e/ {& a
* Description    : This function handles TIM2 global interrupt request.
. ]( O4 w* W, v* Input          : None! U) ?2 {2 Z2 P5 v: i
* Output         : None7 \  w$ L; y; m, W/ g( M0 x$ X6 \
* Return         : None# ?: O9 Y" [7 C0 T' c6 a4 Z
*******************************************************************************/% r! V' G. G) l. j
 
& L5 K  Q9 ^; M. D 
" S* X9 U( h5 J6 M" Yvoid TIM2_IRQHandler(void)
) M: D2 H2 O  o7 @4 H/ O" F1 ~{
. r, X% h) @' |+ T    TIM_Cmd(TIM2, DISABLE);
9 f" E- R8 L4 x  j2 ]    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);* ~$ T& e  R3 g# K8 F9 x  i4 Z
    if(Flag_CR_CN){2 q9 f* c+ e: G$ B& U( V! h: w
        Flag_CR_CN = 0;1 n. J+ l1 X& F
 
, e9 L5 S$ ?0 E" Y+ T9 Q8 e        USART_Rx_Buffer[USART_Rx_ptr_in] = 0x0d;1 }3 e5 `+ k; J) _
        USART_Rx_ptr_in++;' M* Q* y+ M) S4 [/ j. D
        if(USART_Rx_ptr_in == USART_RX_DATA_SIZE)
8 B# j4 J- @: v$ f9 \  T3 O0 q        {' q$ S' |  }' T# f, P, w. ~
            USART_Rx_ptr_in = 0;! ~8 M: L4 K; i$ o
        }) }( v; M  O1 Y  s
        USART_Rx_Buffer[USART_Rx_ptr_in] = 0x0a;
+ S1 {& ~7 u6 P5 I! i        USART_Rx_ptr_in++;
  M; g& E4 A4 d+ ]! B7 Q        if(USART_Rx_ptr_in == USART_RX_DATA_SIZE)5 H" y) \2 }& O, C
        {
* u" d# L4 M, R" J8 J            USART_Rx_ptr_in = 0;
- j2 K4 ~6 U- s$ S& W  t        }" Q( Z# C7 I1 s+ B9 i' s
    }
. S& c% s# s- y5 Y7 E}$ F7 c# d, o7 ?! W3 ]( W8 O: \

9 t2 P/ b) b/ X% f7 L 1 D; c1 \) v, t1 Z6 ?2 h& f
基于ST官方原版例程Virtual_COM_Port修改,添加智能换行功能5 J$ k8 J# H" e% ]: r7 `
下载地址  STM32_USB-FS-Device_Lib_V4.0.0(智能换行).rar (5.65 MB, 下载次数: 6567)
收藏 9 评论17 发布时间:2014-4-16 14:38

举报

17个回答
Aegiss 回答时间:2016-7-27 13:29:58
caizhiwei 发表于 2015-1-19 16:58+ ^# a! [) F! Q2 \/ h/ Z8 Q
请问楼主D+的1.5K电阻能直接上拉到V3.3吗?不用IO口控制。。。

! Z! n7 |5 Z; Y  h7 {- Y可以,上拉D+为全速设备,上拉D-为低速设备,要作为高速设备使用时,才需要使用三极管控制上拉
fafa1 回答时间:2017-3-3 10:54:12
在研究一个使用STM32F101接收扫描枪输入的东西,学习一下,谢谢分享!
caizhiwei 回答时间:2015-1-19 16:58:12
请问楼主D+的1.5K电阻能直接上拉到V3.3吗?不用IO口控制。。。
tianyu22 回答时间:2014-9-17 23:34:01

回复:【MCU实战经验】+ 利用ST官方STM32_USB-FS-Device_Lib_V4.0.0例程实现USB-TO-TTL232的数据包添加智能换行的功能

我也在搞虚拟串口。。。老出问题。。。想找个新点的库
wjandsq 回答时间:2014-9-18 18:08:10

将64字节的定义改为63字节,可以解决64字节不响应的bug,以上所有例程都有这个bug

将USB通讯数据包64字节大小的定义改为63字节,
! f1 J+ |) c5 P可以解决64字节不响应的bug,以上所有例程都有这个bug
zhangkun2609 回答时间:2015-7-7 18:06:13
good
风之谷-2040681 回答时间:2016-1-28 09:31:02
谢谢楼主分享
alft 回答时间:2016-5-23 09:25:19
大爱楼主!!!!!!
一叶清风 回答时间:2017-9-9 15:33:27
谢谢
ToDo 回答时间:2017-12-20 21:14:33
謝謝樓主!最近也想嘗試STM的HID
路平 回答时间:2018-4-27 10:53:17
学习中
xheng 回答时间:2018-4-28 10:10:30
非常感谢了。
静水-394928 回答时间:2018-5-22 17:27:31
学习一下,不错的资源
a914002128 回答时间:2018-7-16 13:44:02
mask!!!!
12下一页

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版