系统描述
基于51单片机红外高速测速仪,两个按键模拟红外光电开关,按下开始键开始计时,按下结束键结束计时,系统记录时间并计算出速度显示在1602液晶屏上,并且支持串口打印数据。
资料下载地址:基于51单片机红外高速汽车测速仪表设计
硬件设计
仿真图1:
仿真图2:
程序设计
部分程序
#include<reg52.h>
#include "stdio.h"
#include "string.h"
#define uchar unsigned char
#define uint unsigned int
uchar tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0X88,0x83,0xC6,0xA1,0x86,0x8E};
char a = 2,b;
uchar totalnumstr[20] = {0};
long int totalnum = 0;
long int num = 0;
uchar mSendSta = 0;
uchar mSendCounts = 0;
sbit KeyAdd = P3^2;
sbit KeyMinus = P3^3;
sbit rs=P2^0; //寄存器选择信号 H:数据寄存器 L:指令寄存器
sbit rw=P2^1; //寄存器选择信号 H:数据寄存器 L:指令寄存器
sbit e =P2^2; //片选信号 下降沿触发
void send(uchar* state,uchar num);
/***********************1ms延时函数*****************************/
void delay_1ms(uint q)
{
uint i,j;
for(i=0;i<q;i++)
for(j=0;j<110;j++);
}
/********************************************************************
* 名称 : delay_uint()
* 功能 : 小延时。
* 输入 : 无
* 输出 : 无
***********************************************************************/
void delay_uint(uint q)
{
while(q--);
}
/********************************************************************
* 名称 : write_com(uchar com)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void write_com(uchar com)
{
e=0;
rs=0;
rw=0;
P0=com;
delay_uint(25);
e=1;
delay_uint(100);
e=0;
}
/********************************************************************
* 名称 : write_data(uchar dat)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write_data(uchar dat)
{
e=0;
rs=1;
rw=0;
P0=dat;
delay_uint(25);
e=1;
delay_uint(100);
e=0;
}
/********************************************************************
* 名称 : write_string(uchar hang,uchar add,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
write_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void write_string(uchar hang,uchar add,uchar *p)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
while(1)
{
if(*p == '\0') break;
write_data(*p);
p++;
}
}
/***********************lcd1602上显示特定的字符************************/
void write_zifu(uchar hang,uchar add,uchar date)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
write_data(date);
}
/***********************lcd1602上显示两位十进制数************************/
void write_1(uchar hang,uchar add,uint date)
{
if(hang==1)
{
write_com(0x80+add);
write_data(0x30+date);
}
}
void write_2(uchar hang,uchar add,uint date)
{
if(hang==2)
{
write_com(0x80+0x40+add);
write_data(0x30+date/1000);
write_data(0x30+date%1000/100);
write_data(0x30+date%100/10);
write_data(0x30+date%100%10);
}
}
/***********************lcd1602初始化设置************************/
void init_1602()
{
write_com(0x38); //
write_com(0x0c);
write_com(0x06);
delay_uint(1000);
// write_string(1,0," Number: ");
//
// write_string(2,0," Level: ");
//
}
void delayms(uint ms)
{
uint i;
while(ms--)
{
for(i=0;i<120;i++);
}
}
void keyscan()
{
if(KeyAdd == 0)
{
delayms(10);
if(KeyAdd == 0)
{
TR0 = 1;//打开定时器开始计时
mSendSta = 0;
while(!KeyAdd);
}
}
else if(KeyMinus == 0)
{
delayms(10);
if(KeyMinus == 0)
{
TR0 = 0;//关闭定时器
mSendSta = 1;//显示速度
totalnum = 8000 / num / 20;
num = 0;
while(!KeyMinus);
}
}
}
void int0() interrupt 0
{
// delayms(10);
// if(INT0==0)
// {
// a--;
// if(a==0)
// {a=9;}
// }
}
void int1() interrupt 2
{
//delayms(10);
//if(INT1==0)
//{
//a++;
//if(a==9)
//{a=0;}
//}
}
void disp(void)
{
P2=0X01;
P0=tab[b/10];
delayms(1);
P2=0x02;
P0=tab[b%10];
delayms(1);
}
void send(uchar* state,uchar num)
{
uchar i = 0;
for(i = 0 ; i < num ; i++)
{
SBUF=state[i];
while(TI==0);
TI=0;
}
}
void receive() interrupt 4
{
if(RI)
{
RI=0;
b=SBUF;
}
}
附: