Umgebungstemperatur- und Luftfeuchtigkeitsüberwachungssystem basierend auf STM32F407ZET6 (Guangdong eingebetteter GEC-M4)

Hinweis zur Verwendung:
Das Entwicklungsboard sieht wie folgt aus
Fügen Sie hier eine Bildbeschreibung ein

Da der externe Quarzoszillator 8M ist, müssen die Quarzoszillatorwerte in den Setup- und STM32F4-Header-Dateien geändert werden.
Die Operation ist wie folgt:
Zeile 254 von system_stm32f4xx.c

#define PLL_M      8

Zeile 127 von stm32f4xx.h

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

Laden Sie die Projektdateien wie folgt herunter

Zum Herunterladen klicken Sie hier

Funktionseinführung und Gebrauchsanweisung

Öffnen Sie nach dem Herunterladen des Programms den Debugging-Assistenten für die serielle Schnittstelle und drücken Sie die Reset-Taste, wie in der Abbildung gezeigt.
Fügen Sie hier eine Bildbeschreibung ein
Geben Sie durch Drücken der Taste 1234 ein oder geben Sie den Befehl open# ein, um das System zu betreten. Wenn das Passwort falsch ist, ertönt zweimal hintereinander ein Piepton, und wenn Wenn das Passwort korrekt ist, ertönt einmal ein Piepton. Wie in der Abbildung gezeigt, nach der Eingabe.
Fügen Sie hier eine Bildbeschreibung ein
Geben Sie an der Steuerschnittstelle den Befehl mode0 oder mode1 ein, um zwischen manuellem Modus und automatischem Modus zu wechseln. Im manuellen Modus können Sie Kann die Helligkeit von LED1 mit einem Schieberheostat steuern, im Automatikmodus kann die Lichthelligkeit über einen Fotowiderstand angepasst werden.
Der Temperaturschwellenwert und der Feuchtigkeitsschwellenwert sind die kritischen Werte von Temperatur und Luftfeuchtigkeit. Wenn die Temperatur höher als der kritische Wert ist, leuchtet LED3 auf, andernfalls erlischt sie. Wenn die Luftfeuchtigkeit höher ist Unterschreitet der kritische Wert, leuchtet LED2.
Die Lichthelligkeit ist der Wert des Schiebewiderstands und der Lichtwert ist der Wert des Fotowiderstands.
Der Temperaturschwellenwert kann mit dem Befehl txx# geändert werden. Beispielsweise wird t20 auf 20 geändert. < a i=11> Der Feuchtigkeitsschwellenwert. Er kann mit dem Befehl geändert werden. Beispielsweise wird auf 20 geändert und Geben Sie abschließend ein, um das System zu verlassen.
hxx#h20
off#

Der folgende Code

Das Inhaltsverzeichnis lautet wie folgt

Fügen Sie hier eine Bildbeschreibung ein

Haupt 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 

SCHLÜSSEL.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);
}



SCHLÜSSEL.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);

  // 将引脚复用为USART1
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); // TX
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); // RX

  // 配置USART1
  USART_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);

  // 使能USART1
  USART_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)
			      {
    
    
			         //打开D1
				       input_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=8400
	 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	 NVIC_InitTypeDef NVIC_InitStructure;
	 /* 打开TIM3时钟  */
	 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
	 //定时器参数配置:频率  计数值 方向。。。。。中断间隔500ms  中断频率 2hz
	 TIM_TimeBaseStructure.TIM_Period = period;//计数值10000 时间就过去1s  10时间过去1ms
	 TIM_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=42MHz
	ADC_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=42MHz
	ADC_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 

Guess you like

Origin blog.csdn.net/darlingqx/article/details/132890210