0 前言
🔥
这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。
为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是
🚩 毕业设计 STM32的人体检测温控温度风扇(pwm)(源码+硬件+论文)
🥇学长这里给一个题目综合评分(每项满分5分)
- 难度系数:3分
- 工作量:3分
- 创新点:4分
🧿 项目分享:见文末!
1 主要功能
- (1)LCD1602液晶显示当前温度,风扇等级,自动手动模式。
- (2)按键可以设置自动和手动2种模式切换,按键设置温度上限。
- (3)手动模式下可以自由开启风扇,调整档位等级。
- (4)自动模式下,人体红外检测到人并且当前温度大于我们设置温度上限值风扇开启。
- (5)每大于一度风扇档位pwm加一,最大上限为10档。
2 硬件设计(原理图)
对应PCB
3 核心软件设计
篇幅有限,不过多复述详细设计细节,详细的设计分享在论文中。。。
关键代码
#include "stm32f10x.h"
#include "bsp_SysTick.h"
#include <LCD1602.h>
#include "bsp_ds18b20.h"
int main()
{ int PWM,low,zhouqi;
float wendu;
int wendu1;
zhouqi=500;
low=zhouqi-PWM;
SysTick_Init();
init1602();
lcdpos(1,0);
writestring("TEM: 00.0");
GPIO_SetBits(GPIOB,GPIO_Pin_0);
while( DS18B20_Init())
{
lcdpos(0,0);
writestring(" no ds18b20 exit");
}
lcdpos(0,0);
writestring("ds18b20 exit");
for(;;)
{
DS18B20_Get_Temp(wendu);
if (wendu<0)
{ lcdpos(1,4);
writestring("-");
}
wendu1=wendu*100;
lcdpos(1,5);
write_dat(wendu1/10000+0x30);
lcdpos(1,6);
write_dat(wendu1%10000/1000+0x30);
lcdpos(1,7);
write_dat(wendu1%1000/100+0x30);
lcdpos(1,9);
write_dat(wendu1%100/10+0x30);
lcdpos(1,10);
write_dat(wendu1%10+0x30);
Delay_ms(2000);
if(wendu1>30)
{ low=500;
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay_ms(PWM);
}
if(wendu1<15)
{ low=0;
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay_ms(PWM);
}
if(wendu1>=15&wendu1<20)
{ low=100;
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay_ms(PWM);
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
Delay_ms(low);
}
if(wendu1>=20&wendu1<25)
{
low=200;
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay_ms(PWM);
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
Delay_ms(low);
}
if(wendu1>=25&wendu1<30)
{ low=300;
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay_ms(PWM);
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
Delay_ms(low);
}
}
}
2.DS18B20子程序
#include "bsp_ds18b20.h"
/*
* 函数名:DS18B20_GPIO_Config
* 描述 :配置DS18B20用到的I/O口
* 输入 :无
* 输出 :无
*/
static void DS18B20_GPIO_Config(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启DS18B20_PORT的外设时钟*/
RCC_APB2PeriphClockCmd(DS18B20_CLK, ENABLE);
/*选择要控制的DS18B20_PORT引脚*/
GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化DS18B20_PORT*/
GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
GPIO_SetBits(DS18B20_PORT, DS18B20_PIN);
}
/*
* 函数名:DS18B20_Mode_IPU
* 描述 :使DS18B20-DATA引脚变为输入模式
* 输入 :无
* 输出 :无
*/
static void DS18B20_Mode_IPU(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*选择要控制的DS18B20_PORT引脚*/
GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
/*设置引脚模式为浮空输入模式*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
/*调用库函数,初始化DS18B20_PORT*/
GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
}
/*
* 函数名:DS18B20_Mode_Out_PP
* 描述 :使DS18B20-DATA引脚变为输出模式
* 输入 :无
* 输出 :无
*/
static void DS18B20_Mode_Out_PP(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*选择要控制的DS18B20_PORT引脚*/
GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化DS18B20_PORT*/
GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
}
/*
*主机给从机发送复位脉冲
*/
static void DS18B20_Rst(void)
{
/* 主机设置为推挽输出 */
DS18B20_Mode_Out_PP();
DS18B20_DATA_OUT(LOW);
/* 主机至少产生480us的低电平复位信号 */
Delay_us(750);
/* 主机在产生复位信号后,需将总线拉高 */
DS18B20_DATA_OUT(HIGH);
Delay_us(15);
}
/*
* 检测从机给主机返回的存在脉冲
* 0:成功
* 1:失败
*/
static uint8_t DS18B20_Presence(void)
{
uint8_t pulse_time = 0;
/* 主机设置为上拉输入 */
DS18B20_Mode_IPU();
while( DS18B20_DATA_IN() && pulse_time<100 )
{
pulse_time++;
Delay_us(1);
}
/ * 经过100us后,存在脉冲都还没有到来*/
if( pulse_time >=100 )
return 1;
else
pulse_time = 0;
/* 存在脉冲到来,且存在的时间不能超过240us */
while( !DS18B20_DATA_IN() && pulse_time<240 )
{
pulse_time++;
Delay_us(1);
}
if( pulse_time >=240 )
return 1;
else
return 0;
}
/*
* 从DS18B20读取一个bit
*/
static uint8_t DS18B20_Read_Bit(void)
{
uint8_t dat; /* 读0和读1的时间至少要大于60us */
DS18B20_Mode_Out_PP();
/* 读时间的起始:必须由主机产生 >1us <15us 的低电平信号 */
DS18B20_DATA_OUT(LOW);
Delay_us(10);
/ * 设置成输入,释放总线,由外部上拉电阻将总线拉高 */
DS18B20_Mode_IPU();
//Delay_us(2);
if( DS18B20_DATA_IN() == SET )
dat = 1;
else
dat = 0;
/* 这个延时参数请参考时序图 */
Delay_us(45);
return dat;
}
/*
* 从DS18B20读一个字节,低位先行
*/
uint8_t DS18B20_Read_Byte(void)
{
uint8_t i, j, dat = 0;
for(i=0; i<8; i++)
{
j = DS18B20_Read_Bit();
dat = (dat) | (j<<i);
}
return dat;
}
/*
* 写一个字节到DS18B20,低位先行
*/
void DS18B20_Write_Byte(uint8_t dat)
{
uint8_t i, testb;
DS18B20_Mode_Out_PP();
for( i=0; i<8; i++ )
{
testb = dat&0x01;
dat = dat>>1;
/* 写0和写1的时间至少要大于60us */
if (testb)
{
DS18B20_DATA_OUT(LOW);
/* 1us < 这个延时 < 15us */
Delay_us(8);
DS18B20_DATA_OUT(HIGH);
Delay_us(58);
}
else
{
DS18B20_DATA_OUT(LOW);
/* 60us < Tx 0 < 120us */
Delay_us(70);
DS18B20_DATA_OUT(HIGH);
/* 1us < Trec(恢复时间) < 无穷大*/
Delay_us(2);
}
}
}
void DS18B20_Start(void)
{
DS18B20_Rst();
DS18B20_Presence();
DS18B20_Write_Byte(0XCC); /* 跳过 ROM */
DS18B20_Write_Byte(0X44); /* 开始转换 */
}
uint8_t DS18B20_Init(void)
{
DS18B20_GPIO_Config();
DS18B20_Rst();
return DS18B20_Presence();
}
float DS18B20_Get_Temp(float f_tem)
{
uint8_t tpmsb, tplsb;
short s_tem;
DS18B20_Rst();
DS18B20_Presence();
DS18B20_Write_Byte(0XCC); /* 跳过 ROM */
DS18B20_Write_Byte(0X44); /* 开始转换 */
DS18B20_Rst();
DS18B20_Presence();
DS18B20_Write_Byte(0XCC); /* 跳过 ROM */
DS18B20_Write_Byte(0XBE); /* 读温度值 */
tplsb = DS18B20_Read_Byte();
tpmsb = DS18B20_Read_Byte();
s_tem = tpmsb<<8;
s_tem = s_tem | tplsb;
I f( s_tem < 0 ) /* 负温度 */
f_tem = (~s_tem+1) * 0.0625;
else
f_tem = s_tem * 0.0625;
return f_tem;
}
3.LCD1602子程序
#include<LCD1602.h>
#include "bsp_SysTick.h"
void LCD_GPIO_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin =
GPIO_Pin_1|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_0|GPIO_Pin_11;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void RS(u8 a)
{
if(a==0)GPIO_ResetBits(GPIOB,GPIO_Pin_5);
if(a==1)GPIO_SetBits(GPIOB,GPIO_Pin_5);
}
void WR(u8 a)
{
if(a==0)GPIO_ResetBits(GPIOB,GPIO_Pin_1);
if(a==1)GPIO_SetBits(GPIOB,GPIO_Pin_1);
}
void EN(u8 a)
{
if(a==0)GPIO_ResetBits(GPIOB,GPIO_Pin_6);
if(a==1)GPIO_SetBits(GPIOB,GPIO_Pin_6);
}
void dat(u8 dat)
{
u16 a;
a=GPIO_ReadOutputData(GPIOA);
a=a&0xff00;
a=a|dat;
GPIO_Write(GPIOA,a);
}
void write_cmd(u8 cmd)
{
RS(0);
WR(0);
dat(cmd);
Delay_us(500);
EN(1);
Delay_us(500);
EN(0);
}
void write_dat(u8 date)
{
RS(1);
WR(0);
dat(date);
Delay_us(500);
EN(1);
Delay_us(500);
EN(0);
}
void lcdpos(u8 X,u8 Y)
{
u8 cmd;
if(X==0)cmd=0x80+Y;
if(X==1)cmd=0x80+0x40+Y;
write_cmd(cmd);
}
void writestring(char *s)
{
while(*s)
{
write_dat(*s);
s++;
}
}
void init1602(void)
{
LCD_GPIO_init();
Delay_us(1000);
EN(0);
write_cmd(0x38);
write_cmd(0x0c);
write_cmd(0x06);
write_cmd(0x01);
write_cmd(0x80);
}
4 实现效果
5 最后
包含内容
🧿 项目分享:见文末!
**项目分享: **
https://blog.csdn.net/m0_984093