代码程序
在资源里可以进行下载程序包(可以读取到超声波获取的距离,可以获取到烟雾传感器的电压,烟雾浓度。如果需要可以进行下载)。
有源蜂鸣器
以下是有源蜂鸣器的配置,配置内容主要有GPIO口,如有需要,更改宏定义的即可。
找到GPIO口,接上线路,获取GPIO口的高低电平,创建开关蜂鸣器函数,即为成功。
注意:有源蜂鸣器通常需要3V、5V或12V的电压,因此在使用有源蜂鸣器时需要准确设置电源电压。
//有源蜂鸣器
//.c文件
#include "stm32f10x.h"
#define BUZZER_PIN GPIO_Pin_11
#define BUZZER_GPIO GPIOD
#define BUZZER_RCC_GPIO RCC_APB2Periph_GPIOD
void buzzer_Init(void)
{
RCC_APB2PeriphClockCmd(BUZZER_RCC_GPIO,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;//框架
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IPU;//输入上拉模式
GPIO_InitStructure.GPIO_Pin=BUZZER_PIN ;// pin11
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//传输速度
GPIO_Init(BUZZER_GPIO,&GPIO_InitStructure);
GPIO_ResetBits(BUZZER_GPIO,BUZZER_PIN);
}
void buzzer_ON(void){
GPIO_SetBits(BUZZER_GPIO,BUZZER_PIN);
}
void buzzer_OFF(void){
GPIO_ResetBits(BUZZER_GPIO,BUZZER_PIN);
}
//.h文件
#ifndef __BUZZER_H
#define __BUZZER_H
void buzzer_Init(void);//初始化蜂鸣器
void buzzer_ON(void);//开启蜂鸣器
void buzzer_OFF(void);//关闭蜂鸣器
#endif
超声波模块
以下是超声波模块的配置,配置内容主要有GPIO口,定时器,如有需要,更改宏定义的即可。
找到GPIO口,接上线路,获取GPIO口的高低电平,配置定时器的初始化,配置具体的测距函数,接下来是拿到配置好了的测距函数,进行更加一步的判断,达到一定的需求,蜂鸣器进行报警。进行串口打印。
超声波模块:
超声波模块是一种常见的传感器模块,通过发射和接收超声波来测量距离或检测物体。其原理基于声波在介质中的传播和反射。
超声波模块由发射器和接收器组成。发射器会发射一束超声波脉冲,这些超声波脉冲通过空气或其他介质传播到目标物体上,然后被目标物体反射回来。接收器会接收到这些反射回来的超声波信号。
发射器和接收器之间有一个很小的时间间隔,测量器会计算发射超声波脉冲到达目标物体和接收反射波至接收器的时间间隔。根据声波的传播速度和时间间隔,可以计算出超声波在空气中的传播距离。
超声波模块的工作原理可以简化为以下几个步骤:
-
发射器发射超声波脉冲。
-
超声波在空气或介质中传播,直到碰到目标物体。
-
超声波被目标物体反射回来。
-
接收器接收到反射波信号。
-
测量器计算出超声波的传播时间间隔。
-
根据声波的传播速度和时间间隔计算出距离。
//超声波模块
//.c文件
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "main.h"
#include "Serial.h"
#include "Buzzer.h"
#include "main.h"
#define HCSR04_PORT GPIOD
#define HCSR04_PORTC_CLK_FUN RCC_APB2PeriphClockCmd
#define HCSR04_CLK RCC_APB2Periph_GPIOD
#define HCSR04_TRIG GPIO_Pin_14
#define HCSR04_ECHO GPIO_Pin_15
unsigned int dis_count = 0;//脉宽长计时
volatile unsigned int distance_cm = 0;//当前距离
u8 status = 0;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
extern uint32_t Systick_ms_count;
void SysTick_ISR_Count( void )
{
Systick_ms_count++;//
}
void Time4Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = (72 - 1);//72M / 72 = 1us
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
}
u8 Hcsr04GetLength(void )//测量距离
{
u8 res = 0;//状态 成功1,失败0 局部变量每次进来都会初始化
status = 1;//用于记录HC-SR04模块的状态,值为0表示没有进行测量,
// 值为1表示正在发送超声波,
// 值为2表示正在接收超声波的回声。
Trig_SET;//开始发送超声波
TIM_SetCounter(TIM4, 0);//设置TIM4的定时器的计数器值为0。
TIM_Cmd(TIM4, ENABLE);//打开定时器
while(TIM_GetCounter(TIM4) < 11);//延时超过10us
status = 2;//等待回声。
Trig_RESET;//将Trig信号复位
TIM_SetCounter(TIM4, 0);//将TIM4定时器的计数器值设置为0
while(Echo == 0)//等待回向信号起始位置
{
if(TIM_GetCounter(TIM4) > 60000)//回应时间超出正常范围
{
status = 0;
TIM_Cmd(TIM4, DISABLE);//关闭定时器
res = 1;//失败状态
return res;//本次失败
}
}
TIM_SetCounter(TIM4, 0);
while(Echo == 1)//开始计算长度
{
int count = TIM_GetCounter(TIM4);
if(count > 60000)//回应时间超出正常范围
{
status = 0;
TIM_Cmd(TIM4, DISABLE);//关闭定时器
res = 2;//等到了,不过时间太长
return res;//本次失败
}
}
dis_count = TIM_GetCounter(TIM4);
TIM_Cmd(TIM4, DISABLE);//关闭定时器
distance_cm = (unsigned int)(((long)(dis_count) * 34)/2000);//声速340m/s
status = 0;//准备下次发送
res = 0;
return res;
}
void SR04_if(void)
{
Delay_ms(300);
#if(ENABLE_HCR04)
float SR04_cm =150;
uint8_t res = Hcsr04GetLength();
if(res == 0){
printf("distance_cm = %dcm\n",distance_cm);
if(distance_cm>SR04_cm)
{
buzzer_ON();
Delay_ms(200);
buzzer_OFF();
}
}
else
printf("distance_cm get timeout,faultcode: %d\n",res);
#endif
Delay_ms(500);
}
//.h文件
#include "stm32f10x.h" // Device header
#ifndef __SR04__H
#define __SR04__H
void Time4Init(void);
unsigned int Hcsr04GetLength(void);
void SR04_if(void);
#endif
烟雾传感器
以下是烟雾模块的配置,配置内容主要有GPIO口,如有需要,更改上宏定义的即可。
建议了解一下程序的接线,本程序使用的是D0模式,没有使用A0口。
配置GPIO,进行GPIO高低电平的读取,进行if判断。获取配置好的Get_alarm_signal,进行判断,达到要求进行蜂鸣器开启,串口打印。
烟雾传感器:获取到的烟雾量越大,电压值越小,建议使用规定的电压口。
电化学烟雾传感器则使用氧气和燃烧产生的气体之间的反应。在传感器中有两个电极,其中一个电极覆盖着化学成分。当烟雾进入传感器时,烟雾中的有害气体会与化学成分发生反应,导致电流的变化。这种变化被传感器检测并用来判断烟雾的存在。
//烟雾传感器
//.c文件
#include "stm32f10x.h" // Device header
#include "Buzzer.h"
#include "Delay.h"
#include "Serial.h"
#include "MQ.h"
#include "main.h"
extern uint8_t alarm_state ;
#define MQ_RCC RCC_APB2Periph_GPIOD
#define MQ_PIN GPIO_Pin_0
#define MQ_GPIO GPIOD
void MQ_D0_Init(void)
{
RCC_APB2PeriphClockCmd(MQ_RCC,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//输入上拉模式
GPIO_InitStructure.GPIO_Pin=MQ_PIN ;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(MQ_GPIO,&GPIO_InitStructure);
}
uint8_t Get_alarm_signal(void)
{
uint8_t alarm=2;
uint8_t a1 = GPIO_ReadInputDataBit(MQ_GPIO,MQ_PIN );//按下去 0 亮,松开 1 灭
if (a1==0)
{
Delay_ms(100);
while(a1==0)
{
Delay_ms(100);
alarm=1;
return alarm;
}
}
else if(a1==1)
{
Delay_ms(100);
while(a1==1)
{
Delay_ms(100);
alarm=0;
return alarm;
}
}
return alarm;
}
void MQ_if(void)
{
Delay_ms(100);
#if(ENABLE_MQ02)
alarm_state = Get_alarm_signal();
if(alarm_state==0)
{
buzzer_OFF();
printf("alarm_state = %d,normal...\n",alarm_state);
}
else if(alarm_state==1)
{
buzzer_ON();
printf("alarm_state = %d,warning!!!\n",alarm_state);
}
else if(alarm_state==2)
{
buzzer_OFF();
printf("alarm_state get failure!!!\n");
}
#endif
}
//.h文件
#include "stm32f10x.h" // Device header
#ifndef _MQ2_H
#define _MQ2_H
void MQ_D0_Init(void);
uint8_t Get_alarm_signal(void);
void MQ_if(void);
#endif
串口的配置
//串口配置
//.c文件
#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>
#include "Buzzer.h"
#define BUZZER_RCC_USER RCC_APB2Periph_USART1
#define BUZZER_RCC_GPIO RCC_APB2Periph_GPIOA
#define BUZZER_TX GPIO_Pin_9 //实际是rx线
#define BUZZER_RX GPIO_Pin_10 //实际是tx线
#define BUZZER_GPIOx GPIOA
uint8_t Serial_RxDaata;
uint8_t Serial_RxFlag;
int _write(int file, char *ptr, int len)
{
for (int i = 0; i < len; i++)
{
// 发送到USART1数据寄存器
USART_SendData(USART1, (uint8_t)ptr[i]);
// 等待发送完成
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
return len;
}
void Serial_Init(void) //串口配置
{
RCC_APB2PeriphClockCmd(BUZZER_RCC_USER,ENABLE);
RCC_APB2PeriphClockCmd(BUZZER_RCC_GPIO,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_InitStructure.GPIO_Pin=BUZZER_TX ;//tx
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//GPIO端口的最高输出速率50MHz
GPIO_Init(BUZZER_GPIOx,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//复用推挽输出
GPIO_InitStructure.GPIO_Pin=BUZZER_RX ;//rx
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//GPIO端口的最高输出速率50MHz
GPIO_Init(BUZZER_GPIOx,&GPIO_InitStructure);
USART_InitTypeDef USART_InitStruture;
USART_InitStruture.USART_BaudRate=9600;//9600波特率
USART_InitStruture.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//不使用流控
USART_InitStruture.USART_Mode=USART_Mode_Tx |USART_Mode_Rx;//只有发送模式
USART_InitStruture.USART_Parity=USART_Parity_No;//不需要校验位
USART_InitStruture.USART_StopBits=USART_StopBits_1;//一位停止位
USART_InitStruture.USART_WordLength=USART_WordLength_8b;//字长8位
USART_Init(USART1,&USART_InitStruture);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1,ENABLE);
串口发送
}
void Serial_SendByte(uint8_t Byte)//电脑发到串口,打印单个
{ //Serial_SendByte('B');
USART_SendData(USART1,Byte);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//EXEIE为1,产生中断,该位清零
}
void Seerial_SendArray(uint8_t *Array,uint16_t Length)//数组打印
{ //Seerial_SendArray(MyArray,4);
uint16_t i; //uint8_t MyArray[]={0x11,0x12,0x13,0x14};
for(i=0;i<Length;i++)
{
Serial_SendByte(Array[i]);
}
}
void Serial_SendString(char *String)//显示字符串
{ //Serial_SendString("Hello\r\n");
uint8_t i;
for(i=0;String[i]!=0;i++)
{
Serial_SendByte(String[i]);
}
}
int fputc(int ch,FILE *f)//可以使用printf打印,重定向
{
Serial_SendByte(ch);
return ch;
}
串口接收
void Serial_SendByte1(void)//查询
{
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET)
{
uint8_t RxData =USART_ReceiveData(USART1);
buzzer_ON();
}
}
//.h文件
#include "stm32f10x.h" // Device header
#ifndef __SERIAL_H
#define __SERIAL_H
#include <stdio.h>
void Serial_Init(void);
void Serial_SendByte(uint8_t Byte); //Serial_SendByte('B');
void Seerial_SendArray(uint8_t *Array,uint16_t Length); //Seerial_SendArray(MyArray,4);
void Serial_SendString(char *String); //Serial_SendString("Hello\r\n");
void Serial_SendByte1(void);//查询方法串口接收程序 Serial_SendByte1();
#endif
Delay延时函数
//Delay文件
//.c文件
#incluccde "stm32f10x.h"
/**
* @brief 微秒级延时
* @param xus 延时时长,范围:0~233015
* @retval 无
*/
void Delay_us(int xus)
{
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
/**
* @brief 毫秒级延时
* @param xms 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_ms(int xms)
{
while(xms--)
{
// for(uint16_t i = 0;i<7200;i++)
// {
// }
Delay_us(1000);
}
}
/**
* @brief 秒级延时
* @param xs 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_s(int xs)
{
while(xs--)
{
Delay_ms(1000);
}
}
//.h文件
#ifndef __DELAY_H
#define __DELAY_H
void Delay_us(int us);
void Delay_ms(int ms);
void Delay_s(int s);
#endif
主方法函数
//main方法
#include "stm32f10x.h" // Device header
#include "Delay.h"//延时
#include "Buzzer.h"//蜂鸣器
#include "Serial.h"//串口
#include "SR04.h"//超声波
#include "drv_systick.h"
#include "main.h"
#include "MQ.h"
unsigned int length;
uint16_t msHcCount = 0 ;
uint32_t Systick_ms_count = 0;
uint16_t count = 0;
uint8_t alarm_state = 0;
int main(void){
buzzer_Init();//蜂鸣器的初始化
Serial_Init();//串口发送初始化
Time4Init();//HC超声波
MQ_D0_Init();//MQ烟雾传感器
while(1){
// SR04_if();
// MQ_if();
printf("1");
Delay_ms(200);
#if(ENABLE_TIM_TEST)
测试定时器准确性
TIM_SetCounter(TIM4, 0);//计数器清零
TIM_Cmd(TIM4, ENABLE);//打开定时器
Delay_ms(20);
TIM_Cmd(TIM4, DISABLE);//关闭定时器
count = TIM_GetCounter(TIM4);
#endif
}
}
//mian.h
#ifndef __MAIN_H
#define __MAIN_H
extern void SysTick_ISR_Count ( void );
extern volatile unsigned int distance_cm;//当前距离
#define ENABLE_HCR04 1
#define ENABLE_MQ02 1
#define ENABLE_TIM_TEST 0
#define Trig_SET GPIO_SetBits(HCSR04_PORT,HCSR04_TRIG)//置高电平
#define Trig_RESET GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG)//置低电平
#define Echo GPIO_ReadInputDataBit(HCSR04_PORT,HCSR04_ECHO)
//读取指定GPIO引脚的输入电平状态
#endif
具体的话,可以看文件里面的视频接线,效果演示