请选择 进入手机版 | 继续访问电脑版

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

【经验分享】stm32f1系列单片机实战应用

[复制链接]
STMCU小助手 发布时间:2021-11-26 17:00
测量运动自行车速度,上传给上位机软件,处理VR视频播放。正好公司有现成的stm32f1系列单片机开发板,所以我就想到了使用它来实现这个小功能。
: W+ T. y% b% M, J; m/ @& R& b/ F- A9 u) y+ r; i
1. 硬件配置:! J# W0 ]8 g& ]& r  S+ ^

' E9 t1 W2 N' ]1.1. 运动自行车;
3 j0 n$ \2 y8 L6 r( }$ Z1 ]- w8 D; h  l  ]) j, ]6 A- d. Q
20180409144730202.png
1 b: Q; W: a& V8 }" x+ u- Z% L
7 _7 f3 r7 a# H1 c
1.2. 磁感应开关与专用磁铁;    & Y4 r6 r' f" ^5 r! S/ a: M

; m# d1 a; o' O3 T$ c) l4 ^
20180409144808136.png 20180409144818159.png

( n- i5 }# ^  u5 B# [* o$ V) L1 O, {. }3 i$ ~2 x
1.3. 基于Stm32f103zet6芯片的开发板(七星虫),如下图;
% A! l/ U' a& v0 v  P3 X& t
! S1 h: j8 ^7 d" t
20180409144832248.png
  t. T! a  j/ L5 W( h$ ~

0 r; `  v' P4 [' k; R' R3 N; C9 a1.4. 连接线若干;
. u/ C# J- n# n. k$ t4 {! }
' v# N% c" R% |/ `8 R1.5. miniusb线缆,用于给开发板供电及串口通信。
& S: C; K# a( Y  G7 k
7 @9 `, }& S8 {1 K* e
20180409144846453.png

) y/ p" L, l/ F1 b# h8 B- h; X$ s; p# }, i2 V) s( K; j
2. 系统描述与框图:  S7 m/ H4 ~9 n+ t7 W5 H$ A
$ c2 `6 l% p3 ]4 O& d
运动自行车车轮上安装5只磁铁,通过磁感应开关检测磁铁产生信号,接入stm32开发板PE0引脚。测量出的速度值通过串口发送给PC上位机软件(mini usb线缆连接)。硬件框图如下:+ h% M3 }: _; d( o; _
$ A& ]2 u- O7 q9 z5 {" Z9 \
2018040914485823.png

2 W4 G( q) }; r8 \  Z. t# @) c# k' t/ o

7 ]! W: t9 o5 V7 B  y9 H3. 软件实现. K( d+ x6 ^) ?0 d: k
% R" U. d7 `& z) i( S
3.1.设定开发板PE0引脚下降沿中断,在引脚中断服务函数里累计中断次数(即磁感应开关感应到磁铁的次数),同时每累计10次LED2交换一次状态。外部初始化代码及中断服务函数如下:7 A; Q, k; m! y8 \- ~) p

* n( X( h+ f' v( ]0 t- a2 h
  1. void EXTIX_Init(void)
    , U0 a( x+ A  O, l1 _) ]* `
  2. {
    7 G( n/ E2 q! }) d% [1 |: U
  3.     EXTI_InitTypeDef EXTI_InitStructure;
    ; F. Y, Q3 ~7 T. y' r" u8 t
  4.     NVIC_InitTypeDef NVIC_InitStructure;) O' ^" u2 ^/ J$ }9 m
  5.     GPIO_InitTypeDef GPIO_InitStructure;
    5 k. i0 g8 }8 I! Y5 K
  6.     //  引脚端口初始化 PE0
      `/ s: a4 j! E: Y! P2 H
  7.     GPIO_InitStructure.GPIO_Pin  = DEF_BIT_00;' _$ L- s. }. ]# P0 {/ [3 U" e
  8.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;" ]$ j" Z6 x* ~9 h" B
  9.     GPIO_Init(GPIOE, &GPIO_InitStructure);    ! W, ?! D* c0 M' h/ f) A: B
  10.      // 启 AFIO 时钟( ^6 b5 g. K+ n+ w" v: ^) @. x: `
  11.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    ; z5 Y. ~% d" ?/ _! f  W" u9 Q
  12.     //GPIOE.0 中断线以及中断初始化配置,下降沿触发8 B$ z) h5 x. \: m' Q8 m" }
  13.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource0);// 配置中断线为0- s$ M  ^+ b+ E& ~$ F' |
  14.     EXTI_InitStructure.EXTI_Line=EXTI_Line0;. y8 G  I2 y+ x- ^5 Z3 e
  15.     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    " Y  u4 v7 Q' V/ D! k" g2 P, x" A* R
  16.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发. ^1 {; `6 p8 ^
  17.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    % ^( N, {# I1 S  e" |! a0 B5 ]& f
  18.     EXTI_Init(&EXTI_InitStructure); // 初始化中断线参数
    ' Q: v+ @; `) s/ G! Z

  19. 6 X8 k: J  a5 ]( f+ v2 O4 N
  20.     NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;                //使能按键外部中断通道" F2 r& w" b) a5 W9 Y
  21.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;    //抢占优先级 2,
    5 C4 Z/ k$ M4 C5 X5 p, Z. a
  22.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;           //子优先级 24 s; Y4 o, a! r1 K/ f3 B  e
  23.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                 //使能外部中断通道
    ; _+ ?! M, [# Q( Q* U
  24.     NVIC_Init(&NVIC_InitStructure);                                 // 初始化 NVIC* w  s, P, w+ L9 T2 J" `
  25. }" l8 M- _' ~  A9 R" I
  26. // 外部中断0服务程序
    3 `6 E8 N9 a3 M
  27. long long lSpeedCnt = 0;( |7 o# b4 Y7 P# v! y
  28. void EXTI0_IRQHandler(void)9 h. j7 \6 B/ h8 d$ C+ N% Q9 J
  29. {
    # |$ z4 O; v$ z; E
  30.     OSIntEnter();             // 告诉ucosii系统进入中断; y1 {2 S. G% U0 {  L

  31. ; [1 ?0 H, C1 A2 |5 X; {5 x; m
  32.     if(GPIO_ReadInputDataBit(GPIOE, DEF_BIT_00)==0) // PE0检测到下降沿
    - ]% K' ?/ {% y, t7 q2 K
  33.     {
    5 L. f" }$ G, o" G& D4 L
  34.         // 累计中断次数,每隔10次改变led1状态
    ) A0 S' x% U( K+ t$ g
  35.         if(!((lSpeedCnt++)%10))
    + v5 ~" g' F3 K$ i; K. b
  36.         {
    3 [+ ]+ S: S6 \; b- F
  37.             BSP_LED_Toggle(2);
    $ Z: |" L9 `- Z: J8 \3 h
  38.         }( H: f& O1 L+ a& W4 W" p
  39.     }6 V8 J* B' e' q, F, c, K- Q
  40.     EXTI_ClearITPendingBit(EXTI_Line0); // 清除LINE0上的中断标志位  s) s3 {" j" c
  41. 7 j2 H& N9 E/ V6 N% g) z5 j
  42.     OSIntExit             // 告诉ucosii系统退出中断: M/ L) e* e5 S. o) d$ D- G- B9 i
  43. }
复制代码
- H2 X+ T) a$ U. S

( C* [* N$ B) j5 J: O3.2.在启用一个定时器中断,周期为1s,在定时器中断服务函数里计算自行车的速度。计算方式如下:v = p / μ * C,其中:v是速度:m/s,p是磁感应开关感应频率, μ为车轮上安装磁铁个数:5,C为自行车车轮周长:1.38m。定时器中断初始化代码及中断服务函数如下:
3 @$ i9 |3 }1 T! b5 h, E4 h2 t) d+ h
  1. /*******************************************************************************; T! U: m; e2 b( \
  2. * Function Name  : BSP_TIM2_Init
    % @! ^# w4 B2 r' E3 Q& O) c) l( z" q
  3. * Description    : Compute return latest speed measurement
    4 Z; w! x& R6 k. ]/ }6 i# H
  4. * Input          : None
    * L) Q* E- E) I
  5. * Output         : s16
    # w$ K. @  B8 n' t+ c
  6. * Return         : Return the speed in 0.1 Hz resolution.                    2 f; ]1 M8 R6 E
  7. *******************************************************************************/, H! G7 j" V; j1 ^& A
  8. static void BSP_TIM2_Init(u16 arr, u16 psc)& Z8 r7 c9 y- R
  9. {
    . r3 W& ?" e5 \# J% M" y
  10.     TIM_TimeBaseInitTypeDef   bsp_tim2_init;    / |5 l/ Z+ Z1 d% j

  11. 6 d2 W  s: c' H* H( @9 U# S: P9 f
  12.     //使能TIM2时钟
    2 _2 R, s  V& ]" g7 L
  13.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    : D  E6 H! z1 ^9 V2 {* A1 \8 E
  14. 6 I, e( v8 B9 M' w- ^3 }9 N3 R6 @3 F

  15. 2 I8 A$ _9 U# k; _
  16.     TIM_DeInit(TIM2);8 B$ r/ D5 Q9 m( j
  17.     TIM_TimeBaseStructInit(&bsp_tim2_init);
    4 i6 |3 x1 W/ i0 f
  18.     //TIM2初始化
    ) P- s( O) b' l* Y7 ~/ y/ k' b
  19.     bsp_tim2_init.TIM_Prescaler = psc;                                          //时钟预分频   定时器每隔 (psc+1)/72 us计数一次
    1 K/ H$ B0 J1 x9 X; b' P' L' U
  20.     bsp_tim2_init.TIM_CounterMode = TIM_CounterMode_Up;                         //向上计数1 i% V; ]# s9 k
  21.     bsp_tim2_init.TIM_Period = arr;                                             //计数满(arr+1)次更新重装载寄存器数据
    # f' l: F' C# x4 [7 {& D3 x$ `
  22.     bsp_tim2_init.TIM_ClockDivision = TIM_CKD_DIV1;                             //时钟不分频
    1 e; X. R; y1 M- j+ K' h
  23. //    bsp_tim2_init.TIM_RepetitionCounter = ;                                   //高级定时器用,这里不需设置  ~; r+ q. S6 A& L" o3 ^
  24.     TIM_TimeBaseInit(TIM2, &bsp_tim2_init);                                     //初始化定时器
    + [0 f9 G$ ^9 ]: m6 D2 P

  25. ) i; Q# N+ G6 D. o1 B
  26.     //设置定时器TIM2中断
    " q7 S: F5 h: W  N( H9 R( j
  27.     TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);                                  //设置定时器更新中断
    ! `1 u( G0 ]$ ^! B/ k& g+ D
  28.     TIM_ClearITPendingBit(TIM2, TIM_IT_Update);                                 //清除中断标志,防止刚上电时进一次中断
    ! T  l* T8 d( p2 ?" H9 F# D* K. r

  29. 5 ]4 r  ^, T4 _* Z4 q7 R+ }; f, V" E
  30.     //初始化中断1 \7 `7 e3 @4 }$ Z8 t
  31.     BSP_NVIC_Init(TIM2_IRQn, 3, 3); 7 X8 u9 o. V! U; d/ T4 D+ Z

  32. ' e$ x9 X: c6 u, O5 Q! S4 R, m5 _
  33.     //使能定时器TIM2
    4 T1 l, g" }) v) |' }
  34.     TIM_Cmd(TIM2, ENABLE);# R( A/ C& C( D6 A5 \  g
  35. }
复制代码
  1. long long lvalCur;
    ; s& T0 e# y% E% A
  2. long long lValPrev;1 v) ^; j( L9 s: a, i
  3. float fSpeedVal;( O0 K# Y6 q' t- \1 a3 @
  4. void TIM2_IRQHandler(void)5 M, r: B" l9 v0 X4 }, U9 d
  5. {, u9 p) S- d% P
  6.     OSIntEnter();             // 告诉ucosii系统进入中断
      j$ c/ W- k" C3 B. @4 w
  7.   }0 e' V& A/ h4 A1 v
  8.     if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
    $ _5 f$ y: ?5 ~
  9.     {      0 D& X1 P5 a( b* k
  10.       extern long long lSpeedCnt;. p, v& i" J, L0 S% O4 D

  11. ; C1 y# y" p, q# L# i
  12.       lvalCur = lSpeedCnt;- ^' X! W) [. @/ o+ O
  13.       fSpeedVal = (float)lvalCur - (float)lValPrev;9 y, h9 W5 m$ \7 f7 ]
  14.       fSpeedVal /= 5.0;
    % p9 R1 f- u6 |; v, M! w+ b' `0 R" ?
  15.       fSpeedVal *= 1.38;      7 U! f+ Q: _: R) }1 {; p
  16.       lValPrev = lvalCur;0 |+ C( d5 Z$ F6 V
  17.       TIM_ClearFlag(TIM2, TIM_IT_Update);1 `8 R# i. u4 r4 T3 S
  18.     }
    . Z+ v/ T2 k" T; V9 K
  19.     OSIntExit();             // 告诉ucosii系统退出中断
    ) }. b" `9 V2 S! \1 @, e( ~0 i5 S. \

  20. 5 N- Q; L) ~$ p6 T9 X# u
  21. }
复制代码

& J$ A  D  c) K- }, X2 a3.3.系统共有两个任务,其中一个任务每50ms发送一次速度值给PC机,另一个控制LED1闪烁,周期100ms,用于指示系统正常运行。' N9 ^  ~9 f+ \- O  b5 S/ K9 @9 M
- _3 }  z) `  P" g6 h; x" c
第一个任务中运行代码如下:
! W# W5 Z. I( v: i: o7 r! j! G9 Y! L: M6 h# |* G+ C. H
  1. while(DEF_TRUE)
    7 J  I, a  V4 m' o, R& x
  2.     {              : P& @2 |& U& ?& C' J
  3.         extern float fSpeedVal;0 X5 f0 U) d; m+ U
  4.         if((int)(fSpeedVal*100) > 9999)! j& ^8 V1 M0 J
  5.         {
    : z+ q$ g* [) w; N9 s
  6.             printf("9999"); % c" Z& O1 p: |! P) N8 W9 g& V
  7.         }6 ?" q# T( u6 Z9 a# B6 @3 p
  8.         else if((int)(fSpeedVal*100) > 999)
    / V& ^" X- y4 o5 r2 t) ~  `" r
  9.         {( ?& R) |/ r2 u" V0 _
  10.             printf("%d",(int)(fSpeedVal*100));
    % }5 |) }2 \" a5 k' i; o  I
  11.         }
    . b- {/ x( z: i; d
  12.         else if((int)(fSpeedVal*100) > 99)
    ) z3 i' q9 \9 W+ |3 N& q. Z
  13.         {
    & C5 u9 B/ [# }2 ?' g+ u4 i
  14.             printf("0%d",(int)(fSpeedVal*100)); * l9 x% ^; f. t1 R6 Z/ H4 n
  15.         }
    5 g, k  b* \% g1 m( E/ z
  16.         else if((int)(fSpeedVal*100) > 9); F% A4 x& o6 N! J
  17.         {. `, Z" h! p  p9 v' W
  18.             printf("00%d",(int)(fSpeedVal*100)); 9 f8 S& g2 G! v, J+ j9 {- u
  19.         }. B0 Q3 m8 c! o; x; f
  20.         else
    3 r3 x: q2 _, q7 C0 I, }  n! r
  21.         {
    ( W1 e, p+ |% d- [9 h+ `, A
  22.             printf("000%d",(int)(fSpeedVal*100));
      }4 G, S. R" O. S) m1 U
  23.         }     " N5 D2 E3 r3 d5 m! |% D
  24. - ^2 v/ A9 Z4 }6 u+ B( u; s
  25.         OSTimeDlyHMSM(0, 0, 0, 80);3 C% [# l. a/ ], T! _
  26.     }        
复制代码
& i% B# E5 n3 U4 H2 _
第二个任务中代码如下:: q) N, p2 ~, i% Z! C5 P, \; o

3 Z* V' ]% R* s. x
  1. while (DEF_TRUE)" h3 o6 B& n" B' ~  c8 ~
  2.     {     
    $ B* I1 D6 `- u) F4 z7 `) I8 R+ s
  3.         BSP_LED_Toggle(1);  5 K8 a- @5 f) X  g7 d5 b+ t3 u
  4.         OSTimeDlyHMSM(0, 0, 0, 100);# ~7 l2 s- Q. A' d
  5.     }
复制代码
3 Y4 l" G  S5 X9 i6 G7 m
整体运行稳定,满足项目需求。% x9 `* l* Q: _# H

3 {( [" h) n% q. B) v4 _4 M
; b$ l6 X3 n, d7 w! ?9 h+ \
收藏 评论0 发布时间:2021-11-26 17:00

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版