基于STM32F407ZET6的环境温湿度监控系统(粤嵌GEC-M4)

注意使用事项:
开发板如下
在这里插入图片描述

由于外部晶振是8M,需要修改setup和stm32f4头文件的晶振值。
操作如下:
system_stm32f4xx.c的254行

#define PLL_M      8

stm32f4xx.h的127行

  #define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */

基于STM32F407ZET6的环境温湿度监控系统

  • 工程文件下载如下
  • 功能介绍和使用说明
  • 如下代码
    • 目录如下
    • main.c
    • system.c
    • system.h
    • KEY.c
    • KEY.h
    • LED.c
    • LED.h
    • BEEP.c
    • BEEP.h
    • UART.c
    • UART.h
    • CODED_LOCK.c
    • CODED_LOCK.h
    • TIMER.c
    • TIMER.h
    • DHT11.c
    • DHT11.h
    • ADC.c
    • ADC.h

工程文件下载如下

下载点这里

功能介绍和使用说明

下载程序后打开串口调试助手,按一下复位按键,如图。
在这里插入图片描述
通过按键输入1234进入,或者输入指令open#进入系统,密码错误会连响两下,正确会长响一下,进入之后如图。
在这里插入图片描述
到了控制界面,通过输入指令mode0或者mode1切换手动模式和自动模式,手动模式可以使用滑动变阻器控制LED1亮度,自动模式可以由光敏电阻调节灯光亮度。
温度阈值和湿度阈值是温度和湿度的临界值,当温度高于临界值,LED3亮,否则灭,当湿度高于临界值,LED2亮。
灯光亮度是滑动变阻器值,光照值是光敏电阻值。
温度阈值可以由指令txx修改,比如t20就是修改到20
湿度阈值可以由指令hxx修改,比如h20就是修改到20
最后输入off#退出系统

如下代码

目录如下

在这里插入图片描述

main.c

#include "CODED_LOCK.h"int main(void)
{while(1){CODED_LOCK_Open();}
}

system.c

#include "system.h"void System_Init(void)
{LED_Init();KEY_Init();BEEP_Init();UART1_Init(115200);//TIM3_Init(10000,8400);//ADC1_Init();adc_init();adc3_init();TIM14_init();TIM_SetCompare1(TIM14,95);
}//软件延时
void delay_us(uint32_t nus)
{SysTick->CTRL = 0; 			// Disable SysTick,关闭系统时钟后才能设置寄存器SysTick->LOAD = SystemCoreClock/8/1000000*nus; 		//设置计数值SysTick->VAL = 0; 			// Clear current value as well as count flag,清空当前值还有标志位SysTick->CTRL = 1; 			// Enable SysTick timer with processor clock,使能系统定时器开始计算,且使用8分频的时钟while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set,等待计数完成SysTick->CTRL = 0; 			// Disable SysTick,关闭系统时钟代表说不再进行定时计数	}void delay_ms(uint32_t nms)
{while(nms --){SysTick->CTRL = 0; 			// Disable SysTick,关闭系统时钟后才能设置寄存器SysTick->LOAD = SystemCoreClock/8/1000; 		// 设置计数值SysTick->VAL = 0; 			// Clear current value as well as count flag,清空当前值还有标志位SysTick->CTRL = 1; 			// Enable SysTick timer with processor clock,使能系统定时器开始计算,且使用8分频的时钟while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set,等待计数完成SysTick->CTRL = 0; 			// Disable SysTick,关闭系统时钟代表说不再进行定时计数	}
}

system.h

#ifndef __system_H_
#define __system_H_#include "stm32f4xx.h"
#include "LED.h"
#include "BEEP.h"
#include "KEY.h"
#include "UART.h"
#include "TIMER.h"
#include "DHT11.h"
#include "ADC.h"
#include "string.h"//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).M4同M3类似,只是寄存器地址变了.
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+\((addr & 0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))//把值类型转成地址类型
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+20) //0x40020014
#define GPIOB_ODR_Addr    (GPIOB_BASE+20) //0x40020414 
#define GPIOC_ODR_Addr    (GPIOC_BASE+20) //0x40020814 
#define GPIOD_ODR_Addr    (GPIOD_BASE+20) //0x40020C14 
#define GPIOE_ODR_Addr    (GPIOE_BASE+20) //0x40021014 
#define GPIOF_ODR_Addr    (GPIOF_BASE+20) //0x40021414    
#define GPIOG_ODR_Addr    (GPIOG_BASE+20) //0x40021814   
#define GPIOH_ODR_Addr    (GPIOH_BASE+20) //0x40021C14    
#define GPIOI_ODR_Addr    (GPIOI_BASE+20) //0x40022014     #define GPIOA_IDR_Addr    (GPIOA_BASE+16) //0x40020010 
#define GPIOB_IDR_Addr    (GPIOB_BASE+16) //0x40020410 
#define GPIOC_IDR_Addr    (GPIOC_BASE+16) //0x40020810 
#define GPIOD_IDR_Addr    (GPIOD_BASE+16) //0x40020C10 
#define GPIOE_IDR_Addr    (GPIOE_BASE+16) //0x40021010 
#define GPIOF_IDR_Addr    (GPIOF_BASE+16) //0x40021410 
#define GPIOG_IDR_Addr    (GPIOG_BASE+16) //0x40021810 
#define GPIOH_IDR_Addr    (GPIOH_BASE+16) //0x40021C10 
#define GPIOI_IDR_Addr    (GPIOI_BASE+16) //0x40022010 //IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 #define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 #define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 #define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 #define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入#define PHout(n)   BIT_ADDR(GPIOH_ODR_Addr,n)  //输出 
#define PHin(n)    BIT_ADDR(GPIOH_IDR_Addr,n)  //输入#define PIout(n)   BIT_ADDR(GPIOI_ODR_Addr,n)  //输出 
#define PIin(n)    BIT_ADDR(GPIOI_IDR_Addr,n)  //输入void System_Init(void);
void delay_us(uint32_t nus);
void delay_ms(uint32_t nms);#endif 

KEY.c

#include "KEY.h" void KEY_Init(void)
{GPIO_InitTypeDef gpio;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOE,ENABLE);gpio.GPIO_Mode=GPIO_Mode_IN;	gpio.GPIO_PuPd=GPIO_PuPd_UP;gpio.GPIO_Pin=GPIO_Pin_0;GPIO_Init(GPIOA,&gpio);gpio.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;	GPIO_Init(GPIOE,&gpio);
}

KEY.h

#ifndef __KEY_H_
#define __KEY_H_#include "system.h" #define KEY0 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
#define KEY1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)
#define KEY2 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)
#define KEY3 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)
#define KEY ((KEY0)|(KEY1<<1)|(KEY2<<2)|(KEY3<<3))void KEY_Init(void);
//unsigned char KEY_Scan(void);#endif 

LED.c

#include "LED.h" void LED_Init(void)
{GPIO_InitTypeDef gpio;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOE,ENABLE);gpio.GPIO_Mode=GPIO_Mode_OUT;	gpio.GPIO_PuPd=GPIO_PuPd_UP;gpio.GPIO_Speed=GPIO_Speed_100MHz;gpio.GPIO_OType=GPIO_OType_PP;gpio.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10;GPIO_Init(GPIOF,&gpio);gpio.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_14;	GPIO_Init(GPIOE,&gpio);GPIO_SetBits(GPIOF,GPIO_Pin_9|GPIO_Pin_10);GPIO_SetBits(GPIOE,GPIO_Pin_13|GPIO_Pin_14);
}

LED.h

#ifndef __LED_H_
#define __LED_H_#include "system.h"
void LED_Init(void);#endif 

BEEP.c

#include "BEEP.h" void BEEP_Init(void)
{GPIO_InitTypeDef gpio;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);gpio.GPIO_Mode=GPIO_Mode_OUT;	gpio.GPIO_PuPd=GPIO_PuPd_UP;gpio.GPIO_Speed=GPIO_Speed_100MHz;gpio.GPIO_OType=GPIO_OType_PP;gpio.GPIO_Pin=GPIO_Pin_8;GPIO_Init(GPIOF,&gpio);GPIO_ResetBits(GPIOF,GPIO_Pin_8);	
}

BEEP.h

#ifndef __BEEP_H_
#define __BEEP_H_#include "system.h" 
void BEEP_Init(void);#endif 

UART.c

#include "UART.h"void UART1_Init(uint32_t baudrate) 
{GPIO_InitTypeDef GPIO_InitStruct;USART_InitTypeDef USART_InitStruct;NVIC_InitTypeDef NVIC_InitStructure;// 使能USART1和GPIOA的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);// 配置USART1的引脚GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; // PA9(TX), PA10(RX)GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;GPIO_Init(GPIOA, &GPIO_InitStruct);// 将引脚复用为USART1GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); // TXGPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); // RX// 配置USART1USART_InitStruct.USART_BaudRate = baudrate;USART_InitStruct.USART_WordLength = USART_WordLength_8b;USART_InitStruct.USART_StopBits = USART_StopBits_1;USART_InitStruct.USART_Parity = USART_Parity_No;USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_Init(USART1, &USART_InitStruct);/* 配置中断参数--使能中断 */NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);//设置中断条件---接收缓冲区有数据就产生中断USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);// 使能USART1USART_Cmd(USART1, ENABLE);}int fputc(int ch, FILE *f)
{/* 发送一个字节数据到串口 */USART_SendData(USART1, (uint8_t) ch);/* 等待发送完毕 */while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);		return (ch);
}///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{/* 等待串口输入数据 */while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);return (int)USART_ReceiveData(USART1);
}
extern uint8_t usart_recv[1024];//接受串口数据---字符串
extern int recv_i;//接收数组下标
extern int recv_end;//接收标记  0 没有完  1 完了void USART1_IRQHandler(void)//"hello#"
{uint8_t d;//检测中断是否产生if(USART_GetITStatus(USART1, USART_IT_RXNE)==SET){d =USART_ReceiveData(USART1);if(recv_i < 1024&& d != '#'&& recv_end ==0){usart_recv[recv_i++] = d;}else{recv_end = 1;}//把接收的数据回发给发送方//USART_SendData(USART1,d); //h//while(USART_GetFlagStatus( USART1,USART_FLAG_TXE)==0);//等待上一个数据发送完毕}//把中断标志位清空,方便接收下一次中断USART_ClearITPendingBit(USART1, USART_IT_RXNE);}

UART.h

#ifndef __UART_H_
#define __UART_H_#include <stdio.h>
#include "system.h"void UART1_Init(uint32_t baudrate) ;#endif 

CODED_LOCK.c

#include "CODED_LOCK.h"uint8_t pass_num[4]={1,2,3,4};
uint8_t input_num[4]={0,0,0,0};
uint8_t open=0;
uint8_t dht_data[5];
int ret = 0;
uint32_t adc_val;
int adc_vol;
uint32_t light_val;
int light_vol;unsigned char mode=0;uint8_t usart_recv[1024]={0};//接受串口数据---字符串
int recv_i = 0;//接收数组下标
int recv_end = 0;//接收标记  0 没有完  1 完了int byte_light=40;
int byte_temp=40;
int byte_humi=90;
char display=1;
void CODED_LOCK_Open(void)
{System_Init();while(1){if(recv_end ==1){if(strncmp((char *)usart_recv,"open",6)== 0){//打开D1input_num[0]=1;input_num[1]=2;input_num[2]=3;input_num[3]=4;}else if(strncmp((char *)usart_recv,"mode1",6)== 0)mode=1;else if(strncmp((char *)usart_recv,"mode0",6)== 0)mode=0;else if(strncmp((char *)usart_recv,"display",7)== 0)display=1;else if(strncmp((char *)usart_recv,"off",7)== 0)open=0;else if(usart_recv[0]==116){//printf("recv is %d ,%d\n",usart_recv[1]-48,usart_recv[2]-48);byte_temp=(usart_recv[1]-48)*10+(usart_recv[2]-48);}else if(usart_recv[0]==104){//printf("recv is %d ,%d\n",usart_recv[1]-48,usart_recv[2]-48);byte_humi=(usart_recv[1]-48)*10+(usart_recv[2]-48);}memset(usart_recv,0,1024);//清空接收缓冲区数组recv_end = 0;//接收标志置零,方便下一个字符串的接收recv_i = 0;//下标清零display=1;}		
//		USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
//		TIM_ITConfig(TIM3,TIM_IT_Update , DISABLE);ADC_SoftwareStartConv(ADC1);//等待转换完成while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)!=SET);//获取ADC1的转换结果adc_val=ADC_GetConversionValue(ADC1);//将结果值转换为电压值adc_vol=adc_val*100/4095;ADC_SoftwareStartConv(ADC3);//等待转换完成while(ADC_GetFlagStatus(ADC3,ADC_FLAG_EOC)!=SET);//获取ADC1的转换结果light_val=ADC_GetConversionValue(ADC3);//将结果值转换为电压值light_vol=light_val*100/4095;
//		TIM_ITConfig(TIM3,TIM_IT_Update , ENABLE);
//		USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);		if((mode==1)&&(open==1)){TIM_SetCompare1(TIM14,90-light_vol);}else if((mode==0)&&(open==1)){TIM_SetCompare1(TIM14,110-adc_vol);}			 if(open==1){if(dht_data[0]<byte_humi)PFout(10)=1;else PFout(10)=0;if(dht_data[2]<byte_temp)PEout(13)=1;else PEout(13)=0;}ret = Get_DHT11_Data(dht_data);KEY_Scan();if((input_num[0]!=0)&&(input_num[1]!=0)&&(input_num[2]!=0)&&(input_num[3]!=0)){if((input_num[0]==pass_num[0])&&(input_num[1]==pass_num[1])&&(input_num[2]==pass_num[2])&&(input_num[3]==pass_num[3])){PFout(8)=1;delay_ms(1000);PFout(8)=0;open=1;display=1;}else{PFout(8)=1;delay_ms(500);PFout(8)=0;delay_ms(500);PFout(8)=1;delay_ms(500);PFout(8)=0;printf("密码错误,请重新输入\r\n");open=0;}input_num[0]=input_num[1]=input_num[2]=input_num[3]=0;}if((open==1)&&(display==1)){display=0;printf("/**************温湿度控制界面******************/\r\n");if(mode==0)printf("/*****模式:手动\r\n");if(mode==1)printf("/*****模式:自动\r\n");printf("/*****当前湿度:%d/\r\n",dht_data[0]);printf("/*****当前温度:%d/\r\n",dht_data[2]);printf("/*****灯光亮度:%d/\r\n",adc_vol);printf("/*****光照值:%d/\r\n",110-light_vol);printf("/*****湿度阈值:%d/\r\n",byte_humi);printf("/*****温度阈值:%d/\r\n",byte_temp);printf("/**********************************************/\r\n");}if((open==0)&&(display==1)){display=0;printf("/**************密码输入界面******************/\r\n");printf("密码:%d %d %d %d\r\n",input_num[0],input_num[1],input_num[2],input_num[3]);printf("/**********************************************/\r\n");}		}
}void Input_Data(char data)
{if(input_num[0]==0){input_num[0]=data;display=1;}else if(input_num[1]==0){input_num[1]=data;display=1;}else if(input_num[2]==0){input_num[2]=data;display=1;}else if(input_num[3]==0){input_num[3]=data;display=1;}
}void KEY_Scan(void)
{static char keybyte=0;static char key=0x0f;//static char return_num=0;//if(KEY==0x0f)return 1;if((KEY!=0x0f)&&(keybyte==0)){key=0x0f;key &=KEY;keybyte=1;}if((KEY==0x0f)&&(keybyte==1)){keybyte=0;switch(key){case 0x0e:Input_Data(1);break;case 0x0d:Input_Data(2);break;case 0x0b:Input_Data(3);break;case 0x07:Input_Data(4);break;//default: return 0;}}
}

CODED_LOCK.h

#ifndef __CODED_LOCK_H_
#define __CODED_LOCK_H_#include "system.h"
void CODED_LOCK_Init(void);
void CODED_LOCK_Open(void);
void KEY_Scan(void);
void Input_Data(char data);#endif 

TIMER.c

#include "TIMER.h"//tim3初始化
void TIM3_Init(uint32_t period,uint32_t Prescaler)
{//period=5000 Prescaler=8400TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;/* 打开TIM3时钟  */RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//定时器参数配置:频率  计数值 方向。。。。。中断间隔500ms  中断频率 2hzTIM_TimeBaseStructure.TIM_Period = period;//计数值10000 时间就过去1s  10时间过去1msTIM_TimeBaseStructure.TIM_Prescaler = Prescaler;//设置频率  分频值  84000 000hz/8400  10000hz 1s数10000个数TIM_TimeBaseStructure.TIM_ClockDivision = 0;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);/* 配置定时器3的中断参数 */NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);/* 设置中断条件 */TIM_ITConfig(TIM3,TIM_IT_Update , ENABLE);/*启动定时器计数*/TIM_Cmd(TIM3, ENABLE);}//定时器14 通道1 初始化
void TIM14_init(void)
{TIM_OCInitTypeDef  TIM_OCInitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;GPIO_InitTypeDef GPIO_InitStructure;/* 定时器14的时钟使能*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);/*定时器的基本配置,用于配置定时器的输出脉冲的频率为200Hz */TIM_TimeBaseStructure.TIM_Period = 10000/200-1;					//设置定时脉冲的频率TIM_TimeBaseStructure.TIM_Prescaler = 8400-1;						//第一次分频,简称为预分频TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;				//第二次分频,当前实现1分频,也就是不分频TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure);/* 配置PF9 引脚为复用模式 */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;					//第9根引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;				//设置复用模式GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;				//推挽模式,增加驱动电流GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;			//设置IO的速度为100MHz,频率越高性能越好,频率越低,功耗越低GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;			//不需要上拉电阻GPIO_Init(GPIOF, &GPIO_InitStructure);	GPIO_PinAFConfig(GPIOF, GPIO_PinSource9, GPIO_AF_TIM14);/* 让定时器14 PWM 的通道 1 工作在模式 1*///PWM 模式 1, 在递增模式下, 只要TIMx_CNT < TIMx_CCR1, 通道 1 便为有效状态(高电平), 否则为无效状态(低电平)。TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //允许输出TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 		//有效的时候, 输出高电平TIM_OC1Init(TIM14, &TIM_OCInitStructure);//TIMx_CCR1比较值的设置是由TIM_SetCompare1、TIM_SetCompare2、TIM_SetCompare3、TIM_SetCompare4来进行设置TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);  //自动重载初值, 不断输出 PWM 脉冲TIM_ARRPreloadConfig(TIM14, ENABLE); 				//自动重载初值使能/*  使能定时器 14 工作 */TIM_Cmd(TIM14, ENABLE);
}

TIMER.h

#ifndef __TIMER_H_
#define __TIMER_H_#include "system.h"void TIM3_Init(uint32_t period,uint32_t Prescaler);
void TIM14_init(void);#endif 

DHT11.c

#include "DHT11.h"//PG9输出模式
void DHT11_Out()
{GPIO_InitTypeDef GPIO_InitStructure;/* 打开GPIOG的时钟  */RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);/* 选择引脚编号PF9 PF10,配置为输出模式 */GPIO_InitStructure.GPIO_Pin =GPIO_Pin_9;//9号引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//输出模式GPIO_Init(GPIOG, &GPIO_InitStructure); PGout(9) = 1;
}//PG9输入模式
void DHT11_In()
{GPIO_InitTypeDef GPIO_InitStructure;/* 打开GPIOG的时钟  */RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);GPIO_InitStructure.GPIO_Pin =GPIO_Pin_9;//0号引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//输入模式GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//添加上拉电阻GPIO_Init(GPIOG, &GPIO_InitStructure); 
}//读取一个字节(8bit)的数据
uint8_t Read_DHT11_Byte()//1101 0000
{uint8_t byte = 0;//0000 0000 int i = 0;for(i = 0;i<8;i++){//等待低电平时隙结束while(PGin(9) == 0);delay_us(40);if(PGin(9) == 1){//当前数据就是1				       byte = byte|(1<<(7-i));//等待为1时70us的高电平结束while(PGin(9) == 1);}		}return byte;
}//获取一次温湿度数据
int Get_DHT11_Data(uint8_t *DHT11_Data)
{int i = 0;int t = 0;//1.32芯片发送开始信号//PG9输出模式DHT11_Out();PGout(9) = 0;delay_ms(20);PGout(9) = 1;delay_us(30);//2.32芯片等待回响信号---dht11发送响应信号//PG9输入模式DHT11_In();while(PGin(9) == 1)//等待响应信号到来{delay_us(1);t++;if(t >200){return 1;}						}t= 0;while(PGin(9) == 0)//等待响应信号低电平结束{delay_us(1);t++;if(t >200){return 2;}		}t = 0;while(PGin(9) == 1)//等待响应信号高电平结束{delay_us(1);t++;if(t >200){return 3;}		}//3.32芯片接收温湿度数据---dht11发送温湿度数据 (40bit)for(i = 0;i <5; i++){//获取8bit(一个字节)的数据DHT11_Data[i] = Read_DHT11_Byte();}//4.校验数据是否正常if(DHT11_Data[0]+DHT11_Data[1]+DHT11_Data[2]+DHT11_Data[3] == DHT11_Data[4]){return 0;}}

DHT11.h

#ifndef __DHT11_H_
#define __DHT11_H_#include "system.h"int Get_DHT11_Data(uint8_t *DHT11_Data);
void DHT11_Out();
void DHT11_In();
uint8_t Read_DHT11_Byte();#endif 

ADC.c

#include "ADC.h"void adc_init(void)
{GPIO_InitTypeDef GPIO_InitStructure;ADC_InitTypeDef       ADC_InitStructure;ADC_CommonInitTypeDef ADC_CommonInitStructure;ADC_StructInit(&ADC_InitStructure);RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//初始化PA5引脚为模拟模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;GPIO_Init(GPIOA, &GPIO_InitStructure);/* ADC常规的初始化*/ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;						//独立模式,只使用一个ADC硬件进行工作ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;						//ADC硬件的频率=84MHz/2=42MHzADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;			//取消DMA访问模式//ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;	//如果采用了多个ADC硬件对某个通道进行采样的,那么这个时间就是他们硬件工作的相隔时间ADC_CommonInit(&ADC_CommonInitStructure);										/* ADC1初始化*/ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;							//12bit精度,非常重要[*]ADC_InitStructure.ADC_ScanConvMode = DISABLE;									//因不需要多个ADC硬件对某个通道进行采样,则不需要连续扫描ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;								//连续转换,就是ADC硬件一直进行转换输出结果,否则只得到一个结果ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;		//禁止外部脉冲触发ADC硬件工作//ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;							//存储的结构使用右对齐的存储方式[*]//ADC_InitStructure.ADC_NbrOfConversion = 1;									//这个是在DMA模式生效的,转换的结果总数数量是放到内存当中	ADC_Init(ADC1, &ADC_InitStructure);/* ADC1的通道5的配置指定ADC1的通道5,它的优先级为最高1(范围:1~16),采样时间为3个ADC时钟周期=3*1/f=3*(1/42MHz)*/ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_3Cycles);/* 使能ADC工作 */ADC_Cmd(ADC1, ENABLE);}void adc3_init(void)
{GPIO_InitTypeDef GPIO_InitStructure;ADC_InitTypeDef       ADC_InitStructure;ADC_CommonInitTypeDef ADC_CommonInitStructure;ADC_StructInit(&ADC_InitStructure);RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);//初始化PA5引脚为模拟模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;GPIO_Init(GPIOF, &GPIO_InitStructure);/* ADC常规的初始化*/ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;						//独立模式,只使用一个ADC硬件进行工作ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;						//ADC硬件的频率=84MHz/2=42MHzADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;			//取消DMA访问模式//ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;	//如果采用了多个ADC硬件对某个通道进行采样的,那么这个时间就是他们硬件工作的相隔时间ADC_CommonInit(&ADC_CommonInitStructure);										/* ADC1初始化*/ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;							//12bit精度,非常重要[*]ADC_InitStructure.ADC_ScanConvMode = DISABLE;									//因不需要多个ADC硬件对某个通道进行采样,则不需要连续扫描ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;								//连续转换,就是ADC硬件一直进行转换输出结果,否则只得到一个结果ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;		//禁止外部脉冲触发ADC硬件工作//ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;							//存储的结构使用右对齐的存储方式[*]//ADC_InitStructure.ADC_NbrOfConversion = 1;									//这个是在DMA模式生效的,转换的结果总数数量是放到内存当中	ADC_Init(ADC3, &ADC_InitStructure);/* ADC1的通道5的配置指定ADC1的通道5,它的优先级为最高1(范围:1~16),采样时间为3个ADC时钟周期=3*1/f=3*(1/42MHz)*/ADC_RegularChannelConfig(ADC3, ADC_Channel_5, 1, ADC_SampleTime_3Cycles);/* 使能ADC工作 */ADC_Cmd(ADC3, ENABLE);}

ADC.h

#ifndef __ADC_H_
#define __ADC_H_#include "system.h" //void ADC1_Init(void);void adc_init(void);void adc3_init(void);
#endif 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/132338.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023/9/14 -- C++/QT

作业&#xff1a; 仿照Vector实现MyVector&#xff0c;最主要实现二倍扩容 #include <iostream>using namespace std;template <typename T> class MyVector { private:T *data;size_t size;size_t V_capacity; public://无参构造MyVector():data(nullptr),size(…

【深度学习 AIGC】stablediffusion-infinity 在无界限画布中输出绘画 Outpainting

代码&#xff1a;https://github.com/lkwq007/stablediffusion-infinity/tree/master 启动环境&#xff1a; git clone --recurse-submodules https://github.com/lkwq007/stablediffusion-infinity cd stablediffusion-infinity conda env create -f environment.yml conda …

如何开启Win10虚拟机Hyper-V功能

操作步骤: 使用前提&#xff1a; 1、确保系统是 Windows 10 专业版/企业版/教育版&#xff0c;且必须是64位操作系统才支持。 提示&#xff1a;Win10家庭版不支持hyper-v。 2、使用Hyper-V需要cpu支持虚拟化并处于开启状态。 3、硬件要求及如何验证硬件兼容性&#xff1a; 硬件…

什么是云存储,从对象存储说起?

在《存储系统形态之争,从块存储到统一存储》一文中我们提到了对象存储的概念,知道目前很多企业级存储都是支持对象存储的,比如EMC、NetApp和华为等。以EMC的对象存储为例,其最早在1998年就已经具备成熟的产品了,到目前已经有二十多年的历史了。如图是关于对象存储主要产品…

SpringMVC之JSR303和拦截器

一.什么是JSR303 二.JSR303 常用注解 作用 使用 导入pom.xml 在实体类相对应的属性中增加注解用来指定校验 在hpjyController里面新加以下代码 修改eidt.jsp 测试结果 ​编辑 二.拦截器 什么是拦截器 拦截器与过滤器的区别 应用场景日志记录&#xff1a;拦截器可以用…

图解第一类曲线积分与第二类曲线积分的关系

图解第一类曲线积分与第二类曲线积分的关系 笔记相关内容&#xff1a; 1.曲线积分&#xff08;Line Integral&#xff09; 2.向量场中的曲线积分、环量、通量 第一类曲线积分&#xff08;对弧长 d s ds ds进行积分&#xff09;(无方向性) 物理意义&#xff1a; f ( x , y ) f(…

Docker 一键安装Confluence(已支持最新版本)

Docker 一键安装Confluence&#xff08;已支持最新版本&#xff09; 本文用于Confluence在Docker的安装&#xff0c;仅用于记录安装方式Jira 也可以参考这种方式安装&#xff0c;只有细微差别转载请注明来源Linux安装可参考链接Windows安装可查考链接条件允许时&#xff0c;请…

java编辑pdf(itextpdf)

工作上遇到一个小需求&#xff0c;需要在原有的pdf文件上添加一行文字&#xff0c;实现方式如下 引入依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version></dependen…

【千万别上当】揭秘又一个割韭菜的项目:明星网红直播切片项目

今天在某乎浏览内容&#xff0c;看到一篇文章《我做了10个某音号&#xff0c;不拍视频&#xff0c;不直播&#xff0c;光靠剪辑明星素材月入8K&#xff0c;给缺钱的朋友推荐一个无脑赚Q的自媒体项目》&#xff0c;点击进去一看&#xff0c;洋洋洒洒估计有一两万字&#xff0c;过…

【SA8295P 源码分析】97 - QNX AIS Camera 框架介绍 及 Camera 工作流程分析

【SA8295P 源码分析】97 - QNX AIS Camera 框架介绍 及 Camera 工作流程分析 一、QNX AIS Server 框架分析二、QNX Hypervisor / Android GVM 方案介绍三、Camera APP 调用流程分析四、QCarCam 状态转换过程介绍五、Camera 加串-解串 硬件链路分析六、摄像头初始化检测过程介绍…

原生js vue react通用的递归函数

1.递归函数的由来 递归函数的由来可以追溯到数学中的递归概念和数学归纳法。 在数学中&#xff0c;递归是指通过定义基本情况和递推公式&#xff0c;将一个问题分解为更简单的、与原问题具有相同结构的子问题&#xff0c;并用子问题的解来构建原问题的解。递归的思想在解决一些…

【JavaScript】在指定dom元素前面创建标签元素

一、基础操作过程 要在指定的DOM元素前面创建标签元素&#xff0c;有以下步骤&#xff1a; 获取指定的DOM元素&#xff1a;使用document.querySelector()或document.getElementById()等方法来获取指定的DOM元素。 const targetElement document.querySelector(#targetElement…

NOA高歌猛进,智驾地图何去何从?

作者|德新 编辑|王博 今年是辅助驾驶的量产大年&#xff0c;尤其高阶智能驾驶&#xff0c;带动了上游需求的爆发。 一些典型的科技赛道&#xff0c;如激光雷达、大算力芯片等环节都从中受益。禾赛科技、地平线近期都公布了产品出货达到新的里程碑。禾赛AT系列产品上半年的出货…

亲测好用-obsidian无法打开插件库安装或更新的解决办法-结合FastGithub

写在前面 经过半年左右时间的使用情况验证该方案稳定可靠。 方案&#xff1a;插件“Plugin Proxy” 软件“FastGithub” 效果&#xff1a; 插件“Plugin Proxy” 下载地址&#xff1a; https://github.com/gslnzfq/obsidian-proxy-server 插件安装&#xff1a; 插件设置为…

多态的笔记

什么是多态 顾名思义多态就是让一个对象拥有不同的形态 举例如下 多态的应用场景&#xff0c;比如你注册的时候&#xff0c;你可能注册为学生&#xff0c;老师&#xff0c;管理员&#xff0c;但是此时你往函数传递的类型是什么呢&#xff0c;此时你无论传递什么都不太合适&am…

Marin说PCB之封装设计系列---(02)--异形焊盘的封装设计总结

每天下班回家看电视本来是一件很美好的事情&#xff0c;可是正当我磕着瓜子看着异人之下的时候&#xff0c;手机突然响起来了&#xff0c;我以为是我们组哪个同事找我呢。一接电话居然是我的老朋友陈世美陈总&#xff0c;江湖人称少妇杀手。给我打电话主要是说他最近遇到一个异…

回归预测 | MATLAB实现PSO-SDAE粒子群优化堆叠去噪自编码器多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现PSO-SDAE粒子群优化堆叠去噪自编码器多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现PSO-SDAE粒子群优化堆叠去噪自编码器多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览…

【建议收藏】自动化测试框架开发教程

在自动化测试项目中&#xff0c;为了实现更多功能&#xff0c;我们需要引入不同的库、框架。 首先&#xff0c;你需要将常用的这些库、框架都装上。 pip install requests pip install selenium pip install appium pip install pytest pip install pytest-rerunfailures pip …

华为GaussDB数据库

Gauss数据库初识_高斯数据库_ygpGoogle的博客-CSDN博客 Redhat 7.6安装GaussDB_100_1.0.1详细攻略_gaussdb_100_1.0.1-database-redhat-64bit.tar.gz dow_博德1999的博客-CSDN博客 https://www.ngui.cc/el/3381579.html?actiononClick 初识GaussDB——GaussDB的发展历程、部…

学习Bootstrap 5的第六天

目录 信息警告框 警告框 实例 警告框链接 实例 关闭警告框 实例 警告框动画 实例 按钮 按钮样式 实例 按钮轮廓 实例 ​编辑按钮尺寸 实例 块级按钮 实例 实例 活动/禁用按钮 实例 加载器按钮 实例 扩展小知识 按钮组 按钮组 实例 实例 垂直按钮组…