文章目录[隐藏]
一、前言
本篇介绍如何使用STM32控制超声波传感器,方法可以使用STM32的 定时器计数或者输入捕获功能,本篇使用的是定时器中断。
有关定时器的知识在:
【STM32】标准库与HAL库对照学习教程七–定时器中断中有详细说明。
本篇使用串口将测试的距离打印在电脑,有关STM32串口通信的知识可以看这篇文章:
【STM32】标准库与HAL库对照学习教程八–串口通信详解
二、准备工作
- STM32开发板(我用的是普中的STM32F103ZE的Z200系列)
- STM32cubemx软件、keil5(MDK)
- HC-SR04超声波传感器或者HY-SRF05超声波传感器
三、超声波测距传感器
1、原理说明
超声波测距传感器使用回声测距法。传感器由超声波发射器、超声波接收器、传感器电路组成,传感器主要用到4个引脚,VCC、Trig、Echo、GND。
测距原理是超声波发射器向某一方向发射超声波,在发射时刻的同时计数器开始计时,超声波在空气中传播,途中碰到障碍物面阻挡就立即反射回来,超声波接收器收到反射回的超声波就立即停止计时。
超声波在空气中的传播速度为340m/s,根据计时器记录的时间t,就可以计算出发射点距障碍物面的距离s,即:s=340t/2。
2、使用说明
- VCC应接5V供电
- 使用时,STM32给Trig引脚输出10us到20us的高电平,传感器发射超声波。
- 当接收到回声时,Echo引脚输出一定时间的高电平,高电平的持续时间,就是整个过程的时间,因此,距离=高电平时间*声速/2。
- 超声波测距模块可测量距离范围是2cm-400cm, 测距精度可达高到3mm;
- 为了防止回声信号干扰,建议测量周期在60ms以上。
四、标准库使用传感器
1、实验程序
main.c
#include "LED.h"
#include "Delay.h"
#include "System.h"
#include "usart.h"
#include<stdio.h>
#include "ultrasonic.h"
/*************************************************
*函数名: main
*函数功能: 主函数
*输入: 无
*返回值: 无
**************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //抢占式优先级与响应式优先级的分组
LED_Init();
USART1_Init(9600);
Ultrasonic_Init();
while(1)
{
printf("distance = %f mm\r\n",Get_distance()); //输出距离
}
}
ultrasonic.c
#include "ultrasonic.h"
#include "System.c"
#include "Delay.h"
/*************************************************
*函数名: Ultrasonic_Init
*函数功能: 超声波初始化函数
*输入: 无
*返回值: 无
**************************************************/
void Ultrasonic_Init()
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
// NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(Trig_RCC|Echo_RCC, ENABLE); //打开对应引脚时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //打开定时器时钟
GPIO_InitStruct.GPIO_Pin = Trig_Pin; //Trig引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //输出速度
GPIO_Init(Trig_Port, &GPIO_InitStruct); //引脚初始化
GPIO_ResetBits(Trig_Port,Trig_Pin); //引脚置低
GPIO_InitStruct.GPIO_Pin = Echo_Pin; //Echo引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD; //下拉输入
GPIO_Init(Echo_Port, &GPIO_InitStruct); //引脚初始化
TIM_TimeBaseInitStruct.TIM_Prescaler = 71; //分频系数
TIM_TimeBaseInitStruct.TIM_Period = 50000; //重装载值
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //定时器时钟不分频
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct); //定时器初始化
}
/*************************************************
*函数名: Get_distance
*函数功能: 获得距离
*输入: 无
*返回值: 距离,类型浮点型,单位mm
**************************************************/
float Get_distance()
{
float TIME_distance;
Trig = 1; Delay_us(15); Trig = 0; //给Trig引脚15us的高电平
TIM_Cmd(TIM3, ENABLE); //定时器3使能
while(!Echo) //等待高电平出现
{
if(TIM_GetCounter(TIM3)>40000) //200ms内未接收到返回信号
{
TIM_Cmd(TIM3, DISABLE); //定时器3失能
TIM_SetCounter(TIM3, 0); //计时器清零
return ERROR;
}
}
TIM_SetCounter(TIM3, 0); //接收到高电平,开始计时
while(Echo); //等待低电平出现
TIM_Cmd(TIM3, DISABLE); //定时器3失能
TIME_distance = ((float)TIM_GetCounter(TIM3)/1000.0)*340/2.0; //计算距离
TIM_SetCounter(TIM3, 0); //计时器清零
return TIME_distance; //返回距离,单位mm
}
ultrasonic.h
#ifndef ULTRASONIC_H_
#define ULTRASONIC_H_
#include "stm32f10x.h"
/************重定义引脚便于移植************/
#define Trig_RCC RCC_APB2Periph_GPIOB
#define Trig_Pin GPIO_Pin_1
#define Trig_Port GPIOB
#define Echo_RCC RCC_APB2Periph_GPIOB
#define Echo_Pin GPIO_Pin_2
#define Echo_Port GPIOB
/************位带操作************/
#define Trig PBout(1)
#define Echo PBin(2)
/************函数说明************/
void Ultrasonic_Init(void);
float Get_distance(void);
#endif
2、实验效果
五、HAL库使用传感器
1、cubemx主要配置
①
②
③
④串口配置
⑤定时器配置
⑥引脚配置
⑦工程配置
⑧在工程内添加文件(记得添加文件路径)
2、实验程序
ultrasonic.c
#include "Ultrasonic.h"
#include "tim.h"
#include "Delay.h"
#include "System.h"
/*************************************************
*函数名: Ultrasonic_Get_Distance
*函数功能: 获取超声波距离函数
*输入: 无
*返回值: 无
**************************************************/
float Ultrasonic_Get_Distance()
{
float Distance;
Trig = 1; Delay_ms(15); Trig = 0; //给Trig引脚15us的高电平
HAL_TIM_Base_Start(&htim3); //打开定时器
while(!Echo) //等待回声出现
{
if(__HAL_TIM_GET_COUNTER(&htim3)>40000) //时间超时
{
HAL_TIM_Base_Stop(&htim3); //关闭定时器
__HAL_TIM_SET_COUNTER(&htim3, 0); //计数器清零
return ERROR;
}
}
__HAL_TIM_SET_COUNTER(&htim3, 0); //计数器清零
while(Echo); //等待低电平结束
HAL_TIM_Base_Stop(&htim3); //关闭定时器
Distance = ((float)__HAL_TIM_GET_COUNTER(&htim3)/1000.0)*340/2.0; //计算距离
__HAL_TIM_SET_COUNTER(&htim3, 0); //计数器清零
return Distance;
}
ultrasonic.h
#ifndef UITRASONIC_H_
#define UITRASONIC_H_
#include "stm32f1xx_hal.h"
/************位带操作************/
#define Trig PBout(1)
#define Echo PBin(2)
/************函数定义************/
float Ultrasonic_Get_Distance(void);
#endif
main.c
#include<stdio.h>
#include "Ultrasonic.h"
/**
* 函数功能: 重定向c库函数printf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
printf("distance = %f mm \r\n",Ultrasonic_Get_Distance());
HAL_Delay(500);
3、实验效果
到这里就结束啦!
版权声明:本文为CSDN博主「修成真」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_51447215/article/details/121754119
一、前言
本篇介绍如何使用STM32控制红外传感器,方法有软件控制与IO口中断控制,本篇使用IO口中断的形式检测红外传感器的信号并控制LED灯闪烁。
关于LED的使用与外部中断的使用与配置在:
【STM32】标准库与HAL库对照学习教程三–使用库函数配置GPIO点亮LED灯
【STM32】标准库与HAL库对照学习教程五–外部中断详讲与配置
以有详细说明,因此在本篇文章中,只讲程序,不会讲具体工程的配置。
二、准备工作
- STM32开发板(我用的是普中的STM32F103ZE的Z200系列)
- STM32cubemx软件、keil5(MDK)
- 红外避障传感器
三、红外避障传感器
1、传感器原理说明
红外避障传感器的型号有很多种,但原理上大多都相同,具体由一对红外光线发射管与红外光线接收管、传感器电路组成,引脚上有VCC、GND、OUT三个引脚。
工作原理是红外光线发射管发射红外光线,红外光线接收管接收红外光线,当没有接收到返回的红外光线时,OUT引脚输出高电平,当接收到返回的红外光线时,OUT引脚输出低电平。
上图为我们经常使用的传感器图
2、传感器特性
- 工作电压:3.3V-5V
- 工作电流:≥20mA
- 工作温度:-10℃到+50℃
- 检测距离:2-10cm
- 输出信号:接收到光线输出低电平,没有接收到光线输出高电平
四、标准库使用红外传感器
1、实验程序
infrared.h
#ifndef INFRARED_H_
#define INFRARED_H_
#include "stm32f10x.h"
/************引脚重定义************/
#define Infrared_PIN GPIO_Pin_6
#define Infrared_RCC RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO
#define Infrared_Port GPIOC
extern u8 Infrared_LED0;
void Infrared_Init(void); //红外传感器初始化函数
#endif
infrared.c
#include "infrared.h"
/*************************************************
*函数名: Infrared_Init
*函数功能: 红外传感器初始化函数
*输入: 无
*返回值: 无
**************************************************/
void Infrared_Init()
{
GPIO_InitTypeDef GPIO_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
RCC_APB2PeriphClockCmd(Infrared_RCC, ENABLE); //打开引脚时钟与映射时钟
GPIO_InitStruct.GPIO_Pin = Infrared_PIN; //接收信号引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD; //下拉输入
GPIO_Init(Infrared_Port, &GPIO_InitStruct); //引脚初始化
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource6); //打开infrared引脚的相应通道
NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn; //中断通道
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; //抢占式优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2; //响应式优先级
NVIC_Init(&NVIC_InitStruct); //中断通道初始化
EXTI_InitStruct.EXTI_Line = EXTI_Line6; //中断通道
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
EXTI_InitStruct.EXTI_LineCmd = ENABLE; //中断使能
EXTI_Init(&EXTI_InitStruct); //中断初始化
}
u8 Infrared_LED0 = 0; //LED闪烁信号标志
/*************************************************
*函数名: EXTI9_5_IRQHandler
*函数功能: 外部中断函数
*输入: 无
*返回值: 无
**************************************************/
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line6))
{
Infrared_LED0 = 1;
EXTI_ClearITPendingBit(EXTI_Line6);
}
}
main.c
#include "LED.h"
#include "Delay.h"
#include "System.h"
#include "infrared.h"
/*************************************************
*函数名: main
*函数功能: 主函数
*输入: 无
*返回值: 无
**************************************************/
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SysTick_Init(72);
LED_Init();
Infrared_Init();
while(1)
{
if(Infrared_LED0 == 1) //感知到红外信号
{
LED_0 = 1; //LED0灭
while(PCin(6) == 0);
Infrared_LED0 = 0;
}
else
LED_0 = 0; //LED0亮
}
}
2、实验效果
五、HAL库使用红外传感器
1、cubemx的主要配置
①
②
③中断引脚
④中断通道
⑤LED引脚(请参考自己开发板的原理图)
⑥
⑥
2、实验程序
函数变量:
static uint8_t LED0_Infrared = 0; //检测红外信号的标志
主函数
if(LED0_Infrared == 1) //检测到红外信号
{
LED0_Infrared = 0;
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); //灯亮
while(!HAL_GPIO_ReadPin(Infrarred_GPIO_Port, Infrarred_Pin)); //等待手离开
}
else
{
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET); //灯灭
}
回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_6) //检测到红外信号
LED0_Infrared = 1;
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_6); //清除中断标志
}
3、实验效果
到这里就结束啦!
版权声明:本文为CSDN博主「修成真」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_51447215/article/details/121744515
一、前言
本篇介绍如何使用STM32控制红外传感器,方法有软件控制与IO口中断控制,本篇使用IO口中断的形式检测红外传感器的信号并控制LED灯闪烁。
关于LED的使用与外部中断的使用与配置在:
【STM32】标准库与HAL库对照学习教程三–使用库函数配置GPIO点亮LED灯
【STM32】标准库与HAL库对照学习教程五–外部中断详讲与配置
以有详细说明,因此在本篇文章中,只讲程序,不会讲具体工程的配置。
二、准备工作
- STM32开发板(我用的是普中的STM32F103ZE的Z200系列)
- STM32cubemx软件、keil5(MDK)
- 红外避障传感器
三、红外避障传感器
1、传感器原理说明
红外避障传感器的型号有很多种,但原理上大多都相同,具体由一对红外光线发射管与红外光线接收管、传感器电路组成,引脚上有VCC、GND、OUT三个引脚。
工作原理是红外光线发射管发射红外光线,红外光线接收管接收红外光线,当没有接收到返回的红外光线时,OUT引脚输出高电平,当接收到返回的红外光线时,OUT引脚输出低电平。
上图为我们经常使用的传感器图
2、传感器特性
- 工作电压:3.3V-5V
- 工作电流:≥20mA
- 工作温度:-10℃到+50℃
- 检测距离:2-10cm
- 输出信号:接收到光线输出低电平,没有接收到光线输出高电平
四、标准库使用红外传感器
1、实验程序
infrared.h
#ifndef INFRARED_H_
#define INFRARED_H_
#include "stm32f10x.h"
/************引脚重定义************/
#define Infrared_PIN GPIO_Pin_6
#define Infrared_RCC RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO
#define Infrared_Port GPIOC
extern u8 Infrared_LED0;
void Infrared_Init(void); //红外传感器初始化函数
#endif
infrared.c
#include "infrared.h"
/*************************************************
*函数名: Infrared_Init
*函数功能: 红外传感器初始化函数
*输入: 无
*返回值: 无
**************************************************/
void Infrared_Init()
{
GPIO_InitTypeDef GPIO_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
RCC_APB2PeriphClockCmd(Infrared_RCC, ENABLE); //打开引脚时钟与映射时钟
GPIO_InitStruct.GPIO_Pin = Infrared_PIN; //接收信号引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD; //下拉输入
GPIO_Init(Infrared_Port, &GPIO_InitStruct); //引脚初始化
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource6); //打开infrared引脚的相应通道
NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn; //中断通道
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; //抢占式优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2; //响应式优先级
NVIC_Init(&NVIC_InitStruct); //中断通道初始化
EXTI_InitStruct.EXTI_Line = EXTI_Line6; //中断通道
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
EXTI_InitStruct.EXTI_LineCmd = ENABLE; //中断使能
EXTI_Init(&EXTI_InitStruct); //中断初始化
}
u8 Infrared_LED0 = 0; //LED闪烁信号标志
/*************************************************
*函数名: EXTI9_5_IRQHandler
*函数功能: 外部中断函数
*输入: 无
*返回值: 无
**************************************************/
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line6))
{
Infrared_LED0 = 1;
EXTI_ClearITPendingBit(EXTI_Line6);
}
}
main.c
#include "LED.h"
#include "Delay.h"
#include "System.h"
#include "infrared.h"
/*************************************************
*函数名: main
*函数功能: 主函数
*输入: 无
*返回值: 无
**************************************************/
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SysTick_Init(72);
LED_Init();
Infrared_Init();
while(1)
{
if(Infrared_LED0 == 1) //感知到红外信号
{
LED_0 = 1; //LED0灭
while(PCin(6) == 0);
Infrared_LED0 = 0;
}
else
LED_0 = 0; //LED0亮
}
}
2、实验效果
五、HAL库使用红外传感器
1、cubemx的主要配置
①
②
③中断引脚
④中断通道
⑤LED引脚(请参考自己开发板的原理图)
⑥
⑥
2、实验程序
函数变量:
static uint8_t LED0_Infrared = 0; //检测红外信号的标志
主函数
if(LED0_Infrared == 1) //检测到红外信号
{
LED0_Infrared = 0;
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); //灯亮
while(!HAL_GPIO_ReadPin(Infrarred_GPIO_Port, Infrarred_Pin)); //等待手离开
}
else
{
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET); //灯灭
}
回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_6) //检测到红外信号
LED0_Infrared = 1;
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_6); //清除中断标志
}
3、实验效果
到这里就结束啦!
版权声明:本文为CSDN博主「修成真」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_51447215/article/details/121744515
暂无评论