基于51单片机的教室车辆计数器报警proteus仿真原理图PCB

功能:
0.本系统采用STC89C52作为单片机
1.LCD1602液晶实时显示进出计数和当前总数
2.系统设计有四个功能按键,按键可设定总数上限阈值,超过上限,系统将报警
3.报警电路由蜂鸣器和LED组成的声光报警
4.采用DC002作为电源接口可直接输入5V给整个系统供电
5.计数传感器采用的是红外光电传感器,该传感器最远测试距离可达到0.8米,能够满足使用场景

原理图:
在这里插入图片描述

PCB :
在这里插入图片描述

主程序:

#include <reg52.h>	         //调用单片机头文件
#define uchar unsigned char  //无符号字符型 宏定义	变量范围0~255
#define uint  unsigned int	 //无符号整型 宏定义	变量范围0~65535
#include <intrins.h>
#include <stdio.h>

#define OSC 11059200 //11.0592MHz
// #define OSC 12000000 //12MHz
// 定时器寄存器值预处理
#define BAUDRATE 9600
#define RH_UART (256-((OSC/12/32) / BAUDRATE))

bit flag_500ms;
sbit BEEP = P2^2; //蜂鸣器IO口定义 

sbit INFRARED_IN  = P2^0;   //红外传感器IO口定义 
sbit INFRARED_OUT = P2^1;   //红外传感器IO口定义 

sbit LCD_RS=P2^7;	 //寄存器选择信号 H:数据寄存器  	L:指令寄存器
sbit LCD_RW=P2^5;	 //寄存器选择信号 H:数据寄存器  	L:指令寄存器
sbit LCD_EN =P2^6;	 //片选信号   下降沿触发

uchar a_a;
uchar menu_1;	   	//设置参数用

uint num;  //计的数
uint jin,chu;
uchar set_num = 10; // 设置预警值

bit oldPinState1 = 0;
bit nowPinState1 = 0;
bit oldPinState2 = 0;
bit nowPinState2 = 0;
bit sendFlag = 1;


void DelayUs10x(unsigned char t)
{
    do
    {
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
    } while (--t);
}

void Timer0_Init()
{
    TMOD &= 0xF0; //Timer0 16位装载
    TMOD |= 0x01;
	TL0 = 0x00;		//设置定时初始值
	TH0 = 0x4C;		//设置定时初始值 50ms
	TR0 = 1; //开启T0计时
    ET0 = 1; //打开T0中断
    EA = 1;  //打开总中断
}

void UART0_Init()
{
    SCON = 0x50;
    TMOD &= 0x0F;
    TMOD |= 0x20; //8位自动重装
    TH1  = RH_UART;
    TL1  = TH1;
    ET1  = 0; //禁止T1中断
    TR1  = 1; //启动T1计时
    //ES   = 1; //打开串口中断
    EA   = 1; //打开总中断
}

void UART0_SendByte(unsigned char dat) //串口发送单字节数据
{
	unsigned char time_out;
	time_out = 0x00;
	SBUF = dat;						  //将数据放入SBUF中
	while ((!TI) && (time_out < 100)) //检测是否发送出去
	{
		time_out++;
		DelayUs10x(2);
	}		//未发送出去 进行短暂延时
	TI = 0; //清除ti标志
}

void UART0_SendStr(unsigned char *str) //发送定长度字符串
{
	unsigned char *tmp;
	unsigned char cnt = 0;
	unsigned char length = 0;

	tmp = str;
	while (*(tmp++) != '\0')
	{
		length++;
	}

	while (cnt < length) //发送长度对比
	{
		UART0_SendByte(*str); //发送单字节数据
		str++;		  //指针++
		cnt++;		  //下一个++
	}
}

/***********************1ms延时函数*****************************/
void delay_1ms(uint q)
{
	uint i,j;
	for(i=0;i<q;i++)
		for(j=0;j<120;j++);
}

/********************************************************************
* 名称 : delay_uint()
* 功能 : 小延时。
* 输入 : 无
* 输出 : 无
***********************************************************************/
void delay_uint(uint q)
{
	while(q--);
}

/********************************************************************
* 名称 : write_com(uchar com)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void write_com(uchar com)
{
	LCD_EN=0;
	LCD_RS=0;
	LCD_RW=0;
	P0=com;
	delay_uint(25);
	LCD_EN=1;
	delay_uint(100);
	LCD_EN=0;
}

/********************************************************************
* 名称 : write_data(uchar dat)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write_data(uchar dat)
{
	LCD_EN=0;
	LCD_RS=1;
	LCD_RW=0;
	P0=dat;
	delay_uint(25);
	LCD_EN=1;
	delay_uint(100);
	LCD_EN=0;	
}


/***********************lcd1602上显示四位十进制数************************/
void write_sfm4(uchar hang,uchar add,uint date)
{
	if(hang==1)   
		write_com(0x80+add);
	else
		write_com(0x80+0x40+add);
	write_data(0x30+date/1000%10);
	write_data(0x30+date/100%10);
	write_data(0x30+date/10%10);
	write_data(0x30+date%10);	
}

/***********************lcd1602上显示这字符函数************************/
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 init_1602()	//lcd1602初始化
{
	write_com(0x38);	
	write_com(0x0c);
	write_com(0x06);
	delay_uint(1000);
	write_string(1,0,"     Z:0000       ");	
	write_string(2,0," J:0000  C:0000   ");	
	write_sfm4(2,3,jin);  //显示人数
	write_sfm4(1,7,num);  //显示人数
	write_sfm4(2,11,chu);  //显示人数
}


/********************独立按键程序*****************/
uchar key_can;	 //按键值

void key()	     //独立按键程序
{
	static uchar key_new;
	key_can = 20;               //按键值还原
	P3 |= 0x78;
	if((P3 & 0x78) != 0x78)		//按键按下
	{
		delay_1ms(1);	     	//按键消抖动
		if(((P3 & 0x78) != 0x78) && (key_new == 1))
		{						//确认是按键按下
			key_new = 0;
			switch(P3 & 0x78)
			{
				case 0x70: key_can = 1; break;	   //得到k1键值
				case 0x68: key_can = 2; break;	   //得到k2键值
				case 0x38: key_can = 3; break;	   //得到k3键值
                case 0x58: key_can = 4; break;	   //得到k4键值
			}
		}			
	}
	else 
		key_new = 1;	
}

/****************按键处理LCD显示函数***************/
void key_with()
{
	if(key_can == 1)	//设置键
	{
		menu_1 ++;
		if(menu_1 >= 2)
		{
			menu_1 = 0;
			init_1602();  //lcd1602初始化			
		}
		if(menu_1 == 1)				 //初始化显示
		{
			write_string(1,0,"  SET Z Alarm    ");
			write_string(2,0,"                 ");
			write_sfm4(2,6,set_num);  //显示人数
		}
	}
	if(menu_1 == 0)   			
	{ 		
		if(key_can == 4)  //清零
		{
			num = 0;
			jin = 0;
			chu = 0;
			write_sfm4(2,3,jin);  //显示人数
			write_sfm4(1,7,num);  //显示人数
			write_sfm4(2,11,chu);  //显示人数
		}
		
	}
	if(menu_1 == 1)			
	{
		if(key_can == 2)
		{
			set_num ++ ;		// 设置数加
			if(set_num > 99)
				set_num = 99;	//最大加到99	
		}
		if(key_can == 3)
		{
			set_num -- ;		// 设置数减
			if(set_num <= 1)
				set_num = 1;	//最大减到1
		}
		write_sfm4(2,6,set_num);  //显示人数
		write_com(0x80+0x40+6);             //将光标移动到秒个位
		write_com(0x0f);                    //显示光标并且闪烁	
	}
	BEEP = 0;	  //打开蜂鸣器
	delay_1ms(50);
	BEEP = 1;	  //关闭蜂鸣器
	
}  

/******************红外计数**********************/	   
void hw_jin_dis()	//红外计数
{

    nowPinState1 = INFRARED_IN;
    if (oldPinState1 == 1 && nowPinState1 == 0) //检测到下降沿
    {
		delay_1ms(100);
		if (INFRARED_IN == 0) //确定低电平
		{
			jin ++;
			if(jin >= 99)
				jin = 99;
			num  = jin - chu;	  //计算总人数
			if(menu_1 == 0)
			{
				write_sfm4(2,3,jin);  //显示人数
				write_sfm4(1,7,num);  //显示人数
			}
		}
    }
    oldPinState1 = nowPinState1;

}

/******************红外计数**********************/	   
void hw_chu_dis()	//红外计数
{
    nowPinState2 = INFRARED_OUT;
    if (oldPinState2 == 1 && nowPinState2 == 0) //检测到下降沿
    {
		delay_1ms(100);
		if (INFRARED_OUT == 0) //确定低电平
		{
			if(jin > chu)
			chu ++;
			if(chu >= 99)
				chu = 99;
			num  = jin - chu;	  //计算总人数
			if(menu_1 == 0)
			{
				write_sfm4(2,11,chu);  //显示人数
				write_sfm4(1,7,num);  //显示人数
			}
		}
    }
    oldPinState2 = nowPinState2;
}


/******************主程序**********************/	   
void main()
{
    unsigned char dis[16];

	BEEP = 0;				    //开机蜂鸣器叫一声
	delay_1ms(100);
	P0 = P1 = P2 = P3 = 0xff;   //初始化IO口
	Timer0_Init();
	UART0_Init();
	init_1602();	//lcd1602初始化
	while(1)
	{
		hw_jin_dis();	//红外计数	
		hw_chu_dis();	//红外计数	
		if(menu_1 == 0)	 //扫描显示倒计时数
		{	 
			if(flag_500ms == 1)
			{
				flag_500ms = 0;
				if(num > set_num)
					BEEP = ~BEEP;    //报警
				else 
				{
					BEEP = 1;
				}
			}
		}
        if (sendFlag == 1) //定时串口发送信息
		{
			sendFlag = 0;
			sprintf(dis, "Z:%04d\r\n", (uint)num);
			UART0_SendStr(dis);
			delay_1ms(20);
			sprintf(dis, "J:%04d C:%04d\r\n", (uint)jin, (uint)chu);
			UART0_SendStr(dis);
		}
        key();			   //按键扫描函数
		if(key_can < 10)
		{
			key_with();    //按键执行函数
		}
	}
}

/*************定时器0中断服务程序***************/
void Timer0_Intterupt() interrupt 1
{
	static unsigned char time50ms = 0;
	TL0 = 0x00;		//设置定时初始值
	TH0 = 0x4C;		//设置定时初始值 50ms
    
    time50ms++;
	if (time50ms > 100) //5s
	{
		sendFlag = 1;
		time50ms = 0;
	}
    
    if (time50ms % 10 == 0)
    {
        flag_500ms = ~flag_500ms;
    }
}

仿真演示视频:
https://www.bilibili.com/video/BV1WV4y1L7nN/

实物演示视频:
https://www.bilibili.com/video/BV19e41157Bz/

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值