功能介绍:
0.本系统采用STC89C52作为单片机
2.采用LCD1602液晶屏可以实时查看车位使用情况
3.采用超声波模块HC-SR04来检测车位是否有车,且每个车位都附有LED指示灯来实时显示车位情况
4.采用舵机来模拟栏杆的运动
5.采用DC002作为电源接口可直接输入5V给整个系统供电
原理图:
PCB:
主程序:
登录后复制
#include <reg52.h>
#include <intrins.h>
#include <stdio.h>
#include "delay.h"
#include "lcd1602.h"
#include "rc522.h"
#define OFF 1
#define ON 0
#define STARTING_PRICE 2 //起步价
#define HOUR_PRICE 1 //每小时收费
sbit TRIG_1 = P1^0; //接口定义
sbit ECHO_1 = P1^1; //接口定义
sbit LED_VOID_1 = P1^2;
sbit LED_PARKING_1 = P1^3;
sbit TRIG_2 = P2^0; //接口定义
sbit ECHO_2 = P2^1; //接口定义
sbit LED_VOID_2 = P1^4;
sbit LED_PARKING_2 = P1^5;
sbit TRIG_3 = P2^4; //接口定义
sbit ECHO_3 = P2^5; //接口定义
sbit LED_VOID_3 = P2^3;
sbit LED_PARKING_3 = P2^2;
sbit STEERING_ENGINE = P3^2; //舵机
xdata unsigned char dis0[16]; //定义显示区域临时存储数组
unsigned char code CarID[3][4] = {{0x2C, 0x96, 0xE4, 0x17}, {0x4C, 0x8C, 0xE4, 0x17}, {0x0C, 0xD6, 0xBE, 0x16}}; //卡号ID,上位机可通过串口查看卡号ID
bit disFlag = 1; //显示标志
bit refreshFlag = 1; //显示标志
bit openFlag = 0; //栏杆启动标志
bit openDir = 0; //栏杆位置标志
unsigned char i;
unsigned char occupiedFlag1 = 0; //位置标志
unsigned char occupiedFlag2 = 0; //位置标志
unsigned char occupiedFlag3 = 0; //位置标志
unsigned char occupiedNum = 0; //占用总数
float f_distance1 = 0; //距离1
float f_distance2 = 0; //距离2
float f_distance3 = 0; //距离3
struct {
unsigned char inflag; //场内标志
unsigned char stopMinute; //停车总时间
unsigned int stopHour; //停车总时间
}Parking_Status[3];
void Timer1_Init(void); //函数声明
void Measuring(void); //测量
void Display(void); //显示
void CardProcess(void); //刷卡处理
void Open(void); //开启栏杆
void Close(void); //关闭栏杆
void UART_Init(void); //串口初始化
void UART_SendByte(unsigned char dat);
void UART_SendStr(unsigned char *s, unsigned char length);
void main(void)
{
Parking_Status[0].inflag = 0;
Parking_Status[0].stopMinute = 0;
Parking_Status[0].stopHour = 0;
Parking_Status[1].inflag = 0;
Parking_Status[1].stopMinute = 0;
Parking_Status[1].stopHour = 0;
Parking_Status[2].inflag = 0;
Parking_Status[2].stopMinute = 0;
Parking_Status[2].stopHour = 0;
TRIG_1 = 0;
TRIG_2 = 0;
TRIG_3 = 0;
TMOD &= 0xF0; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TH0 = 0; //重新赋值 20ms
TL0 = 0;
EA = 1; //总中断打开
TR0 = 0;
PcdReset(); //复位RC522
PcdAntennaOn(); //开启天线发射
LCD_Init(); //初始化液晶
DelayMs(20); //延时有助于稳定
LCD_Clear(); //清屏
Timer1_Init(); //定时器0初始化
UART_Init(); //串口初始化
while (1)
{
if (refreshFlag == 1)
{
refreshFlag = 0;
Measuring();
}
if (disFlag == 1) //定时显示
{
disFlag = 0; //标志位清零
CardProcess();
Display();
}
}
}
//超声波测距
void Measuring(void)
{
static long cnt = 0; //定时器计数
TR1 = 0;
TRIG_1 = 1; //启动一次模块 //不可以使用其他终端 容易造成死循环
DelayUs10x(1);
TRIG_1 = 0;
while (!ECHO_1)
; //当RX为零时等待
TR0 = 1; //开启计数
while (ECHO_1)
; //当RX为1计数并等待
TR0 = 0;
cnt = (long)(TH0 * 256 + TL0);
TH0 = 0;
TL0 = 0;
f_distance1 = (float)cnt * 17 / 100.0 * 1.102; //算出来是mm (g_cnt * 340 / 2) / 1000.0 * 1.102;系数
cnt = 0;
TRIG_2 = 1; //启动一次模块 //不可以使用其他终端 容易造成死循环
DelayUs10x(1);
TRIG_2 = 0;
while (!ECHO_2)
; //当RX为零时等待
TR0 = 1; //开启计数
while (ECHO_2)
; //当RX为1计数并等待
TR0 = 0;
cnt = (long)(TH0 * 256 + TL0);
TH0 = 0;
TL0 = 0;
f_distance2 = (float)cnt * 17 / 100.0 * 1.102; //算出来是mm (g_cnt * 340 / 2) / 1000.0 * 1.102;系数
cnt = 0;
TRIG_3 = 1; //启动一次模块 //不可以使用其他终端 容易造成死循环
DelayUs10x(1);
TRIG_3 = 0;
while (!ECHO_3)
; //当RX为零时等待
TR0 = 1; //开启计数
while (ECHO_3)
; //当RX为1计数并等待
TR0 = 0;
cnt = (long)(TH0 * 256 + TL0);
TH0 = 0;
TL0 = 0;
f_distance3 = (float)cnt * 17 / 100.0 * 1.102; //算出来是mm (g_cnt * 340 / 2) / 1000.0 * 1.102;系数
cnt = 0;
TR1 = 1;
}
//界面显示
void Display(void)
{
if (f_distance1 <= 500) //检测到车距0.5m
{
occupiedFlag1 = 1;
} //标志
else
{
occupiedFlag1 = 0;
}
if (f_distance2 <= 500) //检测到车距0.5m
{
occupiedFlag2 = 1;
} //标志
else
{
occupiedFlag2 = 0;
}
if (f_distance3 <= 500) //检测到车距0.5m
{
occupiedFlag3 = 1;
} //标志
else
{
occupiedFlag3 = 0;
}
if (occupiedFlag1 == 1)
{
LCD_DispStr(0, 1, "P ");
LED_VOID_1 = OFF;
LED_PARKING_1 = ON;
} //显示占用
else
{
LCD_DispStr(0, 1, "N ");
LED_VOID_1 = ON;
LED_PARKING_1 = OFF;
}
if (occupiedFlag2 == 1)
{
LCD_DispStr(2, 1, "P ");
LED_VOID_2 = OFF;
LED_PARKING_2 = ON;
} //显示占用
else
{
LCD_DispStr(2, 1, "N ");
LED_VOID_2 = ON;
LED_PARKING_2 = OFF;
}
if (occupiedFlag3 == 1)
{
LCD_DispStr(4, 1, "P ");
LED_VOID_3 = OFF;
LED_PARKING_3 = ON;
} //显示占用
else
{
LCD_DispStr(4, 1, "N ");
LED_VOID_3 = ON;
LED_PARKING_3 = OFF;
}
occupiedNum = occupiedFlag1 + occupiedFlag2 + occupiedFlag3; //占用总数
sprintf(dis0, "1 2 3 P:%d N:%d ", (int)occupiedNum, (int)(3 - occupiedNum)); //打印
LCD_DispStr(0, 0, dis0);
}
//刷卡处理
void CardProcess(void)
{
unsigned char Temp[4]; //暂存数组
unsigned char UID[4]; //卡号
static unsigned char dispTime = 0;
if (PcdRequest(0x52, Temp) == MI_OK) //检测到卡号
{
DelayS(1);
if (PcdRequest(0x52, Temp) == MI_OK) // 1S后仍然检测到卡号
{
if (PcdAnticoll(UID) == MI_OK) //读取卡号成功
{
unsigned char i;
UART_SendByte(0x00); //串口发送卡号
UART_SendStr(UID, 4);
UART_SendByte(0x00);
for (i = 0; i < 3; i++)
{
if ((UID[0] == CarID[i][0]) && (UID[1] == CarID[i][1]))
{
Open(); //打开栏杆
if (Parking_Status[i].inflag == 0) //没有停车,初次进场
{
Parking_Status[i].inflag = 1; //进场
sprintf(dis0, "Car%1d: In ", (int)i+1);
LCD_DispStr(6, 1, dis0);
dispTime = 50;
}
else
{
Parking_Status[i].inflag = 0; //出场
// if (Parking_Status[i].stopHour == 0 && Parking_Status[i].stopMinute < 15) //15分钟以内免费
// {
// sprintf(dis0, "Car%1d:%4d$", (unsigned int)i+1, (unsigned int)0);
// LCD_DispStr(6, 1, dis0);
// Parking_Status[i].stopMinute = 0;
// Parking_Status[i].stopHour = 0;
// dispTime = 50; //显示一段时间
// }
if (Parking_Status[i].stopHour < 2 && Parking_Status[i].stopMinute >= 0) //2小时内起步价
{
sprintf(dis0, "Car%1d:$%4d", (unsigned int)i+1, (unsigned int)STARTING_PRICE);
LCD_DispStr(6, 1, dis0);
Parking_Status[i].stopMinute = 0;
Parking_Status[i].stopHour = 0;
dispTime = 50; //显示一段时间
}
else if (Parking_Status[i].stopHour >= 2) //2小时后正常计费
{
sprintf(dis0, "Car%1d:$%4d", (unsigned int)i+1, (unsigned int)(STARTING_PRICE+(Parking_Status[i].stopHour-1)*HOUR_PRICE));
LCD_DispStr(6, 1, dis0);
Parking_Status[i].stopMinute = 0;
Parking_Status[i].stopHour = 0;
dispTime = 50; //显示一段时间
}
}
}
}
}
}
}
if (dispTime == 0)
{
LCD_DispStr(6, 1, " ");
}
else
{
dispTime--;
}
if (dispTime == 1)
{
Close();//关闭栏杆
}
}
//定时器1初始化
void Timer1_Init(void)
{
TMOD |= 0x10; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TMOD &= 0x0F; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TL1 = 0x66; //设置定时初始值
TH1 = 0xFC; //设置定时初始值 1ms
EA = 1; //总中断打开
ET1 = 1; //定时器中断打开
PT1 = 1;
TR1 = 1; //定时器开关打开
}
//定时器1中断
void Timer1_Interrupt(void) interrupt 3
{
static unsigned int time_50ms = 0;
TL1 = 0x00; //设置定时初始值
TH1 = 0x4C; //设置定时初始值 50ms
time_50ms++;
if (time_50ms > 120) // 1min
{
time_50ms = 0;
if (Parking_Status[0].inflag == 1)
{
Parking_Status[0].stopMinute++;
if (Parking_Status[0].stopMinute >= 60)
{
Parking_Status[0].stopMinute = 0;
Parking_Status[0].stopHour++;
}
}
if (Parking_Status[1].inflag == 1)
{
Parking_Status[1].stopMinute++;
if (Parking_Status[1].stopMinute >= 60)
{
Parking_Status[1].stopMinute = 0;
Parking_Status[1].stopHour++;
}
}
if (Parking_Status[2].inflag == 1)
{
Parking_Status[2].stopMinute++;
if (Parking_Status[2].stopMinute >= 60)
{
Parking_Status[2].stopMinute = 0;
Parking_Status[2].stopHour++;
}
}
}
if (time_50ms % 20 == 0)
{
disFlag = 1;
}
if (time_50ms % 5 == 0)
{
refreshFlag = 1;
}
}
//开启栏杆
void Open(void)
{
unsigned char i;
for (i = 0; i < 10; i++)
{
STEERING_ENGINE = 1;
DelayUs10x(50);
STEERING_ENGINE = 0;
DelayUs10x(50);
DelayMs(19);
}
}
//关闭栏杆
void Close(void)
{
unsigned char i;
for (i = 0; i < 10; i++)
{
STEERING_ENGINE = 1;
DelayUs10x(250);
STEERING_ENGINE = 0;
DelayUs10x(50);
DelayMs(17);
}
}
void UART_Init(void)
{
SCON = 0x50;
TH2 = 0xFF;
TL2 = 0xDC;
RCAP2H = 0xFF; //(65536-(FOSC/32/BAUD)) BAUD = 9600 FOSC = 11059200
RCAP2L = 0xDC;
/*****************/
TCLK = 1;
RCLK = 1;
C_T2 = 0;
EXEN2 = 0;
/*****************/
TR2 = 1;
ES = 0; //关闭串口中断
EA = 1; //打开总中断
}
void UART_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 UART_SendStr(unsigned char *s, unsigned char length)
{
unsigned char cnt;
cnt = 0x00;
while (cnt < length) //发送长度对比
{
UART_SendByte(*s); //放松单字节数据
s++; //指针++
cnt++; //下一个++
}
}
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删