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

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

[复制链接]
STMCU小助手 发布时间:2021-11-26 17:00
测量运动自行车速度,上传给上位机软件,处理VR视频播放。正好公司有现成的stm32f1系列单片机开发板,所以我就想到了使用它来实现这个小功能。4 B  G% _* a) K. b  q- r
4 s: K2 ?$ l; D- ]; s
1. 硬件配置:2 |' @& S* u! s0 e* \
9 x- K. u; J. w# K
1.1. 运动自行车;
! ]  s; }* S$ O$ E6 ?% g5 v* ?# g% @5 e( Y, a0 g
20180409144730202.png

- u. S# w4 ?1 s& h1 P) N7 k
" F' N* v. X8 J- ~1 ~. d1.2. 磁感应开关与专用磁铁;   
* \% [. k% i7 X/ u! ?% }& g  s0 H/ H8 i8 s, r4 \& p+ b
20180409144808136.png 20180409144818159.png
% x# J, H6 i4 z) q" O
" z7 d( O( E$ k0 t7 R' @
1.3. 基于Stm32f103zet6芯片的开发板(七星虫),如下图;
% y/ T) t1 L$ a" F1 H) [
/ z+ l  x( C* c1 m; ?* t& A
20180409144832248.png

6 W+ H# \+ ]0 c3 Q" Z) o
3 M/ @' A/ @. D1.4. 连接线若干;
' g; Y; N5 Q* r4 F4 [0 D/ t0 f# n" {' A' Q( f
1.5. miniusb线缆,用于给开发板供电及串口通信。. q' |) q; Y- y, \0 @

! r, c( u+ g% R6 x2 \
20180409144846453.png
- X+ d! L; m* b4 \* d+ h

) ^, @  [- l8 F# n) I! m: V( Y0 o2. 系统描述与框图:3 ~- t+ ~/ r2 |4 W+ A! D4 l1 S
) y) @, t* q" f! z" q
运动自行车车轮上安装5只磁铁,通过磁感应开关检测磁铁产生信号,接入stm32开发板PE0引脚。测量出的速度值通过串口发送给PC上位机软件(mini usb线缆连接)。硬件框图如下:
7 b, B" h, A( R4 f! s7 t0 V7 i& D6 }& j# I0 v
2018040914485823.png

# D. p  v; _, W+ ?! Y' J4 E% r
8 ~* Z: I: {0 q, r
5 W' b: T0 R0 c  O; S1 v2 L1 `3. 软件实现
  v" a! Y& Q2 c  e8 Z- ~, Z; b# l& @. |' K$ m% f
3.1.设定开发板PE0引脚下降沿中断,在引脚中断服务函数里累计中断次数(即磁感应开关感应到磁铁的次数),同时每累计10次LED2交换一次状态。外部初始化代码及中断服务函数如下:/ K0 m+ ]( k/ U6 w" r5 O
7 [; C: ^1 t& a6 q9 e
  1. void EXTIX_Init(void)
    1 }- j, m5 G* p7 D( e5 a( g
  2. {( j: F/ |5 X3 V0 ?; E+ D
  3.     EXTI_InitTypeDef EXTI_InitStructure;
      @5 Y4 z$ W: v7 ?4 E( X5 H
  4.     NVIC_InitTypeDef NVIC_InitStructure;
    ( b% o! f  H' k$ q
  5.     GPIO_InitTypeDef GPIO_InitStructure;% v  ~3 u7 z5 i0 t8 k& l
  6.     //  引脚端口初始化 PE0
    ) ~6 M. [0 v/ {" K% E: o* K
  7.     GPIO_InitStructure.GPIO_Pin  = DEF_BIT_00;$ \$ F* P' ?% }! w( a- R5 P) v
  8.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    4 m- y; q9 z- p3 }# W
  9.     GPIO_Init(GPIOE, &GPIO_InitStructure);   
    ) T( q% v* ~1 B0 P# H! z: s
  10.      // 启 AFIO 时钟
    $ R- n3 [6 `/ a! _
  11.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    6 R9 [. U# b9 \: A# z
  12.     //GPIOE.0 中断线以及中断初始化配置,下降沿触发
    5 U! H$ G3 q4 J+ P. t' {( M
  13.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource0);// 配置中断线为0( l* E: o4 N, n) S/ R  b, Y" {
  14.     EXTI_InitStructure.EXTI_Line=EXTI_Line0;" l- E( c+ v* w8 |2 |
  15.     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;: e; ]. w3 w3 u, @
  16.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发
    9 v" ]* a1 n4 V
  17.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;% X2 D0 x: K2 \7 Y" V3 N2 H* M
  18.     EXTI_Init(&EXTI_InitStructure); // 初始化中断线参数0 l0 o* m% s. y* k2 N; }
  19. 0 c; u# \+ T' R, m& \
  20.     NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;                //使能按键外部中断通道
    , ~" `, G; `% y& P7 u
  21.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;    //抢占优先级 2,5 ?. t9 }- Z3 ?, ?3 X/ J
  22.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;           //子优先级 2- a7 ~/ @! I( C# c& d1 ?: }
  23.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                 //使能外部中断通道
    & n9 }' t" p6 Q6 Z/ g9 G. T8 u
  24.     NVIC_Init(&NVIC_InitStructure);                                 // 初始化 NVIC
    # b1 j; x6 x$ b! }: s  z
  25. }& _) t( J5 r, K! p
  26. // 外部中断0服务程序7 b3 ?: W* f! ^: V/ i1 \, h
  27. long long lSpeedCnt = 0;
    : X  j8 D% }% z
  28. void EXTI0_IRQHandler(void)
    0 K) ~! t2 E) }! l
  29. {( O2 c7 j- A! ?" @. n0 i( ~
  30.     OSIntEnter();             // 告诉ucosii系统进入中断6 l& I. K" }9 O+ g5 N# p& |( c: i
  31. ( d; @& p: z1 l# W2 t- t! ^
  32.     if(GPIO_ReadInputDataBit(GPIOE, DEF_BIT_00)==0) // PE0检测到下降沿
    - \* s- Y3 V- O  e) M
  33.     {
    ' V2 v# |' |3 W
  34.         // 累计中断次数,每隔10次改变led1状态
    0 Y. f. N6 E" z2 y4 f+ v
  35.         if(!((lSpeedCnt++)%10))
    : Z" d/ L% Y4 o" ^  b! O# S
  36.         {/ u2 C* N. M" d* a) D) z
  37.             BSP_LED_Toggle(2);
    & O- S9 i5 M$ k: |% }
  38.         }
    9 ?1 {! x/ Q3 C- K7 ]$ z' k( A
  39.     }
    ; d: K. v% n8 x7 W6 R
  40.     EXTI_ClearITPendingBit(EXTI_Line0); // 清除LINE0上的中断标志位
      X& m) z. v7 S. m4 Q

  41. ! S3 v9 {; W; g$ ~; |6 |
  42.     OSIntExit             // 告诉ucosii系统退出中断) U. Z- E# o7 P: [% W5 r
  43. }
复制代码

3 o3 b$ f+ n8 Z( B  X% W
" u' d+ ]) J4 g$ q; z) }6 ]3.2.在启用一个定时器中断,周期为1s,在定时器中断服务函数里计算自行车的速度。计算方式如下:v = p / μ * C,其中:v是速度:m/s,p是磁感应开关感应频率, μ为车轮上安装磁铁个数:5,C为自行车车轮周长:1.38m。定时器中断初始化代码及中断服务函数如下:
9 e+ p9 ?# Y% t' t
4 A+ E& _  b" |0 u& T4 v2 W$ g& \
  1. /*******************************************************************************
    0 g. ~; ]9 ?, q( H
  2. * Function Name  : BSP_TIM2_Init% H$ _/ H+ p: \" U! r  |5 p( x9 n
  3. * Description    : Compute return latest speed measurement   I9 n' S3 B3 Z$ P  L; ]
  4. * Input          : None/ b) g) P' ^1 `" U# ~. `' c/ I
  5. * Output         : s16
    ) }) E4 t5 b1 U* w- o2 w$ Y+ \
  6. * Return         : Return the speed in 0.1 Hz resolution.                    
    , h- x8 s/ U$ h5 J7 `) N$ S
  7. *******************************************************************************/
    * m4 M4 c$ t1 }6 ^
  8. static void BSP_TIM2_Init(u16 arr, u16 psc)
    4 @0 I: o* ]: L1 R
  9. {
    ) e3 N, H# M" C2 j. C% b
  10.     TIM_TimeBaseInitTypeDef   bsp_tim2_init;    % X8 H; E- I" x6 l5 Z% [* p( ]
  11. ; v5 J* U" E: a7 z
  12.     //使能TIM2时钟# G8 p0 @. v4 f' }4 P6 @* b5 N
  13.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
      c2 T5 a2 w& {1 N/ \- W/ r

  14. 8 F6 R# z* \- K7 O+ |6 m' w% l# d: f

  15. / Y: A2 ^& k! A3 T3 ^, Z
  16.     TIM_DeInit(TIM2);
    7 j9 j" Z/ }6 Q  |1 M
  17.     TIM_TimeBaseStructInit(&bsp_tim2_init);& _+ k: t& [/ N% Y
  18.     //TIM2初始化, }5 ~3 [9 \! }1 F& ^8 L' c
  19.     bsp_tim2_init.TIM_Prescaler = psc;                                          //时钟预分频   定时器每隔 (psc+1)/72 us计数一次
    " X" H7 u0 ]+ I( g( m
  20.     bsp_tim2_init.TIM_CounterMode = TIM_CounterMode_Up;                         //向上计数1 d3 w  A$ @( T1 {+ W% w7 {/ G
  21.     bsp_tim2_init.TIM_Period = arr;                                             //计数满(arr+1)次更新重装载寄存器数据
    + \' K8 ?/ y# V0 x
  22.     bsp_tim2_init.TIM_ClockDivision = TIM_CKD_DIV1;                             //时钟不分频- s; ]' D) i5 y2 b3 }  @4 V
  23. //    bsp_tim2_init.TIM_RepetitionCounter = ;                                   //高级定时器用,这里不需设置. C" q" Y- Y) e* B& ^' F' l* m0 i
  24.     TIM_TimeBaseInit(TIM2, &bsp_tim2_init);                                     //初始化定时器
    6 B& z: q2 w$ F4 L0 t

  25. # D- l' n) s  I. \' ^
  26.     //设置定时器TIM2中断
    ; Q6 x) G/ J' f4 o  T# Y4 ~% C& H
  27.     TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);                                  //设置定时器更新中断
    ' V9 V* `4 |6 f, F. i  P
  28.     TIM_ClearITPendingBit(TIM2, TIM_IT_Update);                                 //清除中断标志,防止刚上电时进一次中断
    1 k0 J0 |! r! d1 {. F1 C

  29. 0 q! V; t1 F! e! k6 r: G
  30.     //初始化中断. d5 F1 r8 E( r& W0 ^6 R
  31.     BSP_NVIC_Init(TIM2_IRQn, 3, 3); * i+ o4 P4 Q0 b& ?
  32. - \% T9 [+ r# Y/ M  c
  33.     //使能定时器TIM2
    9 B8 U& _  A* H/ V+ e) m( w% G
  34.     TIM_Cmd(TIM2, ENABLE);
    ! S/ \3 {  O, v* z, m6 Z
  35. }
复制代码
  1. long long lvalCur;3 d7 A$ w( q! `/ ]$ ]! J
  2. long long lValPrev;( w1 t- R1 X+ J' A+ Z
  3. float fSpeedVal;
    ! a6 q" X  P. H& z
  4. void TIM2_IRQHandler(void)
    , d) W0 [# n# W, Q" r  z" V" y4 p
  5. {# E  W8 p: |) S: z
  6.     OSIntEnter();             // 告诉ucosii系统进入中断
    " g  ~0 x  ]* N& o& E
  7. 6 l, q" K% g: N7 l0 R, w2 c1 X
  8.     if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
    , i; ?  a# S! S. x, o* c
  9.     {      0 f% C# |8 c( f- ^( u
  10.       extern long long lSpeedCnt;% s( |7 J6 {& U/ [

  11. ; K/ A% P) ^- C0 `$ G
  12.       lvalCur = lSpeedCnt;
    9 w( D$ J3 I, G+ E: Q+ L, k
  13.       fSpeedVal = (float)lvalCur - (float)lValPrev;
    / G0 S+ x7 E7 S, G3 R+ \1 p
  14.       fSpeedVal /= 5.0;$ O7 _5 E% C) m8 }: v
  15.       fSpeedVal *= 1.38;      
    ( \$ M8 D  p; v* R7 O) S9 Z6 Y
  16.       lValPrev = lvalCur;
    $ w( i6 `8 X9 j2 T, Q* y! G3 e
  17.       TIM_ClearFlag(TIM2, TIM_IT_Update);
    ! D! d9 G+ b: \' ^7 I/ Y, b1 H3 |
  18.     }
    8 [% a; _  e. T3 Q& e7 J  C( K
  19.     OSIntExit();             // 告诉ucosii系统退出中断
    ! Y/ f9 T' w/ n- x$ }

  20. 0 [" U# {/ S$ Z  m/ u& e5 }
  21. }
复制代码
" M8 I0 g; N2 Y" v7 ]  `, B
3.3.系统共有两个任务,其中一个任务每50ms发送一次速度值给PC机,另一个控制LED1闪烁,周期100ms,用于指示系统正常运行。& U5 f# W# e& U1 H3 p

# o; P& R) z: V8 [7 P2 e4 [第一个任务中运行代码如下:6 x* {) G$ l. K/ e9 ^
$ I8 {$ I6 H6 r: n6 k' V. o+ b$ i
  1. while(DEF_TRUE)
    # c# n7 s! A* \, c, z- o4 o6 e4 I- F8 z/ b
  2.     {              
    & `! ]$ |, X/ P  w- Z( j; m
  3.         extern float fSpeedVal;
    : M! _% H. F7 X
  4.         if((int)(fSpeedVal*100) > 9999)
    # r2 n' Z( }. n# D1 Y
  5.         {* p0 p1 M7 d/ W
  6.             printf("9999");
    6 R0 ~/ H/ p/ i
  7.         }
    9 B; }* D9 R9 M
  8.         else if((int)(fSpeedVal*100) > 999)& ]+ s9 s# C4 N& D& H
  9.         {
    ! q2 t) b+ }: l5 r
  10.             printf("%d",(int)(fSpeedVal*100)); # L; D) d1 D9 X% w5 r, G# i
  11.         }+ C, o. N  T4 o# `$ T) ]
  12.         else if((int)(fSpeedVal*100) > 99)
      z6 r2 B" `7 N& O1 e
  13.         {5 V* u, w: I; W9 E8 W  n+ q
  14.             printf("0%d",(int)(fSpeedVal*100));
    ) ^+ ^# o* \, D  |8 D7 c
  15.         }! W$ x& o( T9 f! Y. `- K: i
  16.         else if((int)(fSpeedVal*100) > 9)
    + q8 S; M& ]$ N- ]: P3 Q: y( j
  17.         {9 ~4 ?* A/ G' y" o" c- x  V
  18.             printf("00%d",(int)(fSpeedVal*100));
      j0 d2 J; Y# ^- }# y, b
  19.         }
    ! @; d6 T6 h8 L1 e( R
  20.         else
    . |4 s1 A6 `" @" H. n
  21.         {
    , o# ^) S1 B" K+ h7 A+ C
  22.             printf("000%d",(int)(fSpeedVal*100)); . p; Z0 r) w* X1 e
  23.         }     ) a  }9 d. k8 ]8 Z$ }; @9 Q
  24. . V4 u; P  S! H' Z
  25.         OSTimeDlyHMSM(0, 0, 0, 80);
    & Z: S8 b! G7 m4 k0 x$ Q$ ]; ^3 F  K
  26.     }        
复制代码

6 W  k. @# I# y. t第二个任务中代码如下:
  t& Z) ?! t$ }& H) C$ _) n$ E' k9 X! e- y2 N" G  K1 n' `5 h% e
  1. while (DEF_TRUE)
    & I9 k5 c% Q. ?! c
  2.     {     
    7 V& I9 `) x+ Q/ J- z5 ]
  3.         BSP_LED_Toggle(1);  + _$ ?: |- F9 P3 P2 P
  4.         OSTimeDlyHMSM(0, 0, 0, 100);
    " J3 y+ G0 A! Q. r, O
  5.     }
复制代码

2 q' M% n" O7 O& ^5 N# \整体运行稳定,满足项目需求。
$ o' @7 Y: p2 g' B5 T( j  h8 t$ {- }( P; Q! J( z1 j
; q' j! h! F" f5 s/ w
收藏 评论0 发布时间:2021-11-26 17:00

举报

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