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

【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上位机中实现这个功能,那将是几乎是不可能完成的任务。  S  {7 Y* d% L7 `2 l
5 k- B8 U! e- [# M, B! O  X* S
在ST官方例程Virtual_COM_Port中增加的函数如下9 w1 G* Q+ R  m; |6 R: j
/*******************************************************************************
( D% A& O9 n" Y- C" J* Function Name  : TIMx_Base_Configration
& t, o' D; V: V; i/ b+ R* Description    : 定时器基础应用配置
+ }5 J% b' d  o5 i3 f1 Y* Input          : TIMx,Period,TIM_Prescaler+ b, f* p; ^1 |8 Y. A
* Output         : None.
0 l4 S1 {, g) `+ o# L3 H$ ?0 }& y* Return         : None.
, _/ n( q6 m: J*******************************************************************************/6 M0 \, S# b3 c& P1 _
void TIMx_Base_Configration(TIM_TypeDef* TIMx, uint16_t Period, uint16_t TIM_Prescaler)( f7 l; M+ x9 M3 U. F- B, g1 V
{$ e3 j: l* L9 c( s- |
    // TIM_Prescaler  72 分频则为1M, 计数加1为1us, 7200分频则为10K, 计数加1为100us) [8 u4 p' k) @
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
, P6 o0 {$ z# |- s , Q& V' b4 r; W# v9 L6 ~6 n3 P1 z
    TIM_TimeBaseStructure.TIM_Period = Period - 1;                 // 定时器计时总数,最大65535
) C( N' h% R% W0 j    TIM_TimeBaseStructure.TIM_Prescaler = TIM_Prescaler - 1;       // 定时器预分频5 u; {: c1 Q4 m! m3 M$ C
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;        // 定时器时钟输入分频
2 s$ b5 R$ t2 j2 M) J, B    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;    // 向上计数模式& J6 ?# [& j7 S: W3 j
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;: C& {# U- F" c& L0 H( r  \
    TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);                // 初始化定时器
. ^+ M) Y# |2 \$ M7 v# C 
1 n( R4 Y0 O9 G  @0 E    TIM_ClearFlag(TIMx, TIM_FLAG_Update);                          // 清除中断标志; u' f& ~& @3 p
    TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE);                   // 使能定时器中断
+ ]* H# X" i' D+ | 3 ]# n9 G+ x' l  g9 a1 _* S
    TIM_SetCounter(TIMx, 0);  // 设置定时器初始值
3 k" H' ]$ k9 r, }. B+ \7 r    TIM_Cmd(TIMx, ENABLE); / z. p9 |5 `2 B) B9 l

4 I9 j" k! S# e& z1 N9 S" E, Z# i & l4 X& s! _3 h4 w  j
 
5 r3 A! s* h  r5 R9 a  /* Enable TIM2 clocks */
8 r( V$ c! F3 s# R& `  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能定时器2; H, b6 f- X$ G: T
  TIMx_Base_Configration(TIM2, 10, 7200);  // 设定周期为1ms
6 n0 ]0 F3 C' L. X. a" j7 y* x 
3 {5 z" [, P2 p) R" g$ | ' p! h5 l1 P0 m4 p2 F2 o6 d
/*******************************************************************************
8 H, h2 O; f8 u. b+ ^* Function Name  : EVAL_COM1_IRQHandler; B9 K# C9 L( U) r) B, M5 D
* Description    : This function handles EVAL_COM1 global interrupt request.0 o, F. V' G& s% G& c& a" ~
* Input          : None$ h3 y8 B, S3 U* ?
* Output         : None
" Y3 ?4 j) U# c5 o* Return         : None
5 ]* h* w4 l* c- Q" x8 `7 z+ b' }*******************************************************************************/
6 X* O6 I, U8 h3 j4 {, Nvoid EVAL_COM1_IRQHandler(void)
; F( R6 P( p( a8 V{
; Q& e: C0 A* w, [  if (USART_GetITStatus(EVAL_COM1, USART_IT_RXNE) != RESET)3 l* L/ X2 U) q/ K! k& V) d
  {
- H7 f0 Z4 I, p& z    /* Send the received data to the PC Host*/
; g) }7 v# j. ?% ]2 ?6 _    USART_To_USB_Send_Data();! ^' o9 @! f7 C7 x1 d& O, b; A
 , G1 C6 ^8 D& B
    /*' V+ G+ @6 ~0 b) _5 A
    最后两个字节为0x0d,0x0a, 这是一个符合微软标准的换行字符
/ O) m$ L/ l% e: M4 o    如果最后两个字节不为0x0d,0x0a, 超时1毫秒则自动添加0x0d,0x0a
5 ?  N7 b  g! N* R) `7 e) W8 b    */
7 U) ^6 M6 O6 G    last_char[0] = last_char[1];
) H1 V' n1 K' ~    last_char[1] =  USART_Rx_Buffer[USART_Rx_ptr_in-1];
& \" L. A3 f4 p    if((last_char[0] == 0x0d)&&(last_char[1] == 0x0a)){
! w1 q/ }  `. A, d: ?( @        Flag_CR_CN = 0;: ]1 m# M$ \5 l# _! m. t2 }
        TIM_Cmd(TIM2, DISABLE);
# i# Y# l" g( N4 Y3 c- _8 M    }else{, s2 J; R. l0 k9 k+ v' {5 q
        TIM_SetCounter(TIM2, 0);
: t% }( W# W0 ]        TIM_Cmd(TIM2, ENABLE);
, Z* J% u% v4 ^& S' H  f' t/ f        Flag_CR_CN = 1;
7 ]1 A( \/ U! y) a6 ~( ?, O  M* w    }, W; b1 ~: U$ A: A2 a5 \
  }
' O$ U/ T* D( s  O" ]+ |) F 3 o' X# i! r% D
  /* If overrun condition occurs, clear the ORE flag and recover communication */
; A8 V  D9 R: r* Q. \  if (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_ORE) != RESET)8 Y6 e. C& V# V, Y) ~& _! X4 W* Q' `
  {
* z' r$ ]9 A. M' E% a3 |    (void)USART_ReceiveData(EVAL_COM1);0 I4 ?6 `( K8 |3 Z# v5 g
  }1 c) s0 J: z4 S6 N: |1 w$ l6 V- v/ `
}
6 W, G6 z( f, S/ l4 A1 D/*******************************************************************************0 `3 q+ }3 T  x) W2 i
* Function Name  : TIM2_IRQHandler 
, F* B+ t* H0 j  w7 d, s* Description    : This function handles TIM2 global interrupt request.. v0 x( D( f& [0 Y2 v# l! o! R! g/ H# {
* Input          : None
8 h) h, h! b% _! [* Output         : None
9 A+ E: r& N5 _. W. j* Return         : None0 D2 o) c& j4 f
*******************************************************************************/# W' |; k7 {- `% n; j
 % P0 l, g7 n/ c1 U3 v# W
 
5 c: p! k( V. O9 }% V# _8 Mvoid TIM2_IRQHandler(void)3 I  d' q9 b- P4 q
{. V  K0 A1 U4 R6 D
    TIM_Cmd(TIM2, DISABLE);. v: R# t, {; Y) ?
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
! E9 v* F4 ]7 @2 z6 }    if(Flag_CR_CN){+ |$ V0 N. T3 G6 j& V+ a: \$ i
        Flag_CR_CN = 0;
0 T$ M% _: S$ A) C7 t 8 I* ^- i5 ~) {1 _
        USART_Rx_Buffer[USART_Rx_ptr_in] = 0x0d;0 x& F* @% W! [, d- M9 x) c& b
        USART_Rx_ptr_in++;4 Z* s4 D) r* J4 [6 `8 N( ~
        if(USART_Rx_ptr_in == USART_RX_DATA_SIZE)9 R7 s  N6 i  B( o* u
        {0 V9 n6 K2 m: r+ |( M6 w+ H
            USART_Rx_ptr_in = 0;
" h9 D9 e9 N* @1 }# f( w        }' q+ G- r3 i( W1 C+ `
        USART_Rx_Buffer[USART_Rx_ptr_in] = 0x0a;
* G: G( Y0 H# [( r* |: D2 L, @3 {) y        USART_Rx_ptr_in++;9 l- R/ I* k; Y! y( O
        if(USART_Rx_ptr_in == USART_RX_DATA_SIZE), q' [2 \, Q! v0 A
        {& V# a' |' t8 I% ]$ r: [8 \; W( U
            USART_Rx_ptr_in = 0;: x& X6 d) N1 ]4 _: b
        }
( c2 l6 @( V& `: ^    }& K3 E7 ]9 x5 f0 @- N( r/ I
}
3 W, P8 O7 F: N; J' F0 `& V# k; ?8 c# J
 
4 X9 ~. t) d) V: i+ p3 Y+ K基于ST官方原版例程Virtual_COM_Port修改,添加智能换行功能
# p5 _4 p( b7 O! r+ w下载地址  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:583 C6 D) m. v) d9 y. m# s6 Q
请问楼主D+的1.5K电阻能直接上拉到V3.3吗?不用IO口控制。。。
* {0 ^% ^' t. b9 d/ p
可以,上拉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字节,' G# u1 w! A0 \- ^$ l: 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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版