注意使用事项:
开发板如下
由于外部晶振是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);
// 将引脚复用为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