基于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
相关文章:

基于STM32F407ZET6的环境温湿度监控系统(粤嵌GEC-M4)
注意使用事项: 开发板如下 由于外部晶振是8M,需要修改setup和stm32f4头文件的晶振值。 操作如下: system_stm32f4xx.c的254行 #define PLL_M 8stm32f4xx.h的127行 #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the Ex…...

2023年五一杯数学建模A题无人机定点投放问题求解全过程论文及程序
2023年五一杯数学建模 A题 无人机定点投放问题 原题再现: 随着科学技术的不断发展,无人机在许多领域都有着广泛的应用。对于空中执行定点投放任务的无人机,其投放精度不仅依赖于无人机的操作技术,而且还与无人机执行任务时所处状…...

Redis 7 第九讲 微服务集成Redis 应用篇
Jedis 理论 Jedis是redis的java版本的客户端实现,使用Jedis提供的Java API对Redis进行操作,是Redis官方推崇的方式;并且,使用Jedis提供的对Redis的支持也最为灵活、全面;不足之处,就是编码复杂度较高。 …...

c++day7
仿照vector手动实现自己的myVector,最主要实现二倍扩容功能 #include <iostream>using namespace std; template <typename T> class Myvector { private:T *start;//起始指针T *end;//数组末尾指针T *last;//数组有效长度的尾指针 public://定义无参构…...
C++学习概述
1.c 为啥需要头文件 如果您刚开始使用 C,您可能想知道为什么C需要 #include 头文件,以及为什么一个程序要拥有多个 .cpp 文件。 原因很简单: a) 减少编译时间 随着程序的增长,您的代码也会增长,如果所有内容都在一个…...
关系型数据库和非关系型数据库
关系型数据库和非关系型数据库 关系型数据库非关系型数据库 非关系型数据库和关系型数据库是两种不同类型的数据库管理系统,它们用于存储和管理数据,但在数据组织和处理方式上有一些重要的区别。 关系型数据库 1.结构化数据存储:关系型数据库…...

基于SSM的快餐店点餐服务系统设计与实现
末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…...
使用vcpkg配置CGAL+visual studio 2022
先安装vcpkg C:\dev> git clone https://github.com/microsoft/vcpkg C:\dev> cd vcpkg C:\dev\vcpkg> .\bootstrap-vcpkg.bat 运行后,先执行 C:\dev\vcpkg> .\vcpkg.exe install yasm-tool:x86-windows 这是因为gmp库中有个bug,只能这样…...

【Spring面试】三、Bean的配置、线程安全、自动装配
文章目录 Q1、什么是Spring Bean?和对象有什么区别Q2、配置Bean有哪几种方式?Q3、Spring支持的Bean有哪几种作用域?Q4、单例Bean的优势是什么?Q5、Spring的Bean是线程安全的吗?Q6、Spring如何处理线程并发问题…...
flink连接kafka报:org.apache.kafka.common.errors.TimeoutException
测试flink1.12.7 连接kafka: package org.test.flink;import org.apache.flink.api.common.serialization.SimpleStringSchema; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.api.environment.StreamExecutio…...
sql order by 排序 null值放最后,怎么写
在 SQL 中,可以使用 ORDER BY 子句对结果进行排序。如果要将 NULL 值放在最后,可以在排序列中使用 CASE 表达式来处理。 下面是一个示例查询,将 NULL 值放在最后进行排序: SELECT column1, column2 FROM your_table ORDER BY CAS…...

HDMI字符显示实验
FPGA教程学习 第十五章 HDMI字符显示实验 文章目录 FPGA教程学习前言实验原理程序设计像素点坐标模块字符叠加模块 实验结果知识点总结 前言 在HDMI输出彩条的基础上输出osd叠加信息。 实验原理 实验通过字符转换工具将字符转换为 16 进制 coe 文件存放到单端口的 ROM IP 核…...

Spring Cloud 框架搭建
Spring Cloud 框架搭建之一基础框架 创建父项目创建子项目 创建父项目 第一步:新建项目,填写基础信息 第二步:这里不需要其他组件直接点next即可。 第三步:pom文件添加下述代码,将父项目设置为pom文件形式打包&#…...
20个非常有用的单行Python代码片段
1. 写在前面 继上篇,继续在本文分享 20 个 Python 单行代码,可以在 30 秒或更短时间内轻松学会。这些单行代码不仅可以提高效率,同时使代码看起来更整洁、更易读。:) 个人博客: https://jianpengzhang.git…...
【LangChain系列 9】Prompt模版——MessagePromptTemplate
原文地址:【LangChain系列 9】Prompt模版——MessagePromptTemplate 本文速读: MessagePromptTemplate MessagesPlaceholder 在对话模型(chat model) 中, prompt主要是封装在Message中,LangChain提供了一些MessagePromptTemplat…...
ROS2的学习路径
学习ROS2的建议学习路径: 理解基础知识: 熟悉机器人操作系统(ROS)的概念及其架构。了解ROS2相对于ROS1的优势以及其提供的关键功能。 安装和配置: 在你选择的操作系统上安装ROS2(如Ubuntu、Windows、macOS…...
Maintaining leader role through timed lease mechanism
Continuous understanding of distributed systems design On the one hand 基于定时的租约机制来保持leader角色 基于定时的租约机制来保持leader角色的设计思想是一种在分布式系统中确保高可用性和系统一致性的解决方法。 在分布式系统中,通常会有一个角色被选举…...

Mysql InnoDB引擎 的hash索引
Mysql InnoDB引擎不支持hash索引,但是在内存结构中有一个自适应hash索引,来提高查询性能 当设置hash索引时会自动转换成btree索引 查一下mysql官方文档:https://dev.mysql.com/doc/refman/5.7/en/create-index.html innodb_adaptive_hash_i…...

23年PMP考试如何备考?
接下来我要分享的备考建议分为三个部分,考试相关、备考期间注意和刷题建议。 1、PMP考试相关 PMP考试时间一定不能忘记,要密切关注,或许会出现延期的情况。考试教材现在是第七版教材,建议买一本或者用pdf电子版打印出来…...
mysql数据库增量备份方案、备份计划(InsCode AI 创作助手)
一、备份计划 以下是MySQL数据库增量备份的一般计划: 创建完整备份:在自动备份计划开始前,先创建一次完整备份。这个备份将包含所有数据和表结构。保存增量备份:在每次备份计划完成后,保存增量备份。这个备份将包含从…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...