目录
概述
1 软硬件
1.1 软硬件环境信息
1.2 开发板信息
1.3 调试器信息
2 硬件架构
2.1 硬件框架结构
2.2 测距模块(HC-SR04)介绍
2.2.1 HC-SR04特性
2.2.2 HC-SR04操作时序
2.2.3 计算距离
3 软件实现
3.1 FSP配置项目
3.1.1 配置IO口的外部中断
3.1.2 配置定时器
3.2 代码架构
3.3 驱动实现
4 测试
4.1 编译代码
4.2 验证
源代码下载地址:
https://www.firebbs.cn/forum.php?mod=viewthread&tid=37943
概述
本文主要介绍Renesas R7FA8D1BH (Cortex®-M85) 上超声波测距模块(HC-SR04)驱动开发的过程,笔者介绍了HC-SR04测距模块驱动的实现原理,并使用FSP配置外围驱动接口,并编写驱动代码,实现测距的功能。在Renesas R7FA8D1BH板卡上通过改变距离参数验证驱动程序的功能。
1 软硬件
1.1 软硬件环境信息
软硬件信息 | 版本信息 |
---|---|
Renesas MCU | R7FA8D1BH |
Keil | MDK ARM 5.38 |
FSP 版本 | 5.3.0 |
调试工具:N32G45XVL-STB | DAP-LINK |
1.2 开发板信息
笔者选择使用野火耀阳开发板_瑞萨RA8,该板块的主控MCU为R7FA8D1BHECBD,7FA8D1BHECBD的内核为ARM Contex-M85。
1.3 调试器信息
对于R7FA8D1BHECBD芯片,其使用的内核为Cortex®-M85 Core, ST-LINK-V2或者J-LINK-V9不支持下载和调试功能。笔者经过多次尝试,发现N32G45XVL-STB板卡上自带的DAP-LINK可以下载和调试R7FA8D1BHECBD。
下图为N32G45XVL-STB开发板实物图:
2 硬件架构
2.1 硬件框架结构
IO接口配置功能:
触发信号接口P7_10: 送触发信号(10us)的脉冲
测距数据响应接口P7_09: 该IO配置外部中断响应模式,用于接收HC-SR04发回的脉冲信号
TIMER-0: 配置为10us响应速度,用于计算数据的脉冲宽度
系统工作框架结构如下:
2.2 测距模块(HC-SR04)介绍
2.2.1 HC-SR04特性
2.2.2 HC-SR04操作时序
工作原理:
Step -1: TRIG IO 收到10us 高电平
step - 2: SR04自动发送8个40hz方波,并检测是否有信号返回
step - 3:SR04检测到返回信号,ECHO IO发送高电平,高电平持续时间为SR04发送波信号到返回波信号的时间。
具体工作波形图如下:
2.2.3 计算距离
以厘米为单位计算公式:
距离 = us/58(单位: cm), us为ECHO IO接收的高电平的持续时间,时间单位为: 微妙
以英寸为单位计算公式:
距离 = us/148(单位: 英寸), us为ECHO IO接收的高电平的持续时间,时间单位为: 微妙
3 软件实现
3.1 FSP配置项目
3.1.1 配置IO口的外部中断
1) 创建外部中断stack
2)配置参数
需要配置的参数如下:
1)选择通道号
2)回调函数
3)IO接口
3.1.2 配置定时器
1)创建定时器的stack
2)配置参数
需要配置的参数如下:
1)通道号
2)周期
3) 最小周期单元
4)中断回调函数
3.2 代码架构
完成以上参数配置后,就可以使用FSP生成工程代码,其代码架构如下:
3.3 驱动实现
1)初始化函数
函数static void timer5_Init(void):实现定时器的驱动初始化功能
代码32行:打开定时器
代码36行:启动定时器
代码39行:启动计数功能
函数:void HC_SR04_Init ( void ):实现HC_SR04模块初始化功能,该函数可以被外部其他函数调用
代码48行: 代码IO外部中断aima
代码52行:打开外部中断
代码55行:调用定时器初始化函数,启动定时器,以实现计算脉冲宽度功能
2)触发函数和定时器回调函数
3)外部中断回调函数
代码90行:启动定时器,开始计数
代码94行:停止定时器
代码95行:计算距离数据
源代码文件如下:
/*
FILE NAME : sht2x.c
Description: user sht20 interface
Author : tangmingfei2013@126.com
Date : 2024/06/03
*/
#include "hal_data.h"
#include "hc_sr04.h"
#define timeDelayUS(us) R_BSP_SoftwareDelay(us, BSP_DELAY_UNITS_MICROSECONDS);
#define ICU_IRQN_PIN BSP_IO_PORT_07_PIN_09
#define ICU_IRQN 10
#define TRIG BSP_IO_PORT_07_PIN_10
#define TRIG_H R_IOPORT_PinWrite(&g_ioport_ctrl, TRIG, BSP_IO_LEVEL_HIGH)
#define TRIG_L R_IOPORT_PinWrite(&g_ioport_ctrl, TRIG, BSP_IO_LEVEL_LOW)
static bool bl_trigger = false;
static uint32_t tick_cnt_1us;
static int state =0;
static float distance;
static void timer5_Init(void)
{
fsp_err_t err = FSP_SUCCESS;
/* Initializes the module. */
err = R_AGT_Open(&g_timer5_ctrl, &g_timer5_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
/* Start the timer. */
err = R_AGT_Start(&g_timer5_ctrl);
assert(FSP_SUCCESS == err);
err = R_AGT_Enable(&g_timer5_ctrl);
assert(FSP_SUCCESS == err);
}
void HC_SR04_Init ( void )
{
/* Configure the external interrupt. */
fsp_err_t err = R_ICU_ExternalIrqOpen(&g_external_irq10_ctrl, &g_external_irq10_cfg);
assert(FSP_SUCCESS == err);
/* Enable the external interrupt. */
/* Enable not required when used with ELC or DMAC. */
err = R_ICU_ExternalIrqEnable(&g_external_irq10_ctrl);
assert(FSP_SUCCESS == err);
timer5_Init();
}
void HC_SR04_Trigger( void )
{
bl_trigger = true;
TRIG_H;
timeDelayUS(10);
TRIG_L;
state = 0;
}
void g_timer5_Callback (timer_callback_args_t * p_args)
{
if (TIMER_EVENT_CYCLE_END == p_args->event)
{
tick_cnt_1us++;
}
}
/* Called from icu_irq_isr */
void external_irq10_callback (external_irq_callback_args_t * p_args)
{
fsp_err_t err = FSP_SUCCESS;
(void) p_args;
switch( state )
{
default:
case 0:
tick_cnt_1us = 0;
state = 1;
err = R_AGT_Enable(&g_timer5_ctrl);
assert(FSP_SUCCESS == err);
break;
case 1:
err = R_AGT_Disable(&g_timer5_ctrl);
distance = (float)(tick_cnt_1us/5.8);
state = 0;
tick_cnt_1us = 0;
assert(FSP_SUCCESS == err);
break;
}
}
void debug_SR04_LOG( void )
{
user_get_rtc();
}
float HC_SR04_getDistance( void )
{
return distance;
}
/* End of this file */
4 测试
4.1 编译代码
系统硬件平台如下:
编译代码下载到板卡中运行:
4.2 验证
改变距离后,在OLED得到当前的距离数据: