毕业设计 STM32的人体检测温控温度风扇(pwm)(源码+硬件+论文)


0 前言

🔥
这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。

为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是

🚩 毕业设计 STM32的人体检测温控温度风扇(pwm)(源码+硬件+论文)

🥇学长这里给一个题目综合评分(每项满分5分)

  • 难度系数:3分
  • 工作量:3分
  • 创新点:4分

🧿 项目分享:

https://gitee.com/sinonfin/sharing

在这里插入图片描述

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://gitee.com/sinonfin/sharing

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于STM32的电子时钟万年历温度OLED显示是一款集成了实时时钟、万年历、温度检测和OLED显示的电子设备。它可以精确显示当前的时间、日期、星期以及环境温度,并通过OLED显示屏进行展示。 硬件连接方面,我们首先需要连接 STM32 微控制器与其他模块。具体连接方式为: 1. 将STM32与OLED显示屏通过I2C总线连接,将OLED的SDA引脚连接到STM32的SDA引脚,将OLED的SCL引脚连接到STM32的SCL引脚。 2. 将STM32温度传感器通过I2C总线连接,将传感器的SDA引脚连接到STM32的SDA引脚,将传感器的SCL引脚连接到STM32的SCL引脚。 3. 将STM32与实时时钟模块通过I2C总线连接,将模块的SDA引脚连接到STM32的SDA引脚,将模块的SCL引脚连接到STM32的SCL引脚。 关于源代码方面,我们需要编写针对STM32的C语言程序。程序的主要功能包括: 1. 初始化STM32的I2C总线通信功能。 2. 初始化实时时钟并设置初始时间、日期。 3. 通过I2C总线读取温度传感器的数据,并将数据转换为摄氏度。 4. 将获取的时间、日期和温度数据分别显示在OLED显示屏上。 实物图方面,可以提供一张电子时钟万年历温度OLED显示的实物照片。照片中可以展示完整的设备外观,包括STM32微控制器、OLED显示屏、温度传感器以及其他配件和连接线。 基于STM32的电子时钟万年历温度OLED显示是一款集成功能丰富的电子设备,它不仅实现了时间、日期和温度的准确显示,还提供了美观的用户界面。通过源代码和实物图,可以了解到具体的芯片连接和外观设计,从而更好地理解和操作这款电子设备。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值