本文介绍了 RA6E2 地奇星开发板驱动 DHT11 传感器实现串口打印环境温湿度数据的项目设计。
RA6E2 地奇星是一款基于100MHz Arm® Cortex®-M33 内核架构的核心板,主控芯片为 R7FA6E2BB3CNE;
项目包括
包括 JLINK 调试器、DHT11 模块、串口模块。
| RA6E2 | J-Link | Note |
|---|---|---|
| SWCLK | SCL | Serial Clock |
| SWDIO | SDA | Serial Data |
| GND | GND | Ground |
| 3V3 | 3V3 | Power |

| RA6E2 | DHT11 | Note |
|---|---|---|
| P407 | Data | Data line |
| 3V3 | VCC | Power |
| GND | GND | Ground |
| RA6E2 | J-Link | Note |
|---|---|---|
| TXD (P109) | RX | Transmit |
| RXD (P110) | TX | Receive |
| GND | GND | Ground |
详见顶部视频。
介绍了板载 USB 串口打印字符串的项目设计,以测试 UART 输出功能。
文件 - 新建 - 瑞萨 C/C++ 项目 - Renesas RA ;R7FA6E2BB3CFM ,工具链选择 GNU ARM Embedded ,调试器选择 J-Link ;New Stack - Connectivity - UART (r_sci_uart) ;user_uart_callback 设置;0x2000 ;Generate Project Content 按钮,生成工程代码。详见:【瑞萨RA6E2】ADC 电压温度计 .
在左侧的项目目录中,打开 src/hal_entry.c 文件,添加如下关键代码
#include "hal_data.h"
#include <stdio.h>
fsp_err_t err = FSP_SUCCESS;
volatile bool uart_send_complete_flag = false;
void user_uart_callback (uart_callback_args_t * p_args)
{
if(p_args->event == UART_EVENT_TX_COMPLETE)
{
uart_send_complete_flag = true;
}
}
/*------------- 串口重定向 -------------*/
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#endif
PUTCHAR_PROTOTYPE
{
err = R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&ch, 1);
if(FSP_SUCCESS != err) __BKPT();
while(uart_send_complete_flag == false){}
uart_send_complete_flag = false;
return ch;
}
int _write(int fd,char *pBuffer,int size)
{
for(int i=0;i<size;i++)
{
__io_putchar(*pBuffer++);
}
return size;
}
void hal_entry(void)
{
/* TODO: add your own code here */
err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
assert(FSP_SUCCESS == err);
while(1){
printf("hello world!\\n");
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_02, BSP_IO_LEVEL_HIGH);
R_BSP_SoftwareDelay (50, BSP_DELAY_UNITS_MILLISECONDS);
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_02, BSP_IO_LEVEL_LOW);
R_BSP_SoftwareDelay (450, BSP_DELAY_UNITS_MILLISECONDS);
}
}
保存文件,右键项目 - 构建程序;
右键项目 - 调试项目 - 上传固件至开发板。
若报错,可右键项目进入属性界面,选择 C/C++ 构建 - 设置 - GNU Arm Cross C Linker - Miscellaneous,勾选 printf 、scanf 以及syscalls 选项。

在串口通信的基础上,使用单总线协议,驱动 DHT11 温湿度传感器,获取环境温湿度数据,并串口打印。
新建 .../src/dht11.h 头文件,并添加如下代码
#ifndef DHT11_H_
#define DHT11_H_
#include "hal_data.h"
#include <stdio.h>
#ifndef delay_ms
#define delay_ms(x) R_BSP_SoftwareDelay(x, BSP_DELAY_UNITS_MILLISECONDS)
#endif
#ifndef delay_1ms
#define delay_1ms(x) R_BSP_SoftwareDelay(x, BSP_DELAY_UNITS_MILLISECONDS)
#endif
#ifndef delay_us
#define delay_us(x) R_BSP_SoftwareDelay(x, BSP_DELAY_UNITS_MICROSECONDS)
#endif
#ifndef delay_1us
#define delay_1us(x) R_BSP_SoftwareDelay(x, BSP_DELAY_UNITS_MICROSECONDS)
#endif
#ifndef u8
#define u8 uint8_t
#endif
#ifndef u16
#define u16 uint16_t
#endif
#ifndef u32
#define u32 uint32_t
#endif
#define DHT11_DAT_GPIO_PIN BSP_IO_PORT_04_PIN_07 // DHT11数据引脚
// 设置DHT11输出高或低电平
#define DATA_GPIO_OUT(x) R_IOPORT_PinWrite(&g_ioport_ctrl, DHT11_DAT_GPIO_PIN, x)
// 获取DHT11数据引脚高低电平状态
static inline bsp_io_level_t DATA_GPIO_IN(void)
{
bsp_io_level_t p_pin_value;
fsp_err_t err = R_IOPORT_PinRead(&g_ioport_ctrl, DHT11_DAT_GPIO_PIN, &p_pin_value);
if(err != FSP_SUCCESS)
{
printf("DATA_GPIO_IN Failed!!\\r\\n");
}
return p_pin_value;
}
void DHT11_Init(void);
uint8_t DHT11_Read_Data(float *temperature, float *humidity);
#endif /* DHT11_H_ */
新建 .../src/dht11.c 源文件,并添加如下代码
#include "dht11.h"
#define DHT11_DEBUG 0 // 调试信息 1:开启 0:关闭
#define DHT11_TIMEOUT 1000 // 超时阈值
/******************************************************************
* 函 数 名 称:DHT11_Init
* 函 数 说 明:配置DHT11的初始化
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void DHT11_Init(void)
{
//调用 R_IOPORT_Open 函数来初始化 IOPORT 模块
R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg);
/* 设置DHT11数据引脚输出高电平 */
DATA_GPIO_OUT(1);
delay_1ms(100); // 等待DHT11稳定
}
/******************************************************************
* 函 数 名 称:DHT11_GPIO_Mode_OUT
* 函 数 说 明:配置DHT11的数据引脚为输出模式
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
static void DHT11_GPIO_Mode_OUT(void)
{
// 在运行过程中配置DHT11数据引脚为输出模式
// 这里使用R_IOPORT_PinCfg函数配置引脚
fsp_err_t err = R_IOPORT_PinCfg(&g_ioport_ctrl, DHT11_DAT_GPIO_PIN,
((uint32_t) IOPORT_CFG_DRIVE_HIGH
| (uint32_t) IOPORT_CFG_PORT_DIRECTION_OUTPUT
| (uint32_t) IOPORT_CFG_PORT_OUTPUT_HIGH));
if(err != FSP_SUCCESS)
{
printf("DHT11_GPIO_Mode_OUT Failed!!\\r\\n");
}
}
/******************************************************************
* 函 数 名 称:DHT11_GPIO_Mode_IN
* 函 数 说 明:配置DHT11的数据引脚为输入模式
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
static void DHT11_GPIO_Mode_IN(void)
{
// 在运行过程中配置DHT11数据引脚为输入模式
// 这里使用R_IOPORT_PinCfg函数配置引脚
fsp_err_t err = R_IOPORT_PinCfg(&g_ioport_ctrl, DHT11_DAT_GPIO_PIN,
(uint32_t) IOPORT_CFG_PORT_DIRECTION_INPUT);
if(err != FSP_SUCCESS)
{
printf("DHT11_GPIO_Mode_IN Failed!!\\r\\n");
}
}
/******************************************************************
* 函 数 名 称:DHT11_Start
* 函 数 说 明:开始DHT11测量
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void DHT11_Start(void)
{
DHT11_GPIO_Mode_OUT(); // 输出模式
DATA_GPIO_OUT(1);
DATA_GPIO_OUT(0);
delay_ms(25); // 保持18+ms低电平
DATA_GPIO_OUT(1);
delay_us(25); // 主机释放总线
DHT11_GPIO_Mode_IN(); // 切换输入模式
}
/******************************************************************
* 函 数 名 称:DHT11_CheckResponse
* 函 数 说 明:检查DHT11从机的相应是否正确
* 函 数 形 参:无
* 函 数 返 回:1:正确 0:错误
* 作 者:LC
* 备 注:无
******************************************************************/
uint8_t DHT11_CheckResponse(void)
{
uint32_t timeout = 0;
// 等待从机响应发送电平响应(低电平)(80µs)
timeout = DHT11_TIMEOUT;
while(DATA_GPIO_IN() && timeout--)
{
if(timeout == 0)
{
printf("DHT11_CheckResponse Failed[1]!!\\r\\n");
return 0; // 失败
}
}
// 等待从机响应发送电平响应(高电平)(80µs)
timeout = DHT11_TIMEOUT;
while((!DATA_GPIO_IN()) && timeout--)
{
if(timeout == 0)
{
printf("DHT11_CheckResponse Failed[2]!!\\r\\n");
return 0; // 失败
}
}
// 进入前导低电平
timeout = DHT11_TIMEOUT;
while(DATA_GPIO_IN() && timeout--)
{
if(timeout == 0)
{
printf("DHT11_CheckResponse Failed[3]!!\\r\\n");
return 0; // 失败
}
}
return 1;
}
/******************************************************************
* 函 数 名 称:DHT11_ReadBit
* 函 数 说 明:读取一位数据位
* 函 数 形 参:无
* 函 数 返 回:0 或 1
* 作 者:LC
* 备 注:无
******************************************************************/
uint8_t DHT11_ReadBit(void)
{
uint8_t bit = 0;
uint8_t timeCount = 0;
uint32_t timeout;
// 等待前导低电平过去
// 等待信号线由低变高
timeout = DHT11_TIMEOUT;
while((!DATA_GPIO_IN()) && timeout--)
{
if(timeout == 0)
{
printf("DHT11_ReadBit Failed[1]!!\\r\\n");
return 0;
}
}
// 判断是0还是1?
timeout = DHT11_TIMEOUT;
while(DATA_GPIO_IN() && timeout--)
{
timeCount++;
delay_us(1); // 等待1us
if(timeout == 0)
{
printf("DHT11_ReadBit Failed[2]!!\\r\\n");
return 0; // 失败
}
}
// 只要大于30us的高电平即可判断为数据1
if(timeCount >= 30)
bit = 1; // 数据1
else
bit = 0; // 数据0
return bit;
}
/******************************************************************
* 函 数 名 称:DHT11_Read_Data
* 函 数 说 明:根据时序读取温湿度数据
* 函 数 形 参:
* 函 数 返 回:0=数据校验失败 其他=错误
* 作 者:LC
* 备 注:无
******************************************************************/
uint8_t DHT11_Read_Data(float *temperature, float *humidity)
{
int i;
uint8_t data[5] = {0};
uint64_t val = 0;
// 开始起始信号
DHT11_Start();
// 检查响应是否合规
if(0 == DHT11_CheckResponse())
{
printf("DHT11_CheckResponse Failed!!\\r\\n");
return 0;
}
// 数据读取核心(40-bit)
for(i = 0; i < 40; i++)
{
val <<= 1;
val |= DHT11_ReadBit();
}
// 校验与数据提取
data[0] = (val >> 32) & 0xFF; // 湿度整数
data[1] = (val >> 24) & 0xFF; // 湿度小数
data[2] = (val >> 16) & 0xFF; // 温度整数
data[3] = (val >> 8) & 0xFF; // 温度小数
data[4] = val & 0xFF; // 校验和
#if DHT11_DEBUG
printf("data[0] = %d\\r\\n",data[0]);
printf("data[1] = %d\\r\\n",data[1]);
printf("data[2] = %d\\r\\n",data[2]);
printf("data[3] = %d\\r\\n",data[3]);
printf("data[4] = %d\\r\\n",data[4]);
#endif
// 校验计算:前4字节和 = 第5字节
if ((data[4] != (data[0] + data[1] + data[2] + data[3])) ||
(data[4] == 0)) {
printf("CheckSum Failed!!!\\r\\n");
return 0; // 校验失败
}
// 保存温湿度
*humidity = data[0] + (data[1] * 0.1f); // 湿度(%)
*temperature = data[2] + (data[3] * 0.1f); // 温度(℃)
#if DHT11_DEBUG
printf("T: %d\\r\\n",(int)*temperature);
printf("H: %d\\r\\n",(int)*humidity);
#endif
return 1;
}
修改 .../src/hal_entry.c 主程序,代码如下
void hal_entry(void)
{
/* TODO: add your own code here */
err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
assert(FSP_SUCCESS == err);
/* initialize DHT11 */
DHT11_Init();
/* 空读两次 */
DHT11_Read_Data(NULL, NULL);
delay_1ms(1000); // 等待DHT11稳定
DHT11_Read_Data(NULL, NULL);
delay_1ms(1000); // 等待DHT11稳定
printf("\\r\\n= = = = = = = = DHT11 Demo Start = = = = = = = = =\\r\\n");
while(1){
float temperature = 0.0;
float humidity = 0.0;
if(DHT11_Read_Data(&temperature, &humidity))
{
printf("Temperature = %.2f, Humidity = %.2f\\r\\n", temperature, humidity);
}
else
{
printf("\\r\\nRead Error!!\\r\\n");
}
//printf("hello world!\\n");
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_02, BSP_IO_LEVEL_HIGH);
R_BSP_SoftwareDelay (50, BSP_DELAY_UNITS_MILLISECONDS);
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_02, BSP_IO_LEVEL_LOW);
R_BSP_SoftwareDelay (950, BSP_DELAY_UNITS_MILLISECONDS);
}
}
保存代码,编译工程并调试。

详见底部视频。
本文介绍了瑞萨 RA6E2 地奇星开发板驱动 DHT11 传感器实现串口打印环境温湿度数据的项目设计,包括串口调试和配置、DHT11 驱动和串口输出等,为相关产品的快速开发和应用设计提供了参考。
更多回帖