基于51单片机的车速里程表项目设计
基于51单片机的车速里程表项目设计
- 背景介绍
- 备选的三个题目
- 脉冲波部分(单片机模拟信号发生器)
- 源代码1
- 接收端主程序
- 基本思路
- 源代码2
- 设计过程中遇到的问题和解决的办法
- 结束语
背景介绍
(这是本人第一次写博客,会有一些牢骚,我保证以后不会这么废话了)。本人做为一名大三学生,这个学期在学长的建议下选修了单片机课程。老师要求完成一篇大作业(三选一),我就选择了最简单的车速里程表的设计。至于我为什么要写这篇博客,是因为我在网上找到相关的资料时(类似于霍尔传感器的车速里程表设计),但是CSDN上的整个项目的源代码都要付费查看,于是我很气愤,遂有此文。
备选的三个题目
因为目测题目二最简单,所以我就选了题目二。
脉冲波部分(单片机模拟信号发生器)
由于老师实验室一下子找不出来信号发生器,所以我找同学借了一个单片机作为信号发生器,用跳线连接信号发生器的P37引脚和车速里程表的P35引脚(老师因此还表扬了我)。
源代码1
#include "reg51.h"
#include "intrins.h"typedef unsigned int u16;
typedef unsigned char u8;sbit pulse = P3^7; //用p37引脚发出脉冲void Time0Init() //中断初始化函数
{TMOD |= 0x01;TH0 = 0xfc;TL0 = 0x18; //中断定时1秒ET0 = 1;EA = 1;TR0 = 1;
}void main()
{Time0Init();while(1); //无限循环,等待中断
}void Time0() interrupt 1
{pulse = ~pulse;
}
接收端主程序
基本思路
引用一个定时器和一个计数器(我的单片机是通过p35引脚输入的,不同的单片机可能不同),定时一秒钟,计算这一秒钟内接收的脉冲个数,乘以一个系数即可得到速度(根据题目描述可计算得这个系数为1,单位为km/h),对速度进行累加即可得到里程。
源代码2
/*
车速里程表项目
输入:信号模拟器产生脉冲,通过引脚P35接入单片机
功能:显示车速,通过按键k1控制显示单次里程与总里程的切换,通过k2长按将单次里程清零
*/
#include "reg52.h"
#include "intrins.h"typedef unsigned int u16;
typedef unsigned char u8;
typedef unsigned long int ul;sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit k1=P3^1;
sbit k2=P3^0;
sbit led=P2^0; //用一个LED灯作为指示信号static u16 single_mileage=0; //单次里程
static u16 total_mileage=0; //总里程
static u16 speed=0;
static u16 realspeed=0; //speed通过realspeed传出
static u16 j=0;
static u16 temp1=0;
static u16 temp2=0;
static u16 temp3=0; //三个中间变量,在按键判断时会用到u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void delay(u16 i)
{while(i--);
}void Time0Init() //定时器初始化函数,定时10ms
{TMOD|=0x51;TH0=0xd8;TL0=0xf0;ET0=1;EA=1;TR0=1;
}void Count1Init() //计数器初始化函数
{TMOD|=0x51;TH1=0x00;TL1=0x00;ET1=1;EA=1;TR1=1;
}
/*------------------------------------------------
函数功能:获取xxxx的每一位并显示在数码管的高四位
------------------------------------------------*/
void DisplaySpeed(u16 x)
{u16 x_gewei=x/1%10;u16 x_shiwei=x/10%10;u16 x_baiwei=x/100%10;u16 x_qianwei=x/1000%10;u8 i;for(i=0;i<4;i++){switch(i){case(0):LSA=1;LSB=1;LSC=1;P0=smgduan[x_qianwei]; break;case(1):LSA=0;LSB=1;LSC=1;P0=smgduan[x_baiwei]; break;case(2):LSA=1;LSB=0;LSC=1;P0=smgduan[x_shiwei]; break;case(3): LSA=0;LSB=0;LSC=1;P0=smgduan[x_gewei]; break;}//P0=smgduan[i];delay(100);P0=0x00;}
}/*------------------------------------------------
函数功能:获取xxxx的每一位并显示在数码管的低四位
------------------------------------------------*/
void DisplayMileage(u16 x)
{u16 x_gewei=x/1%10;u16 x_shiwei=x/10%10;u16 x_baiwei=x/100%10;u16 x_qianwei=x/1000%10;u8 i;for(i=0;i<4;i++){switch(i){case(0):LSA=1;LSB=1;LSC=0;P0=smgduan[x_qianwei]; break;case(1):LSA=0;LSB=1;LSC=0;P0=smgduan[x_baiwei]; break;case(2):LSA=1;LSB=0;LSC=0;P0=smgduan[x_shiwei]; break;case(3): LSA=0;LSB=0;LSC=0;P0=smgduan[x_gewei]; break;}//P0=smgduan[i];delay(100);P0=0x00;}
}
/*-----------------------------------------------------------
主函数:将定时器和计数器初始化,并无限循环等待中断
-----------------------------------------------------------*/
void main()
{Time0Init(); //计时器0初始化Count1Init(); //计数器1初始化while(1); //无限循环
}/*-----------------------------------------------------------
中断服务函数:每过1s将计数器的值传给speed,并通过realspeed传出
-----------------------------------------------------------*/
void Time0() interrupt 1
{TH0=0xd8;TL0=0xf0;j++;if(k2==0){temp2++;}if(temp2==300){temp2=0;single_mileage=0;}if(j==100) //1s{led=~led;j=0;speed=(TH1*256+TL1); //计数传给speedsingle_mileage+=speed;total_mileage+=speed;realspeed=speed;//speed=1;TH1=0x00; //每秒计数后,需将计数器初始化TL1=0x00;speed=0;}DisplaySpeed(realspeed); //显示速度if(k1==0){_nop_();if(k1==0){temp1++;}}if(temp1<=40 && temp1>=15){temp1=0;temp3++;}if(temp3%2==1){DisplayMileage(total_mileage);}else{DisplayMileage(single_mileage);}
}
设计过程中遇到的问题和解决的办法
- 最开始的设计思路是在main函数中显示速度和里程并用delay函数判断按键的短按和长按,但是那样没办法按下k1切换里程显示,只能按下的时候显示总里程,不按的时候显示单次里程,而且在长按清零过程中数码管会闪烁。后来老师告诉我将显示函数放到中断函数中,并将单次中断改10ms,这样在长按将single_mileage清零的时候数码管就不会闪烁。(最开始我设计的中断时是1ms,在显示函数中的delay函数会对中断产生影响,这个问题将单次中断时间变长就能解决)
- 按键函数为什么不用书上的delay函数?同样是因为按键判断的软件消抖过程delay会对中断产生影响。因此定义一个变量temp,在按键按下的时候自加一,加到10就是按键按下100ms(短按),加到300就是按键按下3s(长按)。(temp1<=40 && temp1>=15)是我调试多次之后确定的基本符合短按规律的边界值。
- 第一版代码快完成的时候,发现DisplayMileage只显示0,想了半天才发现每计数都已经把speed清零了,因此定义一个变量realspeed将每次的计数结果传出。
结束语
这是我的第一篇博客,终于理解为什么程序员喜欢写博客了,写博客是真滴快乐。当然还是报着学习的态度,如有错误望网友轻喷,欢迎与我交流。QQ:37892436
基于51单片机的车速里程表项目设计相关推荐
- 【资料分享】基于51单片机的智能指纹考勤系统设计-原理图-PCB-程序-报告、基于51单片机和MAX1898的智能手机充电器设计
1661[毕设课设]基于51单片机的智能指纹考勤系统设计-原理图-PCB-程序-报告 摘 要 随着科学技术的不断发展带动着电子行业的地位越来越重,现在电子产品几乎在社会的各个领域都可以见到.这些技术的 ...
- 基于51单片机的简易mp3的制作
基于51单片机的简易mp3制作原理 1. 项目要求 基于AT89C51系列单片机的音乐播放器,采用AT89C51作为主控芯片,采用12864LCD作为液晶显示屏,通过按键实现播放器对应按键功能. 2 ...
- 基于51单片机的课程设计(毕业设计)——电子贺卡
本篇文章将介绍一个基于51单片机的电子贺卡,本作品可用于课程设计.毕业设计的参考.其所用到的外设硬件以及程序的代码量都是相对较少的,对于51单片机的初学者,通过本设计熟悉51单片机的使用是非常好的选择 ...
- 基于51单片机室内室外环境检测仪控制设计
本项目设计是基于51单片机的时钟+温湿度+PM2.5+12864B液晶屏DIY制作的毕业设计,也可以应用于室内环境检测仪.该室内环境检测系统,时间采用专门的DS1302时钟芯片,温湿度采用DHT22模 ...
- 基于单片机的超市储物柜设计_基于51单片机对电子储物柜系统的设计
电路描述: 安全是我们日常的生活中最关心的问题. 每个人都觉得安全问题是非常至关重要的,在家里的门和安全,可以尽可能多的安全. 为了对于门访问安全 因此,我们打算通过引进一个电子密码锁系统,该系统包括 ...
- C语言 | 基于51单片机实现MPU6050的卡尔曼滤波算法(代码类2)
github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 之前写过一个博客(代码分享:单片机开发 | ...
- 共阳极数码时钟c语言程序,基于51单片机C语言数字钟程序.doc
基于51单片机C语言数字钟程序 基于51单片机C语言数字钟程序 数字电子钟的设计 一. 绪论 (一)引言 20世纪末,电子技术获得了飞速的发展,在其推动下,现代电子产品几乎渗透了社会的各个领域,有力地 ...
- 51单片机计算机实物焊接,基于51单片机的最小系统焊接图 浅谈单片机最小系统...
本文主要是关于51单片机的相关介绍,并对基于51单片机的最小系统焊接进行了详尽的阐述. 单片机最小系统 单片机最小系统主要由电源.复位.振荡电路以及扩展部分等部分组成. 对于一个完整的电子设计来讲,首 ...
- 简易电子钟c语言程序,(最新整理)基于51单片机的电子钟C语言程序
<(最新整理)基于51单片机的电子钟C语言程序>由会员分享,可在线阅读,更多相关<(最新整理)基于51单片机的电子钟C语言程序(9页珍藏版)>请在人人文库网上搜索. 1.完整) ...
最新文章
- 嵌入式linux应用程序升级,基于嵌入式Linux平台的应用升级机制的研究与设计
- poj2096_概率dp
- [微信开发] 微信网页授权Java实现(https://www.cnblogs.com/lovebread/p/5513241.html)
- 爬虫必须得会的预备知识
- [SCOI 2010]传送带
- CentOS 快速安装pip
- HDU4394(数论中的广搜)
- JavaSE各阶段练习题----多线程-垃圾回收
- 关于 extern C的说明
- Exynos4412 Uboot 移植(四)—— Uboot引导内核过程分析
- 起到的C++是中间层的作用
- [Axios] FETCH中的基础语法
- day16 java的访问控制权限
- AndroidStudio新建项目报错build failed
- Tomcat学习总结(13)—— Tomcat常用参数配置说明
- oppo手机解锁_手机解锁新风尚,OPPO的光域屏幕指纹技术又是哪根儿葱
- R包制作(千字详细图文)
- codejock(codejock chart类)
- c程序设计第五版谭浩强课后答案 第四章习题答案
- 【AI视野·今日CV 计算机视觉论文速览 第235期】Mon, 27 Sep 2021