STM32项目分享:游泳馆闸机计费管理系统设计
“我们不做一锤子买卖,只做技术成长的长期伙伴!”
目录
一、视频展示
二、项目简介
三、原理图设计
四、PCB硬件设计
五、程序设计
六、资料分享
一、视频展示
游泳馆闸机计费管理系统设计 -视频分享
二、项目简介
该设计由STM32F103C8T6作为主控芯片和蜂鸣器电路以及供电电路,
0.96oled显示屏,3个独立按键,ds1302时钟模块,
RC522刷卡模块,步进电机组成,蓝牙模块。
本设计的功能:
1、 屏幕显示
用来显示刷卡的信息和其他信息,当前时间(年月日时分秒)。
2、刷卡进场
在主页面时把卡片放在rc522刷卡处后,屏幕显示当前信息,然后步进电机打开,蜂鸣器鸣叫一下,
打开完毕之后再过五秒(可在程序修改),会再次打开进行反转关闭。
3、出场刷卡自动计费
如果已经进站直接刷卡进入出场刷卡模式否则进入进场模式,刷入卡片显示信息,
会根据你进站时间去统计费用,并展示,然后打开步进电机正转,过五秒后进行反转。
4、按键声音
每次按下按键都会滴滴声。
5、时钟修改
在主页面按下按键三会进入时钟修改界面。
6、可调单价
单价可调,每小时多少多少
7、蓝牙连接
手机连接蓝牙接受单片机数据,可控制单片机
三、原理图设计
四、PCB硬件设计
五、程序设计
#include "stm32f10x.h" // 设备头文件
#include "delay.h" // 延迟函数库
#include "lcd.h" // LCD显示库
#include "ds1302.h" // DS1302时钟模块库
#include "IOput.h" // 输入输出控制库
#include "RC522.H" // RC522刷卡模块库
#include "timer.h" // 定时器库
#include "usart.h" // 串口通信库
#include "STEPMOTOR.h" // 步进电机库char status; // 状态变量
unsigned char snr, read_buf[16], write_buf[16], TagType[2], SelectedSnr[4], DefaultKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // RC522相关变量u8 show_flag; // 显示标志
u16 ParkHour; // 小时数
u16 price, EachHour = 4; // 价格和每小时收费
extern u8 res_buf;
extern u8 res1;
void wifi(){if(res1=='a'){OLED_Clear();res1=0;key1_flag=1;}else if(res1=='b'){res1=0;key2_flag=1;}else if(res1=='c'){res1=0;key3_flag=1;}}
void showtime(void) // 显示当前时间函数
{ds1032_read_realTime(); // 读取当前时间OLED_ShowNum(0,4,TimeData.year,4,16);OLED_ShowString(35,4,"/",16);OLED_ShowNum(43,4,TimeData.month,2,16);OLED_ShowString(60,4,"/",16);OLED_ShowNum(70,4,TimeData.day,2,16);OLED_ShowNum(0,6,TimeData.hour,2,16);OLED_ShowString(20,6,":",16);OLED_ShowNum(30,6,TimeData.minute,2,16);OLED_ShowString(50,6,":",16);OLED_ShowNum(60,6,TimeData.second,2,16);
}void show_change_time(void) // 显示修改时间函数
{OLED_ShowString(0,4,"20",16);OLED_ShowNum(16,4,lssj.year,2,16);OLED_ShowString(35,4,"/",16);OLED_ShowNum(43,4,lssj.month,2,16);OLED_ShowString(60,4,"/",16);OLED_ShowNum(70,4,lssj.day,2,16);OLED_ShowNum(0,6,lssj.hour,2,16);OLED_ShowString(20,6,":",16);OLED_ShowNum(30,6,lssj.minute,2,16);OLED_ShowString(50,6,":",16);OLED_ShowNum(60,6,lssj.second,2,16);Delay_50ms(2);
}void Write_RC522(void) // 写入RC522函数
{while(1){status = PcdRequest(REQ_ALL , TagType); // 请求卡片if(!status){status = PcdAnticoll(SelectedSnr); // 防冲突操作if(!status){status = PcdSelect(SelectedSnr); // 选择卡片if(!status){snr = 1; // 设置扇区号为1status = PcdAuthState(KEYA, (snr*4+3), DefaultKey, SelectedSnr); // 使用密钥A对指定扇区进行验证if(!status){status = PcdWrite((snr*4+0), write_buf); // 写入数据到指定扇区的块0if(!status){WaitCardOff(); // 等待卡片break;}}}}}}
}void Read_RC522(void) // 读取RC522函数
{while(1){status = PcdRequest(REQ_ALL , TagType); // 请求卡片if(!status){status = PcdAnticoll(SelectedSnr); // 防冲突操作,获取唯一序列号(UID)if(!status){status = PcdSelect(SelectedSnr); // 选择指定序列号的卡片if(!status){snr = 1; // 设置扇区号为1status = PcdAuthState(KEYA, (snr*4+3), DefaultKey, SelectedSnr); // 使用密钥A对指定扇区进行验证if(!status){status = PcdRead((snr*4+0), read_buf); // 从指定扇区的块0读取数据到缓冲区if(!status){WaitCardOff(); // 等待卡片离开感应区OLED_ShowCH(0,0,"111"); // 显示读取成功break;}}}}}}
}int main (void)
{delay_init(); // 初始化延时函数NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置中断优先级组OLED_Init(); // 初始化OLED显示屏delay_ms(1); // 延时1毫秒OLED_Clear(); // 清屏ds1302_gpio_init(); // 初始化DS1302时钟模块input_init(); // 初始化输入output_init(); // 初始化输出PcdInit(); // 初始化RC522刷卡模块PcdAntennaOff(); // 关闭天线PcdAntennaOn(); // 打开天线PcdReset(); // 重置RC522
// M500PcdConfigISOType('A'); // 配置ISO类型
// Usart1_Init(9600); // 初始化串口1,波特率9600stepmotor_init(); // 初始化步进电机MotorStop(); // 停止电机TIM2_Int_Init(71,9999); // 初始化定时器2Usart3_Init(9600);while(1){wifi();key_scan(); // 扫描按键
// MotorCW(900,500);if(key1_flag == 1){key1_flag = 0;show_flag++;if(show_flag == 7){show_flag = 0;lssj.month=(lssj.month)/10*16+(lssj.month)%10;lssj.day=(lssj.day)/10*16+(lssj.day)%10;lssj.hour=(lssj.hour)/10*16+(lssj.hour)%10;lssj.minute=(lssj.minute)/10*16+(lssj.minute)%10;lssj.second=(lssj.second)/10*16+(lssj.second)%10;lssj.year=lssj.year;ds1032_init(); // 初始化DS1302时钟模块}}if(show_flag == 0){if (key3_flag == 1) {key3_flag = 0;EachHour++;if(EachHour>=11){EachHour=0;}}showtime(); // 显示当前时间OLED_ShowCH(0,0,"闸机计费管理系统"); // 显示系统标题OLED_ShowCH(0,2,"请刷卡入馆/出馆"); // 显示提示信息OLED_ShowCH(96,4,"单价"); // 显示单价OLED_ShowNum(96,6,EachHour,2,16); // 显示每小时收费lssj.year=TimeData.year - 2000;lssj.month=TimeData.month;lssj.day=TimeData.day;lssj.hour=TimeData.hour;lssj.minute=TimeData.minute;lssj.second=TimeData.second;lssj.week=TimeData.week;status = PcdRequest(REQ_ALL , TagType); // 请求卡片if(!status) // 如果请求成功{status = PcdAnticoll(SelectedSnr); // 防冲突操作,获取唯一序列号(UID)if(!status) // 如果防冲突操作成功{status=PcdSelect(SelectedSnr); // 选择指定序列号的卡片if(!status) // 如果选择卡片成功{snr = 1; // 设置扇区号为1status = PcdAuthState(KEYA, (snr*4+3), DefaultKey, SelectedSnr); // 使用密钥A对指定扇区进行验证if(!status) // 如果验证成功{status = PcdRead((snr*4+0), read_buf); // 从指定扇区的块0读取数据到缓冲区if(!status) // 如果读取成功{WaitCardOff(); // 等待卡片离开感应区if(read_buf[0] == 0) // 如果卡片状态为0{write_buf[0] = 1;write_buf[1] = lssj.year;write_buf[2] = lssj.month;write_buf[3] = lssj.day;write_buf[4] = lssj.hour;write_buf[5] = lssj.minute;write_buf[6] = lssj.second;write_buf[7] = read_buf[7];while(1){showtime(); // 显示当前时间status = PcdRequest(REQ_ALL , TagType); // 请求卡片if(!status){status = PcdAnticoll(SelectedSnr); // 防冲突操作if(!status){status = PcdSelect(SelectedSnr); // 选择卡片if(!status){snr = 1; // 设置扇区号为1status = PcdAuthState(KEYA, (snr*4+3), DefaultKey, SelectedSnr); // 使用密钥A对指定扇区进行验证if(!status){status = PcdWrite((snr*4+0), write_buf); // 写入数据到指定扇区的块0if(!status){WaitCardOff(); // 等待卡片break;}}}}}}BEEP = 0;delay_ms(100);BEEP = 1;delay_ms(100);BEEP = 0;delay_ms(100);BEEP = 1;delay_ms(100);MotorCW(800,150); // 正转步进电机OLED_Clear();show_flag = 8;}else if(read_buf[0] == 1) // 如果卡片状态为1{ParkHour = ((lssj.year - read_buf[1]) * 365 * 24 * 3600 + (lssj.month - read_buf[2]) * 30 * 24 * 3600 + (lssj.day - read_buf[3]) * 24 * 3600 + (lssj.hour - read_buf[4]) * 3600 + (lssj.minute - read_buf[5]) * 60 + (lssj.second - read_buf[6])) / 3600; // 计算时间price = EachHour * ParkHour; // 计算费用if(price >= 60)price = 60;write_buf[0] = 0;write_buf[7] = read_buf[7] - price;while(1){showtime(); // 显示当前时间status = PcdRequest(REQ_ALL , TagType); // 请求卡片if(!status){status = PcdAnticoll(SelectedSnr); // 防冲突操作if(!status){status = PcdSelect(SelectedSnr); // 选择卡片if(!status){snr = 1; // 设置扇区号为1status = PcdAuthState(KEYA, (snr*4+3), DefaultKey, SelectedSnr); // 使用密钥A对指定扇区进行验证if(!status){status = PcdWrite((snr*4+0), write_buf); // 写入数据到指定扇区的块0if(!status){WaitCardOff(); // 等待卡片break;}}}}}}BEEP = 0;delay_ms(100);BEEP = 1;delay_ms(100);BEEP = 0;delay_ms(100);BEEP = 1;delay_ms(100);MotorCW(800,150); // 正转步进电机OLED_Clear();show_flag = 9;OLED_Clear();}}}}}}}else if(show_flag == 8){showtime(); // 显示当前时间TIM_Cmd(TIM2, ENABLE); // 使能定时器2OLED_ShowCH(0,2,"人员入场"); // 显示入场UsartPrintf(USART3,"人员入场!\r\n");if(time_count >= 500){TIM_Cmd(TIM2, DISABLE); // 关闭定时器2time_count = 0;OLED_Clear();show_flag = 0;MotorCCW(800,150); // 反转步进电机}}else if(show_flag == 9){showtime(); // 显示当前时间TIM_Cmd(TIM2, ENABLE); // 使能定时器2OLED_ShowCH(0,0,"游玩时长:"); // 显示时长OLED_ShowNum(72,0,ParkHour,3,16); OLED_ShowCH(0,2,"游玩缴费:"); OLED_ShowNum(72,2,price,2,16); // 显示缴费数值UsartPrintf(USART3,"游玩时长:%d\r\n",ParkHour);UsartPrintf(USART3,"游玩缴费:%d\r\n",price);if(time_count >= 500){TIM_Cmd(TIM2, DISABLE); // 关闭定时器2time_count = 0;OLED_Clear();show_flag = 0;MotorCCW(800,150); // 反转步进电机}}else if (show_flag == 1) {show_change_time(); // 显示修改时间if (key2_flag == 1) {key2_flag = 0;lssj.year++;}if (key3_flag == 1) {key3_flag = 0;lssj.year--;}if(lssj.year>100)lssj.year = 0;OLED_ShowChar(24,4,'_',16);Delay_50ms(2);}else if (show_flag == 2) {show_change_time(); // 显示修改时间if (key2_flag == 1) {key2_flag = 0;lssj.month++;}if (key3_flag == 1) {key3_flag = 0;lssj.month--;}if(lssj.month>12)lssj.month = 1;if(lssj.month<1)lssj.month = 12;OLED_ShowChar(51,4,'_',16);Delay_50ms(2);}else if (show_flag == 3){show_change_time(); // 显示修改时间if (key2_flag == 1){key2_flag = 0;lssj.day++;}if (key3_flag == 1){key3_flag = 0;lssj.day--;}if(lssj.day>31)lssj.day = 1;if(lssj.day<1)lssj.day = 31;OLED_ShowChar(78,4,'_',16);Delay_50ms(2);}else if (show_flag == 4){show_change_time(); // 显示修改时间if (key2_flag == 1){key2_flag = 0;lssj.hour++;if (lssj.hour > 23)lssj.hour = 0;}if (key3_flag == 1){key3_flag = 0;lssj.hour--;if (lssj.hour > 200)lssj.hour = 23;}OLED_ShowChar(8,6,'_',16);Delay_50ms(2);}else if (show_flag == 5){show_change_time(); // 显示修改时间if (key2_flag == 1){key2_flag = 0;lssj.minute++;if (lssj.minute > 59)lssj.minute = 0;}if (key3_flag == 1){key3_flag = 0;lssj.minute--;if (lssj.minute > 200)lssj.minute = 59;}OLED_ShowChar(38,6,'_',16);Delay_50ms(2);}else if (show_flag == 6){show_change_time(); // 显示修改时间if (key2_flag == 1){key2_flag = 0;lssj.second++;if (lssj.second > 59)lssj.second = 0;}if (key3_flag == 1){key3_flag = 0;lssj.second--;if (lssj.second > 200)lssj.second = 59;}OLED_ShowChar(68,6,'_',16);Delay_50ms(2);}}
}
六、资料分享
点击即可查看当前资料分享。