当前位置: 首页 > news >正文

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);}}
}

六、资料分享

点击即可查看当前资料分享。

http://www.dtcms.com/a/390429.html

相关文章:

  • 《C++进阶之STL》【unordered_set/unordered_map 模拟实现】
  • LLM中如何添加special_token,并且尽可能保持原模型的训练效果
  • [x-cmd] 使用系统包管理器安装 x-cmd
  • 亮数据MCP结合Dify:构建自动化视频数据抓取与智能分析工作流的深度实践
  • 革新交互体验,开启未来智慧生活 —— OPE.AI 多语言多模态AI产品
  • 生活琐记(2)
  • 一文读懂HTTP 1.1/2.0/3.0:从原理到应用的通俗解析
  • JavaStream用法全解析
  • 在日常开发中实现异常处理和空值处理的最佳实践
  • openstack port binding failure (by quqi99)
  • leetcode 3484. 设计电子表格 中等
  • Docker+cpolar 实战:打造灵活可控的远程办公系统
  • uniApp开发XR-Frame微信小程序 | 设置透明贴图
  • M3 Ultra版Mac Studio无法正常升级到macOS 26.0 苹果已经在调查
  • 老的ios项目在新的mac M1上编译运行遇到的问题及整理
  • Java 大视界 -- Java 大数据机器学习模型在元宇宙虚拟场景智能交互中的关键技术
  • 2025年目标检测还有什么方向好发论文?
  • 离线openHarmonySdk鸿蒙系统动态库的封装
  • 从零实现鸿蒙智能设备数据采集:权限、传感器、云端上传全流程实战
  • 智慧医院IBMS中央集成系统解决方案:构建医疗安全优先的智慧运营中枢​
  • ✅ Python房源数据采集+分析+预测平台 requests爬虫+sklearn回归 大数据实战项目(建议收藏)机器学习(附源码)
  • 结婚证 OCR 识别:政务服务提速的 “关键一环”
  • Git企业开发--多人协作
  • 【论文阅读 | IF 2025 | IF-USOD:用于水下显著目标检测的多模态信息融合交互式特征增强架构】
  • 【14/20】安全强化:HTTPS 和率限制在 Express 中的应用,实现防护机制
  • C#调用钉钉API实现安全企业内部通知推送
  • MyBatis与MyBatis-Plus区别
  • 数据血缘探秘:用SQL串联不同数据源的脉络
  • 多线程程序性能优化:缓存命中率与伪共享深度剖析
  • Spring Boot支持哪些类型的自定义配置文件?