0 前言
🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。
为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是
🚩 基于STM32单片机的智能手环设计与实现
🥇学长这里给一个题目综合评分(每项满分5分)
🧿 选题指导, 项目分享:
https://gitee.com/dancheng-senior/project-sharing-1/blob/master/%E6%AF%95%E8%AE%BE%E6%8C%87%E5%AF%BC/README.md
1 简介
本次是基于STM32单片机的简易蓝牙手环,手指放在心率检测处,心率传感器就能实时的检测使用者的心率的变化,并在显示屏上进行显示;通过DS18B20检测体温,体温数值也会在显示屏上进行显示;通过震动传感器进行震动采集,每个震动的变化会被系统认为步数的变化,进而实现计步的目的。通过蓝牙模块可以将采集的数据上传到手机端的蓝牙APP内进行显示。
2 主要器件
- STM32F103C8T6
- 心率传感器
- DS18B20体温检测模块
- 蓝牙模块
- 震动传感器
3 实现效果
手指放在心率传感器上可检测心跳 两根手指捏住体温传感器可测试体温 翻转晃动机体,可改变步数
4 设计原理
4.1 DS18B20传感器
DS18B20数字温度计提供9位温度读数。信息经过单线接口送入或送出DS18B20传感器,因此从中央处理器到DS18B20仅需要提供电源以及一根数据线,就可以工作。
DS18B20的ROM指令表 DS18B20的RAM指令表
DS18B20单总线协议
1、DS18B20初始化
(1) 数据线拉到低电平“0”。
(2) 延时480微妙(该时间的时间范围可以从480到960微妙)。
(3) 数据线拉到高电平“1”。
(4) 延时等待80微妙。如果初始化成功则在15到60微妙时间内产生一个由DS18B20所返回的低电平“0”.根据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使程序进入死循环,所以要进行超时判断。
(5) 若CPU读到了数据线上的低电平“0”后,还要做延时,其延时的时间从发出的高电平算起(第3步的时间算起)最少要480微妙。
2、读时序
(1) 将数据线拉低“0”。
(2) 延时1微妙。
(3) 将数据线拉高“1”,释放总线准备读数据。
(4) 延时10微妙。 //等待数据稳定
(5) 读数据线的状态得到1个状态位,并进行数据处理。
(6) 延时45微妙。
(7) 重复1~7步骤,直到读完一个字节。
3、写时序
(1) 数据线先置低电平“0”
(2) 延时15微妙。
(3) 按从低位到高位的顺序发送数据(一次只发送一位)。
(4) 延时60微妙。
(5) 将数据线拉到高电平。
(6) 重复1~5步骤,直到发送完整的字节。
(7) 最后将数据线拉高。
4.2 SW-420震动传感器(开关量传感器)
传感器参数
- 采用LM393比较器输出,信号干净,波形好,驱动能力强
- 工作电压3.3V~5V
- 输出形式: 输出数字量开关0和1
- 尺寸 3.2cmx1.4cm
- 产品用途:各种震动触发作用,比如防盗报警等
- 产品不震动时开关闭合输出低电平,震动时输出高电平;
结构及接线图
传感器原理
原理:没有震动时,震动轴静止,导针A和导针B处于导通状态,平时任何角度开关都是接通状态,受到振动或移动时,震动轴会产生移动或振动,从而导致导针A和B会出现断开。
这种开关的特点是平时一般处于导通状态耐振动时会短暂断开,所以它的灵敏度很高,同时没有震动时电路导通,所以他是常闭式震动传感器。
注意这里是传感器的原理,不是模块的原理,下面是SW-420振动传感器模块的原理
4.3 HC-05蓝牙模块
简介 它是汇承公司出品的一个蓝牙主从机一体可用作无线串口透传通讯的模块。 原理图 相关参数讲解
6根引脚,名称与功能如下;
- VCC 接电源的正极,电压的范围为3.3v到5.0v
- vdd 为外接供电电源输入端
- GND 地线
- TXD:模块串口发送引脚(TTL电平,不能直接接RS232电平),可直接接单片机的RXD引脚
- RXD:模块串口接收引脚(TTL电平,不能直接接RS232电平),可直接接单片机的TXD引脚
- KEY:用于进入AT状态:
- LED:这个引脚是用来检测蓝牙模块是否已经连接上了其他蓝牙设备
通讯方式(tx、rx)
HC-05通过TX和RX引脚,支持使用标准AT命令。为此,用户必须在设备启动时进入特殊命令模式。启动进入数据模式,这样它就可以与其他设备进行无线通信
常见的AT指令
AT指令不区分大小写,但是都要以回车符结尾,下面是常用的AT指令
5 部分核心代码
u8 DS18B20_Check(void)
{
u8 retry=0;
DS18B20_IO_IN();
while (DS18B20_DQ_IN&&retry<200)
{
retry++;
delay_us(1);
};
if(retry>=200)
return 1;
else
retry=0;
while (!DS18B20_DQ_IN&&retry<240)
{
retry++;
delay_us(1);
};
if(retry>=240)
return 1;
return 0;
}
u8 DS18B20_Read_Bit(void)
{
u8 data;
DS18B20_IO_OUT();
DS18B20_DQ_OUT=0;
delay_us(2);
DS18B20_DQ_OUT=1;
DS18B20_IO_IN();
delay_us(12);
if(DS18B20_DQ_IN)
data=1;
else
data=0;
delay_us(50);
return data;
}
u8 DS18B20_Read_Byte(void)
{
u8 i,j,dat;
dat=0;
for (i=1;i<=8;i++)
{
j=DS18B20_Read_Bit();
dat=(j<<7)|(dat>>1);
}
return dat;
}
void DS18B20_Write_Byte(u8 dat)
{
u8 j;
u8 testb;
DS18B20_IO_OUT();
for (j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if (testb)
{
DS18B20_DQ_OUT=0;
delay_us(2);
DS18B20_DQ_OUT=1;
delay_us(60);
}
else
{
DS18B20_DQ_OUT=0;
delay_us(60);
DS18B20_DQ_OUT=1;
delay_us(2);
}
}
}
void SW420_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
SW420_RCC_CLK_ENABLE();
GPIO_InitStruct.Pin = SW420_GPIO_PIN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(SW420_GPIO, &GPIO_InitStruct);
}
static void SW420_ScanDelay(void)
{
uint32_t i,j;
for(i=0;i<100;++i)
for(j=0;j<1000;++j){ }
}
SW420_State_TypeDef SW420_StateRead(void)
{
if(HAL_GPIO_ReadPin(SW420_GPIO,SW420_GPIO_PIN)==SW420_ACTIVE_LEVEL)
{
SW420_ScanDelay();
if(HAL_GPIO_ReadPin(SW420_GPIO,SW420_GPIO_PIN)==SW420_ACTIVE_LEVEL)
{
return SW420_HIGH;
}
}
return SW420_LOW;
}
u8 HC05_Get_Role(void)
{
u8 retry=0x0a;
u8 temp,t;
while(retry--)
{
HC05_KEY=1;
delay_ms(5);
u3_printf("AT+ROLE?\r\n");
for(t=0;t<15;t++)
{
delay_ms(10);
if(USART3_RX_STA&0X8000)break;
}
HC05_KEY=0;
if(USART3_RX_STA&0x8000)
{
temp=USART3_RX_STA&0x7fff;
USART3_RX_STA=0;
if(temp==13&&USART3_RX_BUF[0]=='+')
{
temp=USART3_RX_BUF[6]-'0';
break;
}
}
}
if(retry==0)temp=0xff;
return temp;
}
5 最后
|