之前发帖:
【瑞萨RA4系列开发板体验】2. KEIL环境搭建+STLINK调试+FreeRTOS使用
【瑞萨RA4系列开发板体验】3. KEIL下UART实现printf与scanf重定向
【瑞萨RA4系列开发板体验】5. 硬件IIC驱动OLED显示汉字
【瑞萨RA4系列开发板体验】7. 用DAC输出正弦波以及余弦波
本来之前申请试用的时候,打算做一个室内可燃气体检测设备的,但是我的可燃气体传感器居然坏掉了,采集不到ADC数值了,遂只能修改项目,完整了这个测距仪小作品,算是对本次试用的一个作品总结。
手头有一个超声波测距模块,遂使用超声波模块来编写一个举例测试器,本文使用超声波模块US-100是实现了超声波测距的功能。本文实现了一下功能:
通过搜索US-100超声波测距模块的资料,了解到该模块可以通过两种方式进行驱动。
方式一:使用普通GPIO进行驱动Trig触发,然后通过接收echo的反馈波形长度就可以知道超声波测量物体的距离了,该方式需要结合定时器使用,并且自行计算返回距离,使用起来较复杂;
方式二:使用串口,给US-100的TX发送0x55,等待反馈数据,反馈数据为两个单字节数据,第一个字节为距离高位,第二个数据为距离低位,反馈距离为Data0<<8 | Data1, 单位是mm,详细资料见下图。
使用串口模式还可以获取超声波模块的温度,这个温度是用来补偿超声波数据,用来进行校准的,我们也可以通过发送0x50获取内部温度数据,温度数据为单字节,获取的数值-45就是真实的温度。
为了设计的便捷性,本文使用了串口的模式,使用串口模式需要将US-100后边的跳线帽连接上。
确定使用UART连接之后,查看一下数据手册,看看还有没有串口可以供我们使用。我们可以使用SCI0的TXD0以及RXD0.
打开RASC,过程不在赘述。
在Pins页面配置SCI0,如下图:
在Stacks页面下配置串口,方式同我之前发布的帖子。
【瑞萨RA4系列开发板体验】3. KEIL下UART实现printf与scanf重定向
不再赘述,详见配置页面。
配置完成之后点击生成配置代码,然后开始代码设计。
过程比较简单,与我之前的文章类似,我新建了app_us100.c自己app_us100.h,逻辑详见代码。
在该文件中实现了如下功能函数:
/*
@hehung
2022-12-10
*/
#include "hal_data.h"
#include "app_dac.h"
#include <stdio.h>
static volatile uint8_t uart0_send_mode = 0;
static volatile bool uart0_send_complete_flag = false;
static volatile bool uart0_recv_complete_flag = false;
static volatile uint32_t uart0_recv_char = '\0';
static volatile uint8_t uart0_recv_cnt = 0U;
// callback function for uart0
void uart0_notification(uart_callback_args_t * p_args)
{
if (p_args->event == UART_EVENT_TX_COMPLETE)
{
uart0_send_complete_flag = true;
}
else if (p_args->event == UART_EVENT_RX_CHAR)
{
if (uart0_send_mode == 0U)
{
++uart0_recv_cnt;
if (uart0_recv_cnt == 2U)
{
uart0_recv_cnt = 0U;
uart0_recv_char = (uart0_recv_char << 8U) | p_args->data;
uart0_recv_complete_flag = true;
}
else
{
uart0_recv_char = p_args->data;
}
}
else
{
uart0_recv_char = p_args->data;
uart0_recv_complete_flag = true;
}
}
}
// Uart0 initialize
void US100_Init(void)
{
fsp_err_t err = FSP_SUCCESS;
/* Open the transfer instance with initial configuration. */
err = R_SCI_UART_Open(&g_uart0_ctrl, &g_uart0_cfg);
assert(FSP_SUCCESS == err);
}
/* Start US100 distance test */
void US100_StartDistance(void)
{
fsp_err_t err = FSP_SUCCESS;
uint8_t send_ch;
/* 0x50 is command for get the distance from US-100 */
send_ch = 0x55U;
uart0_send_mode = 0U;
err = R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)&send_ch, 1);
if(FSP_SUCCESS != err)
__BKPT();
}
/* Start US100 temperature test */
void US100_StartTemperature(void)
{
fsp_err_t err = FSP_SUCCESS;
uint8_t send_ch;
/* 0x50 is command for get the temperature from US-100 */
send_ch = 0x50U;
uart0_send_mode = 1U;
err = R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)&send_ch, 1);
if(FSP_SUCCESS != err)
__BKPT();
}
/* Read the distance from US100 */
uint8_t US100_ReadDistance(uint16_t *distance)
{
if ((true == uart0_recv_complete_flag) && (0U == uart0_send_mode))
{
// printf ("Distance reveived is %d\n", uart0_recv_char);
*distance = uart0_recv_char & 0xFFFFU;
uart0_recv_complete_flag = false;
return 1;
}
else
{
return 0;
}
}
/* Read the temperature from US100 */
uint8_t US100_ReadTemperature(uint8_t *temp)
{
if ((true == uart0_recv_complete_flag) && (1U == uart0_send_mode))
{
// printf ("Temperature reveived is %d\n", uart0_recv_char);
*temp = uart0_recv_char & 0xFFU;
uart0_recv_complete_flag = false;
return 1;
}
else
{
return 0;
}
}
/*
@hehung
2022-12-10
*/
#ifndef APP_US100_H_
#define APP_US100_H_
#include "stdint.h"
extern void US100_Init(void);
extern void US100_StartDistance(void);
extern void US100_StartTemperature(void);
extern uint8_t US100_ReadDistance(uint16_t *distance);
extern uint8_t US100_ReadTemperature(uint8_t *temp);
#endif
主函数中实现了相关模块初始化,发送测距函数开始距离测试,获取测试结果,发送温度获取命令,获取温度值,并通过OLED显示,每500ms更新一次数据。
uint16_t dist;
uint8_t temp;
void hal_entry(void)
{
char disp_str[16];
/* Initialize the uart for implement the 'printf' and 'scanf' */
Uart_Init();
/* Initialize the os and some tasks */
// Task_Create();
/* Initialize the I2c */
I2c_Init();
/* Initialize the OLED */
OLED_Init();
/* Initialize the ADC */
Adc_Init();
/* initialize the US100 - Ultrasonic module */
US100_Init();
OLED_ShowString(12, 0, (const uint8_t*)"R7FA4M2AD3CFP", 16, 1);
// OLED_ShowHzStringRow(32, 24, (const char*)"电子发烧友", 1);
OLED_ShowString(0, 16, (const uint8_t*)"elecfans", 16, 1);
OLED_ShowString(64, 16, (const uint8_t*)"|hehung", 16, 1);
OLED_Refresh_Gram();
while (1)
{
US100_StartDistance();
while (!US100_ReadDistance(&dist))
{
R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MICROSECONDS);
}
US100_StartTemperature();
while (!US100_ReadTemperature(&temp))
{
R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MICROSECONDS);
}
sprintf(disp_str, "Dis:%03dmm", (dist));
OLED_ShowString(0, 32, (const uint8_t*)disp_str, 16, 1);
sprintf(disp_str, "Temp:%03dC", ((int)temp - 45));
OLED_ShowString(0, 48, (const uint8_t*)disp_str, 16, 1);
OLED_Refresh_Gram();
R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS);
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
我测试了20cm以及10cm,发现测试存在一定的误差,距离越远,误差越大。
20cm测试结果,可以看到,测试结果为21cm左右,存在1cm的误差。
10cm测试结果,可以看到,测试结果误差较大,但是还是偏大。
从测试结果可以看到,获取的温度数值明显不对,当前室内温度也就十几度,但是温度测试出来是20多度,估计是温度的影响导致测试距离存在一定的误差,但是在测试精度要求不是很严重的场合,超声波测距还是可以的,或者自己外接温度传感器对距离进行补偿。
测试验证视频见末尾
更多回帖