注:文末有完整工程链接(包含引脚连接、代码注释和使用说明),已实测通过,下载打开即用。
前言
本次实验采用的是stm32f103c8t6开发板,是比较基础的一款arm主控芯片;使用超声波传感器HC-SR04来测量距离,当距离小于设定距离时进行报警;报警采用了两种方式,一是无源蜂鸣器,二是JQ8900语音模块,该模块配有小喇叭,可以自行设置报警音(如前方有障碍物/警报,警报/你好,请注意等等),我设置的是“警报,注意安全”。
一、超声波测距
具体的测距程序原理,网上一搜就有,简单来说就是当超声波传感器的Trig引脚拉高大于10us之后触发超声波测距模块,另一个Echo引脚变高电平,随后发出超声波,接收到返回的超声波后Echo引脚再变低电平,因此利用公式:
距离s = 1/2*Echo引脚从高变低的时间t ∗ 声速
来测得距离。大家有兴趣可以查阅资料详细学习,这里直接上程序(注:部分程序注释粘贴后乱码如代码第一段所示,所以这里删去了后面的注释。文末有完整工程,实在想看注释可以下载工程打开查看,两个工程超声波测距部分程序是一样的,下载一个即可)。
HC-SR04传感器,该图片来自淘宝Zave旗舰店产品介绍:
此模块有四个引脚:VCC接5V或者3.3V(具体接几伏要看你买的传感器介绍),GND接地,Trig和Echo引脚是IO引脚,可以接开发板上对应的GPIO引脚,这里接的是PB11和PB10。
超声波测距程序:
#include "hc.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "beep.h"
//³¬Éù²¨Ó²¼þ½Ó¿Ú¶¨Òå
#define HCSR04_PORT GPIOB
#define HCSR04_CLK RCC_APB2Periph_GPIOB
#define HCSR04_TRIG GPIO_Pin_11 //trig½ÓPB11
#define HCSR04_ECHO GPIO_Pin_10 //echo½ÓPB10
u16 msHcCount = 0;
void hcsr04_NVIC()
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void Hcsr04Init()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(HCSR04_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin =HCSR04_TRIG;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG);
GPIO_InitStructure.GPIO_Pin = HCSR04_ECHO;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_DeInit(TIM2);
TIM_TimeBaseStructure.TIM_Period = (1000-1);
TIM_TimeBaseStructure.TIM_Prescaler =(72-1);
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
hcsr04_NVIC();
TIM_Cmd(TIM4,DISABLE);
}
static void OpenTimerForHc()
{
TIM_SetCounter(TIM4,0);
msHcCount = 0;
TIM_Cmd(TIM4, ENABLE);
}
static void CloseTimerForHc()
{
TIM_Cmd(TIM4, DISABLE);
}
void TIM4_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update );
msHcCount++;
}
}
u32 GetEchoTimer(void)
{
u32 t = 0;
t = msHcCount*1000;
t += TIM_GetCounter(TIM4);
TIM4->CNT = 0;
delay_ms(50);
return t;
}
float Hcsr04GetLength(void )
{
u32 t = 0;
int i = 0;
float lengthTemp = 0;
float sum = 0;
while(i!=5)
{
TRIG_Send = 1;
delay_us(20);
TRIG_Send = 0;
while(ECHO_Reci == 0);
OpenTimerForHc();
i = i + 1;
while(ECHO_Reci == 1);
CloseTimerForHc();
t = GetEchoTimer();
lengthTemp = ((float)t/58.0); //(1/2)*340*(t/10^6)*100 = t/58 cm
sum = lengthTemp + sum ;
}
lengthTemp = sum/5.0;
return lengthTemp;
}
串口距离显示:
二、短距报警模块
1.使用无源蜂鸣器进行报警
注:对应的文末工程链接1。
这里使用的是无源蜂鸣器,有三个引脚:VCC接5V,GND接地,IO脚接单片机IO脚(本实验接的是PA11)。
蜂鸣器报警对应代码如下:
#include "beep.h"
#include "delay.h"
int melody[] = {50, 50, 50, 50, 200, 200, 200, 400, 400, 500, 500, 500};
void BEEP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_11);
}
void Sound(u16 frq)
{
u32 time;
if(frq != 1000)
{
time = 200000/((u32)frq);
BEEP = 1;
delay_us(time);
BEEP = 0;
delay_us(time);
}else
delay_us(1000);
}
void Sound2(u16 time)
{
BEEP = 1;
delay_ms(time);
BEEP = 0;
delay_ms(time);
}
void play_successful(void)
{
int id=0;
for(id = 0 ;id < 12 ;id++)
{
Sound2(melody[id]);
}
}
void play_failed(void)
{
int id=0;
for(id = 11 ;id >=0 ;id--)
{
Sound2(melody[id]);
}
}
void play_music(void)
{
uc16 tone[] ={250,262,294,330,350,393,441,495,525,589,661,700,786,882,990}; //??
u8 music[]={5,5,6,5,8,7,5,5,6,5,9,8,5,5,12,10,8,7,6,11,
11,10,8,9,8,5,5,8,5,5,12,10,8,7,6,11,11,10,8,9,8 //????
};
u8 time[] = {1,2,2,2,2,4,1,2,2,2,2,4,1,2,2,2,1,4,
4,1,2,2,2,2,4,1,2,4,1,2,2,2,1,4, 4,1,2,2,2,2,4,4 //????
};
u32 yanshi;
u16 i,e;
yanshi = 10;
for(i=0;i<sizeof(music)/sizeof(music[0]);i++){
for(e=0;e<((u16)time[i])*tone[music[i]]/yanshi;e++){
Sound((u32)tone[music[i]]);
}
}
}
2.使用JQ8900语音模块报警
JQ8900有三种通信模式,即两线串口通信方式、一线串口通信方式和IO口按键触发模式,本实验中使用的是一线串口通信方式,因为查阅资料后发现一线串口通信方式程序编写更加简便,因此最后采用这种方式编写了短距语音报警程序,对应文末工程链接2。
JQ8900模块,此图片来自语音产品商城产品介绍:
JQ8900语音模块:VPP接PB11(这个必须接PB11,因为PB11是SDA口,因为trig也接了PB11,所以我用了一块面包板。当然,也可以改变超声波的连接引脚,trig接PB7,echo接PB6也是可以的,实测过,就是需要改程序里的引脚设置);GND接地,DC接5V,SPK+和SPK-接小喇叭正负极。
JQ8900模块程序(部分):
#include "oneuart.h"
#include "delay.h"
#include "stm32f10x.h"
void OnUart_GPIO(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC->APB2ENR|=1<<3; //GPIOB
//GPIOB.12
GPIOB->CRH&=0xFFFF0FFF;
GPIOB->CRH|=0x00003000;
GPIOB->ODR=~(1<<12);
}
void SendData ( u8 addr )
{
u8 i;
SDA = 1;
delay_us ( 1000 );
SDA = 0;
delay_us ( 3200 );
for ( i = 0; i < 8; i++ )
{
SDA = 1;
if ( addr & 0x01 )
{
delay_us ( 600 );
SDA = 0;
delay_us ( 200 );
}
else
{
delay_us ( 200 );
SDA = 0;
delay_us ( 600 );
}
addr >>= 1;
}
SDA = 1;
}
void delay_1us(u32 nTimer)
{
u32 i=0;
for(i=0;i<nTimer;i++)
{
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
}
}
对应的main.c程序部分:
//²âÊÔÖ÷º¯Êý
int main(void)
{
float length;
OnUart_GPIO();
delay_init();
NVIC_Configuration();
uart_init(9600);
Hcsr04Init();
//printf("´®¿Ú²âÊÔ\r\n");
Hcsr04Init();
//printf("³¬Éù²¨³õʼ»¯³É¹¦!\n");
while(1)
{
length = Hcsr04GetLength();
printf(":%.2fcm\n",length);
if(length<10)
{
SendData(0x0a);
SendData(0x01);
SendData(0x0b);
delay_ms(1000);
}
delay_ms(1000);
}
}
三、完整工程链接
1.stm32+超声波测距+短距蜂鸣器报警:
https://download.csdn.net/download/m0_52152690/85930149
2.stm32+超声波测距+JQ8900语音报警+小喇叭放大声音
https://download.csdn.net/download/m0_52152690/85930472