stm32简单的HC-SR04驱动代码

刚水完校际联赛对自己很不满意,继续学习32的同时,也开始接触一些模块

于是把HC-SR04的代码封装一下,感觉挺好用,虽然代码量不大,但算是一个开始吧

废话不多,直接上代码

.h文件:

#ifndef __HC_SR04_H__
#define __HC_SR04_H__

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"

#define TIM6_STOP_UP() TIM6_UP_FLAG = 0
#define TIM6_START_UP() TIM6_UP_FLAG = 1
#define TIM6_RESET() TIM6_UP_FLAG = 1;change_TIM6_time(0)

/* 初始化只用调用 HC_SR04_Init(定时器初始化 在HC_SR04_Init已调用)*/
/* 输出控制IO给超过10us的高电平,输入控制IO等待高电平,输入控制接收到高电平的时间就是声波来回走过的时间 */

/******************************************************* HC_SR04部分**************************************************************/

short HC_SR04_Init(GPIO_TypeDef  *GPIO_IN,uint32_t IN_GPIO_Pin,GPIO_TypeDef  *GPIO_OUT,uint32_t OUT_GPIO_Pin,uint16_t psc,uint16_t arr); //调用此函数初始化HC_SR04和所用定时器
double HC_SR04_get_len(void);//阻塞式获取距离
    
/********************************************************* 定时器部分 ************************************************************/

void btimer_x_Init(uint16_t psc,uint16_t arr);  //定时器初始化 在HC_SR04_Init已调用

void change_TIM6_time(double new_time);  //修改定时器时间
double get_TIM6_time(void);   //获取定时器时间 

#endif

.c文件:

#include "./BSP/HC-SR04/HC-SR04.h"

/******************************************************* HC_SR04部分**************************************************************/
typedef struct HC_SR04_IO{
    GPIO_TypeDef  *GPIO_IN;
    uint32_t IN_GPIO_Pin;
    
    GPIO_TypeDef  *GPIO_OUT;
    uint32_t OUT_GPIO_Pin;
}HC_SR04_IO;

HC_SR04_IO hc_sr04_io;  /* HC_SR04使用的IO口 */

TIM_HandleTypeDef g_btimer_x_handle;  /*定时器句柄*/
double TIM_time = 0;   /* 记录超声波走过的时间 */
short TIM6_UP_FLAG = 1;  /* 超声波时间计数标志 */

short HC_SR04_Init(GPIO_TypeDef  *GPIO_IN,uint32_t IN_GPIO_Pin,GPIO_TypeDef  *GPIO_OUT,uint32_t OUT_GPIO_Pin,uint16_t psc,uint16_t arr)
{
    GPIO_InitTypeDef gpio_init_struct;
    hc_sr04_io.GPIO_IN = GPIO_IN;
    hc_sr04_io.GPIO_OUT = GPIO_OUT;
    hc_sr04_io.IN_GPIO_Pin = IN_GPIO_Pin;
    hc_sr04_io.OUT_GPIO_Pin = OUT_GPIO_Pin;
    
    __HAL_RCC_GPIOA_CLK_ENABLE();
    
    gpio_init_struct.Pin = IN_GPIO_Pin;     //PA1是输入
    gpio_init_struct.Mode = GPIO_MODE_INPUT;
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;
    
    HAL_GPIO_Init(GPIO_IN,&gpio_init_struct);
    HAL_GPIO_WritePin(GPIO_IN,IN_GPIO_Pin,GPIO_PIN_RESET);
    
    
    gpio_init_struct.Pin = OUT_GPIO_Pin;     //PA4是输出
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;
    
    HAL_GPIO_Init(GPIO_OUT,&gpio_init_struct);
    HAL_GPIO_WritePin(GPIO_OUT,OUT_GPIO_Pin,GPIO_PIN_RESET);
    
    btimer_x_Init(psc,arr);
    
    return 1;
}

double HC_SR04_get_len()
{
    //先给10us的高电平
    HAL_GPIO_WritePin(hc_sr04_io.GPIO_OUT , hc_sr04_io.OUT_GPIO_Pin , GPIO_PIN_SET);
    delay_us(10);
    HAL_GPIO_WritePin(hc_sr04_io.GPIO_OUT , hc_sr04_io.OUT_GPIO_Pin , GPIO_PIN_RESET);
    
    /* 阻塞等待:输入端接收到高电平后开始计时,变为低电平结束计时 */
    while(HAL_GPIO_ReadPin(hc_sr04_io.GPIO_IN , hc_sr04_io.IN_GPIO_Pin) == GPIO_PIN_RESET);   
    TIM6_RESET(); //计时器从0开始计数
    while(HAL_GPIO_ReadPin(hc_sr04_io.GPIO_IN , hc_sr04_io.IN_GPIO_Pin) == GPIO_PIN_SET);
    
    TIM6_STOP_UP();  //计时器停止计数
    return get_TIM6_time()*170/100;    //TIM_time为10微秒计数,除以100000。 乘340,除以二算距离(米),乘以1000计算毫米
}
/********************************************************* 定时器部分 ************************************************************/

/* 定时器初始化函数 */
void btimer_x_Init(uint16_t psc,uint16_t arr)
{
    g_btimer_x_handle.Instance = TIM6;
    g_btimer_x_handle.Init.Prescaler = psc;
    g_btimer_x_handle.Init.Period = arr;
    
    HAL_TIM_Base_Init(&g_btimer_x_handle);
    HAL_TIM_Base_Start_IT(&g_btimer_x_handle);
}

/* 基础定时器自定义初始化函数 */
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM6){
        __HAL_RCC_TIM6_CLK_ENABLE();
        HAL_NVIC_SetPriorityGrouping(2);
        HAL_NVIC_SetPriority(TIM6_IRQn,2,2);
        HAL_NVIC_EnableIRQ(TIM6_IRQn);
    }
}

/* 中断服务函数 */
void TIM6_IRQHandler()
{
    /* 定时器公共函数 */
    HAL_TIM_IRQHandler(&g_btimer_x_handle);
}

/* 定时器溢出中断回调函数 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance ==TIM6){ //
        if(TIM6_UP_FLAG)TIM_time ++;
    }
}

/*处理超声波时间函数*/
void change_TIM6_time(double new_time)
{
    TIM_time = new_time;
}

double get_TIM6_time(void)
{
    return TIM_time;
}

main函数可以写的很简单

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/HC-SR04/HC-SR04.h"

int main(void)
{
    HAL_Init();                              /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);      /* 设置时钟, 72Mhz */
    delay_init(72);                          /* 延时初始化 */
    usart_init(9600);
    HC_SR04_Init(GPIOA,GPIO_PIN_1,GPIOA,GPIO_PIN_4,10-1,72-1);//使用PA1作为HC_SR04接收IO,PA4作为输出控制IO  ,10us触发一次中断
    
    while(1)
    { 
        printf("检测到距离为:%f\r\n",HC_SR04_get_len());
        delay_ms(50);
    }
}

就这么多,最近考试,等月底会继续分享学习过程

如有代码不妥,感谢指点!

当然,下面是一个简单的示例代码,用于在STM32驱动HC-SR04超声波测距传感器: ```c #include "stm32f4xx.h" #include "delay.h" #define TRIGGER_PIN GPIO_Pin_0 #define ECHO_PIN GPIO_Pin_1 #define GPIO_PORT GPIOA void HC_SR04_Init(void) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = TRIGGER_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIO_PORT, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = ECHO_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIO_PORT, &GPIO_InitStruct); } float HC_SR04_GetDistance(void) { uint32_t Timeout = 0; uint32_t StartTime = 0, EndTime = 0; float Distance = 0; GPIO_SetBits(GPIO_PORT, TRIGGER_PIN); Delay_us(10); GPIO_ResetBits(GPIO_PORT, TRIGGER_PIN); while (GPIO_ReadInputDataBit(GPIO_PORT, ECHO_PIN) == RESET) { if (Timeout++ > 50000) return -1; } StartTime = TIM2->CNT; Timeout = 0; while (GPIO_ReadInputDataBit(GPIO_PORT, ECHO_PIN) == SET) { if (Timeout++ > 50000) return -1; } EndTime = TIM2->CNT; Distance = (float)(EndTime - StartTime) / 58.0; return Distance; } int main(void) { HC_SR04_Init(); while (1) { float distance = HC_SR04_GetDistance(); // 处理测量结果 // ... } } ``` 这只是一个简单的示例代码,你可能需要根据你的具体硬件和需求进行适当的修改和优化。同时,你还需要配置STM32的定时器和延时函数(例如使用SysTick定时器和延时函数)。 希望这能帮到你!如果有其他问题,请随时提问。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值