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

【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上位机中实现这个功能,那将是几乎是不可能完成的任务。: g! r8 P: g' d% I' \
( `/ ]( U1 y, }
在ST官方例程Virtual_COM_Port中增加的函数如下7 a1 s7 j& P. ?: G# j  e
/*******************************************************************************# |% C1 w/ M* j7 `5 F) q5 y' p
* Function Name  : TIMx_Base_Configration; t* Q: d: ]* b
* Description    : 定时器基础应用配置
3 E/ u3 U% N& g  f9 v8 e6 ~- z* Input          : TIMx,Period,TIM_Prescaler! e3 X* ?6 W! n( S# _
* Output         : None.
0 n8 x7 \, v! x" i) U1 o1 I& ?* Return         : None.+ P, d$ x* W$ |2 Y, E1 a* }
*******************************************************************************/# @3 t5 Z1 M& n9 @, \) A" N
void TIMx_Base_Configration(TIM_TypeDef* TIMx, uint16_t Period, uint16_t TIM_Prescaler)$ C* r2 T8 Z' m- j7 ?
{3 }2 o; @3 u4 F  c+ _# b
    // TIM_Prescaler  72 分频则为1M, 计数加1为1us, 7200分频则为10K, 计数加1为100us
# s$ f$ \7 h( n) e% p4 {, Y    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;, o$ I# s. [6 P0 j7 M! V+ X" J
 
- U2 v- G- M* \; z5 n    TIM_TimeBaseStructure.TIM_Period = Period - 1;                 // 定时器计时总数,最大65535
& K/ k* m3 D* Y+ {6 h: T* c0 a    TIM_TimeBaseStructure.TIM_Prescaler = TIM_Prescaler - 1;       // 定时器预分频
- C0 s2 S# n% o$ ?- X+ H' T    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;        // 定时器时钟输入分频& }$ q: K$ G% s4 V. T
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;    // 向上计数模式
! D& m' J. G# ]# J' X$ Z    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
* H* F: ^0 ?' s7 T    TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);                // 初始化定时器% s! h+ ^& b. S. E
 - S! y- y1 O5 M9 t3 v" N9 Z3 U# v0 ^5 w
    TIM_ClearFlag(TIMx, TIM_FLAG_Update);                          // 清除中断标志) z2 l) v( {5 D) e# d- F# S, ~
    TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE);                   // 使能定时器中断
. L2 e4 a9 Q2 u# r( m! z# _ 
# E8 s4 g# @: L, W. I0 z8 h) G/ k    TIM_SetCounter(TIMx, 0);  // 设置定时器初始值6 l2 t; Z* m3 f" j2 ~, q. }5 F
    TIM_Cmd(TIMx, ENABLE); 
- N8 D8 X- B7 P, x6 v) n
2 \& D8 Z0 R1 ~& } 
. B# m; d( ?5 @; }2 u/ u 
  l2 x* ^7 G3 X4 i( H) S: U. b  /* Enable TIM2 clocks */
- {; r/ Z3 u4 U4 Y% Q% d+ [  p  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能定时器2* O, L9 D+ L& q- j, Y8 E$ d* q/ T
  TIMx_Base_Configration(TIM2, 10, 7200);  // 设定周期为1ms
1 Y4 Y( b( G1 l+ E8 y 
0 D" A7 |$ j' u% o 
; @' d1 ]0 w8 m1 e7 ]/*******************************************************************************- h9 V5 A6 A/ |1 g6 m
* Function Name  : EVAL_COM1_IRQHandler
  W0 H; r" k0 [6 ?* Description    : This function handles EVAL_COM1 global interrupt request.1 ^$ l4 @$ N3 V5 `
* Input          : None
9 Y/ R# q1 e( f) Z* Output         : None
7 E1 l) p. `/ w$ @  J2 f* Return         : None# F8 C$ |( Z3 u; {2 d
*******************************************************************************/
9 a0 A. Q! U. \& A5 ]void EVAL_COM1_IRQHandler(void)
' R- ?) L; Z8 |{0 N) `0 |6 {2 }) C- M) E4 |* L
  if (USART_GetITStatus(EVAL_COM1, USART_IT_RXNE) != RESET)
+ g) ]' d$ P# w* F9 z% G. A: k  {$ ~1 f: ~0 A: ^8 V* j. f
    /* Send the received data to the PC Host*/
, g. R/ ?. ~2 x  b3 U8 ^- v    USART_To_USB_Send_Data();
& m1 V% P4 e4 b( u 
, M. l5 \  U* N    /** H  t( L% u7 w( P
    最后两个字节为0x0d,0x0a, 这是一个符合微软标准的换行字符
: ^  q+ U7 m# G8 F    如果最后两个字节不为0x0d,0x0a, 超时1毫秒则自动添加0x0d,0x0a+ v- K! v+ ?  A# V6 l- r- \! Z' [2 O
    */
: O8 E' m& B6 z- x# Y5 v3 ~    last_char[0] = last_char[1];8 H+ F# _: M0 N; H
    last_char[1] =  USART_Rx_Buffer[USART_Rx_ptr_in-1];% v+ X7 H2 l& _% g* c4 N
    if((last_char[0] == 0x0d)&&(last_char[1] == 0x0a)){
; x+ i) L3 E" `. Y2 {, i$ G        Flag_CR_CN = 0;- Q' b: V( a1 I
        TIM_Cmd(TIM2, DISABLE);4 a2 k( i/ U# \5 R2 Z9 y) w
    }else{
' q/ K  o3 f: ]" |1 U* d! T        TIM_SetCounter(TIM2, 0);0 `! ^7 y% F  o# N8 v, }6 d" A
        TIM_Cmd(TIM2, ENABLE);
3 ?) C/ I# a- u9 I* X. j        Flag_CR_CN = 1;5 Z! Y( g; }. T1 I% U2 V0 f
    }' B; n) y, x3 w2 K7 S
  }
8 d& S7 l" a, w/ {# K" g" q; [ 0 _+ b3 n) D2 f9 s" n3 c
  /* If overrun condition occurs, clear the ORE flag and recover communication */
3 B# ~% J# {- J1 r, p  if (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_ORE) != RESET)/ H/ d& ]2 C! W; \4 s2 `
  {/ {& V9 ]6 Z3 p) U1 L
    (void)USART_ReceiveData(EVAL_COM1);
: j" _, v( \) K" s4 e9 ?  }9 B1 M; n. g6 O+ O, @) a! T
}: s' t' I/ a: V( |5 h$ ^( F1 n# g- e
/*******************************************************************************
; J$ N/ T; B; \1 n* Function Name  : TIM2_IRQHandler % C, D, N2 P% M) p( U
* Description    : This function handles TIM2 global interrupt request.* t8 c# G. v9 W1 r5 @2 K, Z$ V; V
* Input          : None4 }% |6 I$ q" a# y( e3 S0 O  ^2 R
* Output         : None
7 n; Z9 S6 b1 |6 ~1 m$ D* Return         : None
# t: \) i. M$ s  R, S0 a1 Z*******************************************************************************/
  T0 u9 M& b& j3 @0 r7 u& ^- {, u 
( b) _) l( y! I# b4 m: g$ J 
, J* Z( j$ {! k; Y: Q3 g/ l6 Pvoid TIM2_IRQHandler(void)
: i4 Z+ i' i" |" S1 i{
4 Q& Y1 ]4 K8 e8 }6 q    TIM_Cmd(TIM2, DISABLE);/ c. o* R- P7 w; P0 F* r
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);0 C0 j) F" J# {" a3 R1 g; ]
    if(Flag_CR_CN){
0 d3 ^5 b4 _; `; L        Flag_CR_CN = 0;" P) `9 M+ i3 o; A: F
 
$ w4 X4 x; m2 o+ ^7 X6 r$ n        USART_Rx_Buffer[USART_Rx_ptr_in] = 0x0d;
9 N- v- x& }+ K8 [1 @6 G/ J2 I9 a2 e        USART_Rx_ptr_in++;7 z- s. i) H# m# [0 \! ?
        if(USART_Rx_ptr_in == USART_RX_DATA_SIZE)+ W- J6 t- K. u2 P# H- z% }) G
        {( y2 K4 ~( [# S, y: e( P* y3 l% Q
            USART_Rx_ptr_in = 0;8 @  ]. }+ G/ c9 j2 w
        }
, I& B& i! \# r# w# z8 X6 F( K        USART_Rx_Buffer[USART_Rx_ptr_in] = 0x0a;& N% [& X0 s1 [+ {$ [8 X. V
        USART_Rx_ptr_in++;0 u2 M& C* ~; V. Z( I1 G( {0 ~
        if(USART_Rx_ptr_in == USART_RX_DATA_SIZE)
" |( ]9 K5 i5 [8 M' l        {
. L9 K9 I" D3 ?& \            USART_Rx_ptr_in = 0;+ g% F4 g4 ?0 j- M
        }8 O+ d- [6 z2 z& a* Q/ o+ ~
    }1 P/ [, r4 i1 w0 k1 }% P# P. ?
}7 o) V/ p; [! r
: w& ^; @/ x. [0 D2 h& N% K3 y
 + L1 p) Q2 i- q% ?3 _4 L. ^* v# N
基于ST官方原版例程Virtual_COM_Port修改,添加智能换行功能
; V; K* \9 ]) o8 U7 F5 [下载地址  STM32_USB-FS-Device_Lib_V4.0.0(智能换行).rar (5.65 MB, 下载次数: 6726)
收藏 9 评论17 发布时间:2014-4-16 14:38

举报

17个回答
Aegiss 回答时间:2016-7-27 13:29:58
caizhiwei 发表于 2015-1-19 16:58
* l* f" M' _- U请问楼主D+的1.5K电阻能直接上拉到V3.3吗?不用IO口控制。。。

: X8 {6 z5 z; @: y* x' I  b可以,上拉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字节,: ^5 T+ i* {" c3 d, s
可以解决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管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版