|
一、简介 ! {4 F! \6 {5 Q! h
本文介绍如何在STM32上使用霍尔传感器模块。
8 r) X! I' R n. {二、实验平台 0 P& R& z, D5 U$ I
库版本:STM32F10x_StdPeriph_Lib_V3.5.0 编译软件:MDK4.53 硬件平台:STM32开发板(主芯片stm32f103c8t6) 仿真器:JLINK . E$ X* i) f& e0 H
三、基础知识
3 z# n1 G! l$ g5 S- D/ ~. J1、霍尔传感器是什么? 答:霍尔传感器是根据霍尔效应制作的一种磁场传感器。 用磁铁去靠近霍尔传感器时,霍尔传感器的引脚电平会产生变化。 & f3 @4 v. q8 z5 s% t2 f
0 E% c7 D$ T8 k, n5 O2、霍尔传感器主要用在什么地方? 答:霍尔传感器可测速、计数、限位上。
* G% @: b9 u4 q* E' w$ C3 t5 U1 [+ r7 m 举例限位功能:两个霍尔传感器形成45°的夹角,电机边缘粘着一个磁铁,一旦电机转动导致磁铁触发任意其中一个霍尔传感器,则STM32检测到触发后立刻停止电机,不能再继续往此方向转动。以此达到限制电机转动角度的作用。 ! E: s0 j7 V. p O) o4 h8 i
1 x" |9 Q( a! b- n3、本文使用的是什么霍尔传感器模块? 答:
* e# Q2 x1 z: g, v4 F- n. v. W
买的霍尔传感器模块一共有四个引脚,GND、VCC、D0、A0。
8 Q5 J% T8 W! ^: A4 v f
其中只需要用到三根线,GND、VCC、D0。
% Y: i+ T0 n, a5 F/ b$ I
使用方法: 1)5V供电。 2)用跳线连接D0和STM32的IO口(本文连接的是PA11)。 3)D0默认是高电平,但磁铁的特定一面(磁铁另一面无用)去靠近霍尔传感器模块时,D0会被拉低。
% L! e3 K% p/ W7 [ ' t* l" s. t) M3 p
4、霍尔传感器与限位开关有什么区别?
! J" _" }2 C( d& y+ I+ t+ j' K
答: 1)限位开关 ①优点:无功耗。 ②缺点:易损坏。
1 j6 H$ H- b2 Y. X! J2 h6 M. ]2 h
2)霍尔传感器 ①优点:不易损坏。 ②缺点:有功耗。 0 Q L+ r$ C N
$ ?! ~8 ?% B2 y, G3 N
四、实验步骤 : K6 V/ p W4 r$ u
1、编写并添加霍尔传感器驱动 . T% A5 B; n4 {7 q' D% q
1)编写驱动GUA_Hall_Sensor.c(存放在“……\HARDWARE”) - @0 x5 V' M% Y) X& E3 R& W4 T; V
# e' \& q( ~* Y0 R: }9 C- #include "stm32f10x.h"
4 |& d2 O# I3 T; G) R; @" v# ] - #include "GUA_Hall_Sensor.h"
4 F6 }) J% T ?0 n/ i" s -
1 t9 Q0 W6 |, q% r - /*********************宏定义************************/
5 {9 h3 W# n9 F& f. J( k - //霍尔传感器引脚
5 [. m! g: n0 c - #define GUA_HALL_SENSOR_PORT GPIOA$ x; {) o6 A* k+ H+ m9 I* `
- #define GUA_HALL_SENSOR_PIN GPIO_Pin_11
- Z) [3 _5 `! i - ! C/ O. d3 z2 A7 L; f
- //消抖总次数6 [$ L7 H ~7 i) T1 S
- #define GUA_HALL_SENSOR_DISAPPERAS_SHAKS_COUNT 500000
}; }1 Z9 a% y! D: s0 k! | - /*********************内部变量************************/0 X' C* W5 Q+ H8 t4 @* K, P
- static GUA_U32 sGUA_Hall_Sensor_DisapperasShakes_IdleCount = 0; //消抖时的空闲状态计数值: q. a6 f! `, E# I8 C( g; } T
- static GUA_U32 sGUA_Hall_Sensor_DisapperasShakes_TriggerCount = 0; //消抖时的触发状态计数值
+ H. X) s" ?4 Z3 T# h0 F -
" Y& A5 d8 ^# Z. @( @5 ~% G - /*********************内部函数************************/
0 I; W7 o7 n* ^0 E8 f - static void GUA_Hall_Sensor_IO_Init(void);# }8 u7 i5 s7 e6 j; f& I! w% H0 b
- % j" r7 s2 }3 I3 I# A
- static void GUA_Hall_Sensor_IO_Init(void)
% V/ `: Z+ T# w: ? - {
0 O9 d6 C1 w- Z: P8 o8 e - //IO结构体
! j/ A' d. F; _' a S% I - GPIO_InitTypeDef GPIO_InitStructure;
4 z. J1 N( d. C! I7 z -
" n1 @, p9 ~ T2 L5 u& n! } - //时钟使能0 z# m. k y# g6 k! P1 ]% T% R% T
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); & n" T$ a: ^3 _/ m) z+ y6 T
-
# R% b" x0 X }2 G9 p" k2 J# N1 g - //霍尔IO配置
$ ~& d+ N4 X7 \4 B" P - GPIO_InitStructure.GPIO_Pin = GUA_HALL_SENSOR_PIN; ' [9 ]. V# Q% ?+ b! U
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; ' C8 ^1 }2 p. t! s' x) }# h/ n$ R5 _
- GPIO_Init(GUA_HALL_SENSOR_PORT, &GPIO_InitStructure);
. D0 ^, p& O6 b3 o E* c" @9 [ - }
+ [5 E, E2 w: u - 9 N7 R" |( u# X, U! T$ J
- GUA_U8 GUA_Hall_Sensor_Check_Pin(void) 8 \3 L9 q( C" W# e2 s
- {
3 q: q7 s8 a! O - //没触发
/ s4 R3 i9 L1 R7 A J - if(GPIO_ReadInputDataBit(GUA_HALL_SENSOR_PORT, GUA_HALL_SENSOR_PIN) == SET)
5 |: c9 F5 @2 ?0 [ - {
" T3 V0 D6 Q: l0 K! q - //计数0 t) F3 H) C" z
- sGUA_Hall_Sensor_DisapperasShakes_IdleCount++;, N8 K8 Q" Z9 u5 l
- sGUA_Hall_Sensor_DisapperasShakes_TriggerCount = 0;
8 j! ?. T! m8 C) ?9 ~ - 0 W# j( Z1 C6 G. l; z2 |
- //判断计数是否足够
2 z) h( h; y6 f! G, S - if(sGUA_Hall_Sensor_DisapperasShakes_IdleCount >= GUA_HALL_SENSOR_DISAPPERAS_SHAKS_COUNT)+ t" [4 Z- s1 n, j3 n
- {: t f5 K% M$ H2 p( K
- return GUA_HALL_SENSOR_STATUS_IDLE;
: O, N' c9 Q K4 W3 e& t( x - }
; R0 k6 ~) \" J/ \7 j, R - }
# R) J( z( ~; L! f6 N; y - //触发$ R% G) j) q+ ^- p% H% _
- else
4 A9 x5 T0 L$ l; S$ h. S, ^) T" L - {
; F/ o$ g. Q1 }% M. x k - //计数
* [( Q/ T0 j$ K& ^( W, }- e0 G - sGUA_Hall_Sensor_DisapperasShakes_IdleCount = 0;$ b. H$ r) d, @0 O
- sGUA_Hall_Sensor_DisapperasShakes_TriggerCount++;
5 k O. G! w+ {" w1 V1 o -
* q* ?& s% B5 n8 V/ F - //判断计数是否足够
0 i$ ?6 u- |7 N0 y: Z - if(sGUA_Hall_Sensor_DisapperasShakes_TriggerCount >= GUA_HALL_SENSOR_DISAPPERAS_SHAKS_COUNT)
8 x8 j; I8 C- X - {: P' {! C' N/ @0 F
- return GUA_HALL_SENSOR_STATUS_TRIGGER; " s) Z' r5 q- h9 o9 E5 I
- }
6 s; Z6 Q& _% T ~% u) E% G, x - } 4 Q+ \/ F; U+ T, k8 J
- - h+ Z8 r. p5 o8 _7 G) f7 s3 |- [
- return GUA_HALL_SENSOR_STATUS_DISAPPERAS_SHAKS; " @" l5 W- i( a6 q6 v. |
- } ' C. j# l# p5 `& @& l% Z
-
' \/ u; j* _9 N" a6 ?9 d9 k - void GUA_Hall_Sensor_Init(void)
+ b+ z% w3 }' I% M3 s7 Q - {+ j+ j/ {% Q1 |; D$ E+ q
- //初始化IO3 E, V+ d4 {7 ~1 j* w" i; O
- GUA_Hall_Sensor_IO_Init();
4 P) x3 E0 h+ B) D- R( g - <font size="3">}$ m5 v2 v1 s2 [' t6 |
- </font>
复制代码
8 q2 D+ ?) I. U; Z2)编写驱动头文件GUA_Hall_Sensor.h(存放在“……\HARDWARE”)
+ M; H, M: F& H3 S8 b! g: [- ; r$ t" l f& b) c7 E
- #ifndef _GUA_HALL_SENSOR_H_
) j; O! \! v. W7 k- A - #define _GUA_HALL_SENSOR_H_, Y4 H# w2 N0 t3 l
-
$ Y- f5 J2 ^; H - /*********************宏定义************************/ ], M; R c. l# r7 N6 g
- //类型宏; s7 y3 y% E- E5 y* l
- #ifndef GUA_U8
* ^. j+ u# |4 R7 o - typedef unsigned char GUA_U8;
( R: [ I& ]3 W; X3 ? - #endif
0 x7 i$ i4 c4 m! `; k - 0 N& a3 y5 c) K! l! G: N2 f1 ^; b% L
- #ifndef GUA_8
1 e" I9 v* l* s - typedef signed char GUA_8; 6 q6 }( ]4 ]3 |
- #endif % G; a, }# B3 u* i3 e* p
- 4 }* u9 C" F! Q/ T7 R
- #ifndef GUA_U16
8 p& [' }. @! b - typedef unsigned short GUA_U16; 9 P6 z2 t6 c' o9 @3 L9 j
- #endif . q# z9 V" h+ X/ C6 K6 I
- . c- M( }- M3 D: @4 R
- #ifndef GUA_16
l" p" W7 w3 K) Y+ q4 N5 [ - typedef signed short GUA_16;
4 h0 O" C& c3 O* u - #endif
$ \# a5 x7 M- |2 n8 O7 e- u - 8 S8 @# k& s+ \! _7 R# O. n( X
- #ifndef GUA_U32
% a1 S& q: {0 v, i - typedef unsigned long GUA_U32;
0 y% i! `! H! t3 | - #endif
# Z+ o) g l* O+ s, W -
2 S @2 G$ e8 G5 c* X# a - #ifndef GUA_32
6 B. x. Y% a9 N; j - typedef signed long GUA_32;
, P: c/ J, l9 z( A3 |- |8 j - #endif
% |" j3 T; f5 v$ S7 R7 W( @: e -
0 a9 ~3 f0 ^# ]" G4 x2 u+ T - #ifndef GUA_U64 9 G8 i+ w. D2 o' i9 D
- typedef unsigned long long GUA_U64; 5 ~& Q1 w4 n* ^& n* p
- #endif
! X9 L/ T, M5 @, f3 ?9 B, d. P -
7 y8 s: i; B& Q1 e: F' ^ - #ifndef GUA_64
/ N x2 P4 J' j: D( _1 Y' p6 R - typedef signed long long GUA_64;
) D8 W; [2 _9 J4 |% n - #endif
1 z( s7 ~5 ^0 P1 Q - ; g$ j m# }% P0 D% b0 W
- //霍尔传感器的触发状态
9 `" X9 |! Z* b) D! A+ R+ Q - #define GUA_HALL_SENSOR_STATUS_TRIGGER 0 //霍尔传感器触发$ Z6 a1 C" M! D7 p6 O1 K
- #define GUA_HALL_SENSOR_STATUS_IDLE 1 //霍尔传感器没触发, `: ?' B, B$ v7 K6 A
- #define GUA_HALL_SENSOR_STATUS_DISAPPERAS_SHAKS 2 //霍尔传感器消抖中
_5 w+ x+ x* A$ B. M: ^8 s% W9 n - ) A, Z& T+ J8 C: R# n- U: o
- /*********************外部函数声明************************/
. R* m0 d, I- g$ T$ I4 s; m - GUA_U8 GUA_Hall_Sensor_Check_Pin(void); 6 @+ @, @! F3 E7 G$ Q q& @
- void GUA_Hall_Sensor_Init(void);
( k/ J' H/ E, C6 L; q8 c! [7 U -
# {8 h# Z9 j0 @2 {2 B - #endif
复制代码
' o) m0 h3 w8 K. }' E- l3)工程中添加GUA_Hall_Sensor.c
: W W( P+ u# [ g! [; |& [8 t+ }4 {6 c
4 X) o1 q) A/ O# |7 n/ i: M4)在MDK设置中添加串口驱动源文件路径5 y! c# a$ [- S- e7 l. U7 z
. x" W1 O# M& [0 l8 v/ C
l) Y& ^+ v& H& Z/ x7 S$ J# M$ }. P
2、在应用层中调用
- w: l$ [/ H2 C
1)添加驱动头文件(main.c中) - #include "GUA_Hall_Sensor.h"
复制代码
3 R9 a4 t* M$ z9 w. l0 x( C
% }( c* n! `, S1 q/ }. w1 }- h4 v, T# F' O+ {: p
2)添加驱动初始化代码(main.c的main函数中)" I. c; {" }. Q' z0 j! g
8 t$ G, X: A% I4 ?, f( x b6 W
) V$ o/ s% i3 Q/ u1 ~0 G
' m2 s# D+ x8 P# q) p) c- GUA_Hall_Sensor_Init();
复制代码 % B w! _: j$ Z! S/ |# A
3)添加测试代码
7 d; n+ {3 C, I. U9 ?9 n' m4 C& n% k1 g* W
①写测试代码(main.c中)
7 |& d1 s8 ]- J( l9 ?- static void GUA_Test(void)
- Z* Z8 S1 A& E5 ` - {
4 L% N% h! R- Y - U8 nGUA_Ret = 0;+ M! Z- a( d' \
- U8 nGUA_Stop = 0;# N o7 A. k/ n: n
-
6 D+ E8 o5 c& C1 s. I* R2 F - while(1)
1 ~2 S J0 j, p! W& f- g4 p - {
1 S# D" K h4 p5 \/ }5 I7 f - //检测霍尔当前状态6 G) w c6 v1 W4 D2 K0 N
- nGUA_Ret = GUA_Hall_Sensor_Check_Pin();; [. T. x. g8 c4 R% z! C* b
- , R2 V4 c9 A# L- |
- //检测到霍尔被触发( ]/ b/ X) G* k
- if(nGUA_Ret == GUA_HALL_SENSOR_STATUS_TRIGGER)( G4 j3 u! E# \. w& L
- {
! S* z& e7 l" p9 T& j" O- ^) C, r - nGUA_Stop = 1;9 E: n5 Y4 S' T/ S& ^) F& K
- } 1 A( n0 S; [& @0 P6 j6 W& U
- }
2 A' e! u( g ]$ r$ Q4 {( |
复制代码
* k3 ? O$ C7 O: a8 R3 K- ]) f0 F: {- U* v+ H, a6 T# Z$ `7 I i
②调用测试代码(main.c的main函数中)3 U* X8 e' m1 [1 F5 Z+ C
- //测试代码$ A- Z( A U1 \
- GUA_Test();
复制代码 + F7 P/ @: \' \5 k* w9 a8 ?
6 Y3 I' F) s" l2 D4 r* `7 W4 T
五、实验结果 t" T' t0 V- U) z( H) V9 v/ r- G6 W
仿真并设置断点在测试代码的“nGUA_Stop = 1;”中,全速运行。 4 ^# ?! k0 R D
用磁铁去靠近模块上的霍尔传感器芯片,模块上的led被点亮表示触发,同时工程中消抖之后会停止在断点处,表示检测到PA11处的霍尔传感器触发导致的低电平。如下图
: ?8 q: i; u0 s( W! m: L+ p. i

; ~: n; l) U+ _( ~. N9 h
( x& Y. I' ^& o1 k$ C9 U: i
因此实验成功。
3 Q4 W6 \, P6 [, ~# A4 r3 U# ?7 n0 B7 q
+ u' L7 Z) j! ?5 f& R6 G5 A0 E
* o6 L& u ` J" I8 { |