马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
一、项目整体概述(知识分享)
1. 设计目标
以 STC89C51 单片机为核心,实现自行车实时速度、累计里程采集与 LCD1602 显示,内置超速预警功能,速度超标时 LED + 蜂鸣器声光提醒;搭配独立按键一键清零里程数据,支持 Proteus 仿真验证与实物焊接调试,整套系统稳定可靠,具备实际落地价值。
2. 核心硬件选型与原理知识点
- 主控:STC89C51 单片机
MCS-51 架构 8 位单片机,自带定时器、外部中断、IO 口资源,是嵌入式入门首选;本项目用到定时器 0 定时计时、外部中断 0 捕获脉冲两大核心外设,是单片机面试高频考点。 - 采集模块:AH3503 霍尔传感器
基于霍尔效应非接触式检测,车轮每旋转一圈输出 1 个脉冲;磁铁固定车轮、传感器固定车架,无机械磨损、抗干扰强,脉冲信号接入单片机 INT0 引脚计数。 - 显示模块:LCD1602 液晶
两行字符液晶,驱动简单、成本低,实时刷新当前速度、总里程数据。 - 预警模块:LED + 有源蜂鸣器
P1 口驱动,车速超过设定阈值同时点亮 LED、蜂鸣器鸣响,速度回落自动关闭报警。 - 输入模块:独立复位按键
按键触发清空累计里程、圈数计数,重新开始统计。 - 电源:LM7805 稳压电路
将外部输入电压转为稳定 5V,为整套单片机系统供电。
3. 测速里程计算核心原理(干货技能)
已知车轮直径 D,车轮周长 L=π×D;
- 里程:每检测 1 个脉冲代表车轮转 1 圈,总里程 = 总圈数 × 周长;
- 瞬时速度:通过定时器固定 1 秒统计脉冲圈数,速度 = 1 秒内圈数 × 车轮周长;
本项目采用 26 英寸车轮,直径 0.66m,程序中直接代入参数运算。
二、系统整体架构(技能拆解)
1. 硬件架构组成
整套系统分为 6 大电路模块,可单独模块化学习:
- STC89C51 最小系统(晶振 + 复位)
- AH3503 霍尔脉冲采集电路
- LCD1602 液晶显示驱动电路
- LED + 蜂鸣器声光报警电路
- 独立按键清零电路
- LM7805 稳压电源电路
硬件逻辑:霍尔产生脉冲→外部中断计数;定时器每秒统计脉冲数量→运算速度、里程;LCD 刷新数据;阈值判断控制报警;按键触发数据清零。
2. 软件程序架构
软件采用模块化编程,分 5 大函数模块,分层清晰便于二次开发:
- 系统初始化:LCD、定时器、外部中断初始化
- 外部中断 0 服务函数:捕获霍尔脉冲,车轮圈数 + 1
- 定时器 0 中断:50ms 定时累计,1 秒执行一次数据运算
- LCD1602 显示函数:刷新速度、里程数值
- 按键扫描函数:检测按键,清零全部统计数据
程序主循环持续轮询按键,中断后台独立完成计数、计时,不阻塞主流程,掌握中断并发处理嵌入式核心开发思想。
三、核心代码分享(可直接编译运行,Keil C51)
1. 头文件与全局定义
- #include<reg52.h>
- #include "LCD1602.h" //LCD1602驱动头文件
- #define uchar unsigned char
- #define uint unsigned int
- //IO口定义
- sbit key1=P3^7; //清零按键
- sbit led=P1^7; //超速指示灯
- sbit bz=P1^6; //蜂鸣器
- //全局统计变量
- uchar time50ms=0; //50ms计时计数器
- uint cylinder_number=0;//1秒内车轮圈数
- uint Total_number_of_cycles=0;//总圈数
- uint Distance=0; //总里程
- uint Speed=0; //瞬时速度
[color=rgb(242, 23, 23) !important]复制代码
2. 定时器 0 初始化(50ms 定时)
- void InitTimer0(void)
- {
- TMOD = 0x01; //定时器0模式1,16位定时
- TH0 = 0x3C;
- TL0 = 0xB0; //50ms定时初值
- EA = 1; //开启总中断
- ET0 = 1; //定时器0中断使能
- TR0 = 1; //启动定时器0
- }
[color=rgb(242, 23, 23) !important]复制代码
3. 外部中断 0 初始化(霍尔脉冲捕获)
- void Ex_Init(void)
- {
- IT0 = 1; //下降沿触发外部中断0
- EX0 = 1; //外部中断0使能
- EA = 1;
- }
[color=rgb(242, 23, 23) !important]复制代码
4. 外部中断 0 服务函数(脉冲计数)
- void int0_interrupt(void) interrupt 0
- {
- cylinder_number++; //每来一个脉冲,圈数+1
- }
[color=rgb(242, 23, 23) !important]复制代码
5. 定时器 0 中断服务函数(1 秒计算速度里程)
- void Timer0Interrupt(void) interrupt 1
- {
- //重装50ms初值
- TH0 = 0x3C;
- TL0 = 0xB0;
- time50ms++;
- //20次50ms=1s,每秒计算一次数据
- if(time50ms >= 20)
- {
- Total_number_of_cycles += cylinder_number;
- //计算总里程:总圈数*π*0.66m,放大10倍保留小数
- Distance = (uint)(Total_number_of_cycles * 3.14 * 0.66 * 10);
- //计算瞬时速度
- Speed = cylinder_number * 3.14 * 0.66 * 10;
- //LCD刷新显示
- LcdDisplayTemp(Distance, Speed);
- //超速判断:速度大于100触发声光报警
- if(Speed > 100)
- {
- led = 1;
- bz = 1;
- }
- else
- {
- led = 0;
- bz = 0;
- }
- //重置1秒计数变量
- time50ms = 0;
- cylinder_number = 0;
- }
- }
[color=rgb(242, 23, 23) !important]复制代码
6. 按键检测函数(清零里程)
- void getkey(void)
- {
- if(key1 == 0)
- {
- //清空所有统计数据
- Total_number_of_cycles = 0;
- Distance = 0;
- Speed = 0;
- cylinder_number = 0;
- time50ms = 0;
- LcdDisplayTemp(Distance, Speed);
- }
- }
[color=rgb(242, 23, 23) !important]复制代码
7. 主函数入口
- void main(void)
- {
- LCD1602_Init(); //液晶初始化
- InitTimer0(); //定时器初始化
- Ex_Init(); //外部中断初始化
- LcdDisplayTemp(Distance, Speed);
- while(1)
- {
- getkey(); //循环扫描按键
- }
- }
[color=rgb(242, 23, 23) !important]复制代码
[color=rgb(242, 23, 23) !important]
[color=rgb(242, 23, 23) !important]
[color=rgb(242, 23, 23) !important]
[color=rgb(242, 23, 23) !important]
[color=rgb(242, 23, 23) !important]
|