“我们不做一锤子买卖,只做技术成长的长期伙伴!”
目录
一、视频展示
基于单片机的图书馆座位监测系统 -视频分享
二、项目简介
题目:基于单片机的图书馆座位监测系统
主控:STM32
显示:OLED显示屏
DS1302时钟模块
红外光电
红外测温模块
蓝牙模块
红色led+黄色led
声光报警:LED+蜂鸣器
功能:
1、光电负责检测是否有物品在位置上,红外测温负责识别是人体还是其他物品。
2、若为物品占位则开启蜂鸣器报警提醒不得占位。
3、若为人则正常,当人员长时间使用座位时,黄色灯光亮起一分钟以提醒休息。若人员长时间离开座位时,红色灯光亮起,提示工作人员进行清洁。
4、显示屏显示当前座位编号,数据信息。
三、原理图设计
四、PCB硬件设计
五、程序设计
#include "stm32f10x.h" // 包含设备头文件
#include "delay.h" // 包含延时库
#include "lcd.h" // 包含LCD显示库
#include "ds1302.h" // 包含DS1302时钟库
#include "IOput.h" // 包含输入输出库
#include "usart.h" // 包含USART库
// 定义全局变量
u8 show_flag, BEEP_flag, on_flag, count;
u8 flag_lightel = 0,flag_wd = 0;
float MAX_WD=37.5,wd;
u8 flag_peo = 0;
u8 flag_real_peo = 0;
u8 flag_wuti = 0;
u8 timeM = 0;
u8 timeS = 0;
// 蜂鸣器控制函数
void beep1()
{
BEEP = 0; // 打开蜂鸣器
// 延时8秒,模拟蜂鸣器响8秒
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
BEEP = 1; // 关闭蜂鸣器
// 延时8秒,模拟蜂鸣器停止8秒
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
}
// 显示时间函数
void showtime(void)
{
OLED_ShowCH(0,0,"编号:");
OLED_ShowNum(40,0,12,2,16);
if(flag_peo&&!flag_lightel )
{
OLED_ShowCH(64,0,"有人");
flag_real_peo = 1;
BEEP = 1;
}else if(!flag_lightel)
{
OLED_ShowCH(64,0,"物体");
flag_real_peo = 0;
flag_wuti = 1;
BEEP = 0;
}else
{
OLED_ShowCH(64,0,"无人");
flag_real_peo = 0;
flag_wuti = 0;
BEEP = 1;
}
OLED_ShowCH(0, 2, "状态:"); // 显示闹钟标识
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 DINGSHI(u8 minute_flag,u8 flag_led)
{
if(TimeData.minute == minute_flag && TimeData.second < 30)
{
BEEP_flag = 1;
}
if(BEEP_flag == 1)
{
if(flag_led)
{
OLED_ShowCH(40,2,"该休息了");
YELLOW = 1;
}else
{
RED = 1;
OLED_ShowCH(40,2,"该打扫了");
}
if(TimeData.second > 30)
{
RED = 0;
YELLOW = 0;
on_flag = 0;
BEEP_flag = 0;
}
}
}
void check_people(void)
{
u8 WENDU_H,WENDU_L;
// OLED_ShowCH(0,0," 红外体温计 ");
// OLED_ShowCH(0,2,"温度阈值:");
// OLED_ShowCH(0,4,"当前体温:");
// OLED_Showdecimal(72,2,MAX_WD,2,1,16);
if(USART_RX_STA&0X8000)//接收到一次数据
{
WENDU_H=USART_RX_BUF[2];
WENDU_L=USART_RX_BUF[3]/10;
WENDU_H=WENDU_H&0X00FF;
if(WENDU_H>=55)
{
WENDU_H=0;
WENDU_L=0;
wd = (float)WENDU_H+(float)WENDU_L;
UsartPrintf(USART1,"编号:%d\r\n",12);
if(flag_real_peo)
{
UsartPrintf(USART1,"有人\r\n");
}else if(flag_wuti)
{
UsartPrintf(USART1,"有物品\r\n");
}else
{
UsartPrintf(USART1,"没人\r\n");
}
UsartPrintf(USART1,"\r\n\r\n");
OLED_ShowNum(104,0,wd,2,16);
if(wd>1 && wd < 39.5)
{
flag_peo = 1;
}else
{
flag_peo = 0;
}
USART_RX_STA=0;//启动下次接收
}
else
{
wd = (float)WENDU_H+(float)WENDU_L;
UsartPrintf(USART1,"编号:%d\r\n",12);
if(flag_real_peo)
{
UsartPrintf(USART1,"有人\r\n");
}else if(flag_wuti)
{
UsartPrintf(USART1,"有物品\r\n");
}else
{
UsartPrintf(USART1,"没人\r\n");
}
UsartPrintf(USART1,"\r\n\r\n");
OLED_ShowNum(104,0,wd,2,16);
if(wd>1 && wd < 39.5)
{
flag_peo = 1;
}else
{
flag_peo = 0;
}
USART_RX_STA=0;//启动下次接收
}
}
delay_ms(200);
//发送测温指令 0XFA 0XCA 0XC4
USART2_SendData(0XFA);
USART2_SendData(0XCA);
USART2_SendData(0XC4);
}
// 主函数
int main(void)
{
delay_init(); // 初始化延时
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 配置优先级分组
OLED_Init(); // 初始化OLED
delay_ms(1);
OLED_Clear(); // 清屏
ds1302_gpio_init(); // 初始化DS1302
input_init(); // 初始化输入
output_init(); // 初始化输出
Usart1_Init(9600);
Usart2_Init(9600);
//发送体温模式指令 0XFA 0XC5 0XBF
USART_SendData(USART2,0XFA);
USART_SendData(USART2,0XC5);
USART_SendData(USART2,0XBF);
delay_ms(50);
while(1)
{
check_people();
flag_lightel= GD;
key_scan();
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(); // 初始化DS1032
}
}
if(show_flag == 0)
{
showtime(); // 显示时间
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;
if(flag_real_peo == 1)
{
OLED_ShowCH(40,2,"位置有人");
// flag_real_peo = 0;
on_flag++;
if(on_flag == 1)
{
timeM = TimeData.minute;
timeS = TimeData.second;
}
}else
{
on_flag = 0;
}
if(on_flag)
{
DINGSHI(timeM+1,1);//有人黄灯提醒
}else
{
DINGSHI(timeM+1,0);//无人红灯提醒
OLED_ShowCH(40,2,"位置没人");
}
// count++; // 增加计数
// if(count >= 100)
// {
// // 通过串口打印时间和闹钟状态
// UsartPrintf(USART1, "时间:\r\n%d年", TimeData.year);
// UsartPrintf(USART1, "%d月", TimeData.month);
// UsartPrintf(USART1, "%d日\r\n", TimeData.day);
// UsartPrintf(USART1, " %d", TimeData.hour);
// UsartPrintf(USART1, ":%d", TimeData.minute);
// UsartPrintf(USART1, ":%d\r\n", TimeData.second);
// if(on_flag == 1)
// {
// UsartPrintf(USART1, "闹钟:开\r\n");
// }
// else
// {
// UsartPrintf(USART1, "闹钟:关\r\n");
// }
// count = 0; // 重置计数
// }
}
// 以下是调整年、月、日、小时、分钟和秒的功能
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
}
}
六、资料分享
点击即可查看当前资料分享。