马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
一、项目整体概述(知识分享)$ ~9 S: a& P8 u; G, u. ?2 q
3 |% c: P5 j1 G) d. R6 L7 m6 T
" i1 c5 a1 y1 }( X" z# y/ s( D
1. 设计目标
' a% \ s) G! R& |! n: j8 x- g3 \& K, p
) e, p8 ~# J7 A7 N& c
% s3 q9 T: Z, O$ t: t) j以 STC89C51 单片机为核心,实现自行车实时速度、累计里程采集与 LCD1602 显示,内置超速预警功能,速度超标时 LED + 蜂鸣器声光提醒;搭配独立按键一键清零里程数据,支持 Proteus 仿真验证与实物焊接调试,整套系统稳定可靠,具备实际落地价值。
' _/ A8 r4 \+ D* N) J E* l* \& i) q: x2 K7 G: b; Q5 ~9 x
2. 核心硬件选型与原理知识点
/ ?) f! f$ \) b: N! k: w8 l- U( l6 n
, |' C: B) V: o# m# ]
- 主控:STC89C51 单片机' O+ r3 T/ B: T. H; N/ S) w9 \1 P( M
$ b( Z k+ {& tMCS-51 架构 8 位单片机,自带定时器、外部中断、IO 口资源,是嵌入式入门首选;本项目用到定时器 0 定时计时、外部中断 0 捕获脉冲两大核心外设,是单片机面试高频考点。 - 采集模块:AH3503 霍尔传感器( ]4 O+ g6 p+ z6 I8 ?7 D
* K7 x% _& Q$ D基于霍尔效应非接触式检测,车轮每旋转一圈输出 1 个脉冲;磁铁固定车轮、传感器固定车架,无机械磨损、抗干扰强,脉冲信号接入单片机 INT0 引脚计数。 - 显示模块:LCD1602 液晶' \; g8 U6 W( Y- _
7 H2 e+ h- K" ~& k/ Q8 G- d两行字符液晶,驱动简单、成本低,实时刷新当前速度、总里程数据。 - 预警模块:LED + 有源蜂鸣器
9 q: ]2 X$ |# e! i7 [, v. }% Y1 X) d
P1 口驱动,车速超过设定阈值同时点亮 LED、蜂鸣器鸣响,速度回落自动关闭报警。 - 输入模块:独立复位按键
3 r2 Q& e( }6 m {+ G1 \
* `2 a8 ]: @1 U& h按键触发清空累计里程、圈数计数,重新开始统计。 - 电源:LM7805 稳压电路' y, ~( M, k8 ]% p5 m, w
) ?2 U' `5 G8 j0 X) ~将外部输入电压转为稳定 5V,为整套单片机系统供电。
, w8 Z i z7 k3 D) J0 j $ V, P7 |- C' y6 v. Y2 W
3. 测速里程计算核心原理(干货技能)9 ^" H1 @, q- w5 _8 {/ A4 v! r( E2 |
2 ?+ q V- v) y, e
0 J! e* ~! \% {. v( ~% W0 a
# f9 g" F( B P. ~( v+ i已知车轮直径 D,车轮周长 L=π×D;
' |5 j: A8 p, y9 R4 R* K" ]# V4 O6 [, F. r, N% X2 g) Q
- 里程:每检测 1 个脉冲代表车轮转 1 圈,总里程 = 总圈数 × 周长;
- 瞬时速度:通过定时器固定 1 秒统计脉冲圈数,速度 = 1 秒内圈数 × 车轮周长;
5 n; o5 ^( T9 }3 V0 o1 L L3 x
4 _: o' |0 s9 C: J- C本项目采用 26 英寸车轮,直径 0.66m,程序中直接代入参数运算。
; s# C4 S5 X. k5 m L/ h2 H2 L C/ A; a- G' P( A6 V; Y$ m
二、系统整体架构(技能拆解)
' O$ K$ Y v% ^5 {+ s
* m1 |& W: R- \+ R* A' y+ N2 B' C+ E4 ^' y
1. 硬件架构组成% B3 n6 R! ?# r/ ^8 d7 }2 k
/ u( ~3 Q) r' l7 V; }6 N' B: a
6 V0 t: y" t) @' _) e
& s# L5 {! U, Q* j. p整套系统分为 6 大电路模块,可单独模块化学习:9 w6 y* r$ |& `- t5 `2 V
8 I7 |; i. h' C" s; X- STC89C51 最小系统(晶振 + 复位)
- AH3503 霍尔脉冲采集电路
- LCD1602 液晶显示驱动电路
- LED + 蜂鸣器声光报警电路
- 独立按键清零电路
- LM7805 稳压电源电路
8 l7 c# b( {3 [+ K$ S1 R/ K
: l/ x. d6 O' p/ \7 f硬件逻辑:霍尔产生脉冲→外部中断计数;定时器每秒统计脉冲数量→运算速度、里程;LCD 刷新数据;阈值判断控制报警;按键触发数据清零。
! N- S! |: b2 z" S; S 5 D" }% a' J1 N# K8 W& T/ L
2. 软件程序架构) `: y. J) R. i: S" C
4 y' C" V6 e7 h, I; {! h
* s2 \& u9 [ V+ W+ K! N* Q3 g
, l4 P& ]4 p) G) T9 m8 L软件采用模块化编程,分 5 大函数模块,分层清晰便于二次开发:
' o: h, L2 u5 }: V6 ~9 {
# @, }' p& g# c- 系统初始化:LCD、定时器、外部中断初始化
- 外部中断 0 服务函数:捕获霍尔脉冲,车轮圈数 + 1
- 定时器 0 中断:50ms 定时累计,1 秒执行一次数据运算
- LCD1602 显示函数:刷新速度、里程数值
- 按键扫描函数:检测按键,清零全部统计数据) _: ~& v+ Y2 _. B
% i: a- ^* J' Q7 b4 S
程序主循环持续轮询按键,中断后台独立完成计数、计时,不阻塞主流程,掌握中断并发处理嵌入式核心开发思想。6 K, {3 X, X. t0 ?
% Q* Y1 R/ T7 v# v- T$ P6 U, R- w
三、核心代码分享(可直接编译运行,Keil C51)
( O' b( Z! X- I
& I) g7 O7 U' F) N( ~5 `3 r3 [/ C! |
1. 头文件与全局定义7 y4 E- s# s* D: Y
' d" A k7 G4 m9 X# \5 O' }4 F7 F
+ W3 ]3 F- V* o, n# i o9 V- #include<reg52.h>
% D* n% l; r" G+ F9 U - #include "LCD1602.h" //LCD1602驱动头文件3 k$ p# j0 I5 f3 y, w3 x
- #define uchar unsigned char8 s7 T* m* \/ p. `; ?5 m, I
- #define uint unsigned int% d3 H: u0 n2 v) w
- h" `; O, \- f, `
- //IO口定义
& i k3 A+ q! y/ B - sbit key1=P3^7; //清零按键$ Y# r% F- S1 h8 r( o. l
- sbit led=P1^7; //超速指示灯
0 P( K) S' t$ `7 O - sbit bz=P1^6; //蜂鸣器: g) G% p7 o* z: e: Y) F
4 q1 Y' j5 X! @$ B3 A- //全局统计变量4 `) x, G/ S. e1 W$ A5 Y" b; |
- uchar time50ms=0; //50ms计时计数器
v" Z* Q$ u7 v( c* ~) a+ | - uint cylinder_number=0;//1秒内车轮圈数
3 b, Z4 C+ U# ^ - uint Total_number_of_cycles=0;//总圈数
/ h! _) m7 ~' E/ _& W* D9 t. z - uint Distance=0; //总里程' y6 W& h: A( E" p) z# e8 Y& y1 q
- uint Speed=0; //瞬时速度) z: H, k4 ]9 _+ C8 _" H
复制代码 2. 定时器 0 初始化(50ms 定时)# V0 V" S7 t* l) L* w! ?
- void InitTimer0(void)
2 [1 l7 R/ b: L' ^ - {
+ y& k, b/ |9 }& d6 @* y3 ~" } - TMOD = 0x01; //定时器0模式1,16位定时
" @( n2 N8 @, y# K$ b - TH0 = 0x3C;. }) g4 E* Y; a2 {( _6 E* C* X& k
- TL0 = 0xB0; //50ms定时初值
0 H; [0 G$ I) m - EA = 1; //开启总中断& _2 A) s, s* H2 _2 `
- ET0 = 1; //定时器0中断使能6 D+ Y8 w3 u5 c) E! `4 @
- TR0 = 1; //启动定时器0% `1 J0 Z# K# F" u# K( o
- }
复制代码 3. 外部中断 0 初始化(霍尔脉冲捕获)9 l/ c( D/ p5 J/ l# i0 N& J) f
- void Ex_Init(void); K# {% }: f5 m4 J
- {
+ G2 p3 ^' V- {+ c5 N - IT0 = 1; //下降沿触发外部中断0" v4 ^4 ]6 o1 P1 _: r
- EX0 = 1; //外部中断0使能
$ v; {- M4 F' @ - EA = 1;
! O$ z, J6 V; g9 W7 P - }
复制代码 4. 外部中断 0 服务函数(脉冲计数)
8 \; r/ C5 Y8 U- void int0_interrupt(void) interrupt 09 q- A3 V6 n3 M* ^
- {
3 o8 x* n3 D7 q" q8 C1 B - cylinder_number++; //每来一个脉冲,圈数+1
" I+ L2 n; l% o( B# V - }
复制代码 5. 定时器 0 中断服务函数(1 秒计算速度里程)
4 i9 P0 u+ a& p/ y0 {, s- void Timer0Interrupt(void) interrupt 1/ O1 Y8 `( R* f; V r I4 J6 u
- {5 [9 G2 U3 B) B; ?( G
- //重装50ms初值
( f5 g2 o, Q9 n6 j; D9 l - TH0 = 0x3C;
3 p; I, m# E8 | V - TL0 = 0xB0;. e" B4 u8 r7 w7 L+ R0 K6 v# {
- time50ms++;$ Q2 X: k7 e L( _9 C0 ^
- * `3 o+ T( A7 \3 i
- //20次50ms=1s,每秒计算一次数据( n5 T; H0 B1 X5 a5 b7 D" \( S
- if(time50ms >= 20)
% A7 J4 p* n* N6 k2 ?2 b/ |0 }9 @$ S3 l - {2 C* `1 J; j/ {3 ?$ X% X
- Total_number_of_cycles += cylinder_number;
; ?6 M" y P8 A; h& w( q - //计算总里程:总圈数*π*0.66m,放大10倍保留小数
' b$ b; x9 }) d- k1 g! r - Distance = (uint)(Total_number_of_cycles * 3.14 * 0.66 * 10);
. ?+ m7 t- x( z5 G - //计算瞬时速度5 D1 T1 N. o3 `
- Speed = cylinder_number * 3.14 * 0.66 * 10;/ A/ t* V( c5 O0 i# \9 B* k0 k
-
$ r0 e9 g0 i T - //LCD刷新显示. B' w4 t g4 E) y! x: R* u7 [
- LcdDisplayTemp(Distance, Speed);
- ~& k% `6 Y1 c! S - 3 X! f. G' O; A! k5 e
- //超速判断:速度大于100触发声光报警2 W/ q9 H) I0 A3 L; p$ x4 U
- if(Speed > 100)+ u, t1 ~6 _/ `
- {& O$ y3 A9 F) F a, Y! r
- led = 1;8 `' @2 O3 K' F2 a& a: S
- bz = 1;
: v* l! d2 ]! ~ P+ b% J - }/ g1 i/ s8 ~% W# \. w* c
- else
1 u' v8 P- v5 l# G1 t& K! g0 \ - {/ P( F' G/ P4 E& S i
- led = 0;
) ]0 v1 L$ J& m8 a0 T - bz = 0;* P1 X0 H2 i$ s# h6 T
- }
$ T& Q% s# G! p - //重置1秒计数变量
, O( u# W6 i( y - time50ms = 0;
% N' _! x& S& `* o# X% a - cylinder_number = 0;
; R$ V# }- o9 D: K - }
& c9 B- Q" F6 q; x/ ~* Z s - }
复制代码 6. 按键检测函数(清零里程)
) b( |+ U& l1 o- f4 W# p/ {- void getkey(void)
# k( |( e! l( G( k/ R, n - {
7 F) _- H2 L/ `" P& q - if(key1 == 0), ~$ Z. X5 ^3 z( p
- {5 ?: p+ A2 D5 s. l @
- //清空所有统计数据
) n: _ D; G8 P) U) H H - Total_number_of_cycles = 0; u$ m% f/ U, h9 C7 ~
- Distance = 0;& l. ?' A/ a( N* @3 a% s9 L
- Speed = 0;
" O1 x: k+ s( y, | - cylinder_number = 0;5 q5 ^! Q' ]+ ^7 u2 _5 |
- time50ms = 0;$ v" l4 i) y E; r. |
- LcdDisplayTemp(Distance, Speed);. n( R J: ^+ w2 U |
- }
3 a1 m/ T- ]! \ D7 k9 K6 o - }
复制代码 7. 主函数入口
9 ], H3 G: `5 o, [* l5 s5 Q- void main(void)
9 j( N1 j6 K" U8 O& T6 V - {
& y: i9 z- O* ?, G0 H - LCD1602_Init(); //液晶初始化
( z: y- m2 z; ^ V, s2 h - InitTimer0(); //定时器初始化
& |: }% Z Z4 N* M0 Y5 E9 W+ t# o - Ex_Init(); //外部中断初始化
' T+ }: P* g0 h1 I! p - LcdDisplayTemp(Distance, Speed);) r$ D9 a& q1 I! b: k9 {7 d
- " r& p) z3 B# M0 S% v
- while(1): T3 @* _- N9 m) g9 k5 f9 B
- {: J) X% s* Q: c6 T ]
- getkey(); //循环扫描按键
8 M( O; X. B$ r5 Z6 ?8 ]$ ~9 _ - }( U+ d# b6 d0 v- }1 E+ q0 `
- }
复制代码
6 q- d& \4 r! N' O6 D/ b' X% B! ~7 b7 M. ?7 h
0 D: B2 ?8 d/ r3 {2 N; X
" E9 y% N- i: f
" ^9 z* j( B6 z: a2 o! S; F P
2 }5 I% C2 ]& U& Q
+ _, y7 M8 [6 `+ ~( J
3 [; f' K) l$ H! Z) j |
|