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

【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上位机中实现这个功能,那将是几乎是不可能完成的任务。2 j- |! D/ a$ l! N& ^8 P- g! \
/ t5 e: [& o" F( ]
在ST官方例程Virtual_COM_Port中增加的函数如下; _  `! A  Z2 l' x2 i
/*******************************************************************************. @/ [: N: V' ~) T2 ^" W" f; k
* Function Name  : TIMx_Base_Configration
" q: s+ m* }8 J* Description    : 定时器基础应用配置
* Y9 [5 U5 C- O$ ]* H* Input          : TIMx,Period,TIM_Prescaler
* m# r+ C5 @8 d: c0 @$ {* Output         : None." ?# U/ E: h6 S9 O+ L+ S3 l5 Z4 {; \4 e
* Return         : None.6 F5 h+ x& ]) V/ {/ u1 x7 Q
*******************************************************************************/
8 B, F' D# p6 p' d' Fvoid TIMx_Base_Configration(TIM_TypeDef* TIMx, uint16_t Period, uint16_t TIM_Prescaler)3 w+ j  K5 d& n6 e4 B
{
" D2 b4 c5 a. F% S8 o4 \) C1 N4 A' T0 r    // TIM_Prescaler  72 分频则为1M, 计数加1为1us, 7200分频则为10K, 计数加1为100us$ m1 O% h) Y) v1 K
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
, b# C$ ~/ R6 A, y; d/ O' z% B" T 
, U/ C! h% l" k1 [    TIM_TimeBaseStructure.TIM_Period = Period - 1;                 // 定时器计时总数,最大65535
. W; _; i  X6 q) v* q% T1 i    TIM_TimeBaseStructure.TIM_Prescaler = TIM_Prescaler - 1;       // 定时器预分频0 F* z2 B- H, n4 @4 O1 y6 Q
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;        // 定时器时钟输入分频3 R: W5 E- s: Q2 r) S7 h
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;    // 向上计数模式3 U7 Z" F1 ?% q% p! W: J1 U
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
2 P% w5 R% m' J# h1 k    TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);                // 初始化定时器$ l. H" E/ `. ~' x+ V; I
 
( u& y' J) K) p3 L/ {0 M9 f; _    TIM_ClearFlag(TIMx, TIM_FLAG_Update);                          // 清除中断标志# Z3 H: z( A: k4 ^/ o
    TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE);                   // 使能定时器中断' l# e: T1 n6 k1 D6 e: m  N$ }
 " j1 f7 C; L5 {2 _
    TIM_SetCounter(TIMx, 0);  // 设置定时器初始值
" g* V; [2 ?5 _0 I0 H& r    TIM_Cmd(TIMx, ENABLE); 1 r1 y4 U9 p8 o* f4 w
} ; c" R  ]' y$ I0 J. ]
 6 Z7 t' j- F& Z, o; f* o- B
 
/ a" o: b' [: J  /* Enable TIM2 clocks */
, R& h! \- l9 |5 Q* G, _  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能定时器26 ^1 J, ^- f3 a2 _% [# `) Y& P8 z
  TIMx_Base_Configration(TIM2, 10, 7200);  // 设定周期为1ms0 D2 F# J* `# e# K2 a; O
 2 ?; ]; f3 i3 e8 j9 v
 ( z) `. H8 o+ H: P' h% }8 s
/*******************************************************************************0 w' ?2 D2 u, S, D4 r) Z
* Function Name  : EVAL_COM1_IRQHandler6 R/ v3 t) b) R  b9 j5 q9 ?8 Q
* Description    : This function handles EVAL_COM1 global interrupt request.
3 @1 |9 q5 h3 t( o5 X  c, ?* Input          : None; j& L  W) K# U* {8 x1 i/ a
* Output         : None
) V6 l, {+ q& F2 J9 b2 q+ ?5 p$ o* @" P* Return         : None9 F1 _9 A% g. @) V# K
*******************************************************************************/) P: g4 c  G& V" |
void EVAL_COM1_IRQHandler(void)
8 O; e/ Q1 v0 h4 _{
. E% l/ h, i, T  if (USART_GetITStatus(EVAL_COM1, USART_IT_RXNE) != RESET)
6 r. F  Y6 M$ {) d0 Z  {
/ Q8 w& Y" w% f, U+ u! S    /* Send the received data to the PC Host*/+ }. [! N" e% c5 }$ Z* U
    USART_To_USB_Send_Data();
/ s3 Q$ E0 c9 i+ y* }* k  K: j' X   Y3 [# n- T4 c
    /*
. X2 R+ h, A: G+ U1 D! k' D    最后两个字节为0x0d,0x0a, 这是一个符合微软标准的换行字符
( _* b3 w3 l- F5 y  d    如果最后两个字节不为0x0d,0x0a, 超时1毫秒则自动添加0x0d,0x0a- D" c& Q1 G8 [  L# [
    */
; ~, t) z5 T# V    last_char[0] = last_char[1];4 D% h! s8 T% w8 T# q1 r& p3 m0 ^
    last_char[1] =  USART_Rx_Buffer[USART_Rx_ptr_in-1];* }; \- A7 a0 s0 `) X! ?; i
    if((last_char[0] == 0x0d)&&(last_char[1] == 0x0a)){
  \" _5 O% o! F' _        Flag_CR_CN = 0;' Q3 k) r. l) K0 G) o0 g
        TIM_Cmd(TIM2, DISABLE);
$ e. [# e$ `, R2 U    }else{$ H" J4 h, y1 `% J
        TIM_SetCounter(TIM2, 0);2 Q9 C1 ^1 C4 c5 e
        TIM_Cmd(TIM2, ENABLE);# y3 D' J: p" O6 t, j
        Flag_CR_CN = 1;3 ^' o1 Y! Q0 m/ e
    }: ~* D+ N4 p/ T' C0 N4 C
  }' ?$ D5 U7 H4 x' F# t* W
 
2 h( g# B$ x- F  /* If overrun condition occurs, clear the ORE flag and recover communication */
9 l$ B, S# q4 {- V7 V  if (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_ORE) != RESET)  z% d' \0 D3 ?
  {
9 @' b, J3 N% K5 t# S+ u    (void)USART_ReceiveData(EVAL_COM1);  t0 }0 a; R9 \! R# f& T5 I3 f
  }
( E! A, m3 l0 ?3 F# |( p$ D9 x}
9 {7 v' }0 |' A- _% |! F3 b; w+ b/*******************************************************************************; G  Z. W% f& _: K$ f( D# ^. B* U
* Function Name  : TIM2_IRQHandler & E+ Y8 }, s& C
* Description    : This function handles TIM2 global interrupt request.
) R+ ]6 i7 e' S8 x/ y$ x* Input          : None
9 _6 E& D" ^9 a1 ]% H$ n* Output         : None
  P& w2 f" |6 K5 v$ F* Return         : None
  G( U  r1 N0 s& F+ E: H*******************************************************************************/0 f7 l* }1 B4 ^3 R: B- m" h1 N
 % K( m1 U0 e/ a* K9 C- V' r
 3 h( c3 a: c) n
void TIM2_IRQHandler(void)
8 r# x& b  @) V8 @5 E{
& e  i& ]) O7 c' Z    TIM_Cmd(TIM2, DISABLE);: ~, I" o  ^1 ^" l5 m8 z
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
4 K) }+ B8 [  g: @. h2 H, k    if(Flag_CR_CN){$ b1 w) `( a" C+ ?. N+ h
        Flag_CR_CN = 0;
* t7 g5 T: N5 L  `/ P ! z1 i; Z0 E5 m1 ?
        USART_Rx_Buffer[USART_Rx_ptr_in] = 0x0d;
/ }' d+ V  \9 Z( w+ F5 [        USART_Rx_ptr_in++;
2 `' M# _0 W2 d; z$ y        if(USART_Rx_ptr_in == USART_RX_DATA_SIZE)# f) n( K) W$ P4 N. ^# @7 O" O' C
        {# g  x$ M' B/ r# ^1 E
            USART_Rx_ptr_in = 0;. e9 L8 S) D9 R/ v% y! L
        }% g# ?$ t+ {3 K' ]$ K+ }
        USART_Rx_Buffer[USART_Rx_ptr_in] = 0x0a;
1 t7 _. R% ~8 j        USART_Rx_ptr_in++;
8 [1 h6 q6 Z% b9 H* z        if(USART_Rx_ptr_in == USART_RX_DATA_SIZE); b/ _# s$ d3 a; W9 |; f
        {+ k4 C1 y% h2 i& v; B- |
            USART_Rx_ptr_in = 0;
$ x4 ~' B  e) j. p# @        }
! W6 F$ v2 A( H) d# J* |    }
- Z6 Q/ X" B' X}
: e! o4 Z* M- b* x" U' @5 g* Z' O- r/ }/ W
 9 X# R. a5 l; A/ c+ C% C
基于ST官方原版例程Virtual_COM_Port修改,添加智能换行功能- k# G8 A( D$ l' T# v* S
下载地址:  STM32_USB-FS-Device_Lib_V4.0.0(智能换行).rar (5.65 MB, 下载次数: 6727)
赞 收藏 9 评论17 发布时间:2014-4-16 14:38

举报

17个回答
Aegiss 回答时间:2016-7-27 13:29:58
caizhiwei 发表于 2015-1-19 16:58
7 S. O) K+ y; X/ ?4 N7 N请问楼主D+的1.5K电阻能直接上拉到V3.3吗?不用IO口控制。。。

" w: F( y/ A+ ^% F* C* N可以,上拉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字节,. ]3 Z8 Z& R2 C7 @, \! G3 V" R/ f6 A- A
可以解决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 手机版