当前位置: 首页 > news >正文

基于立创开发板的土壤湿度传感器模块移植与ADC/GPIO双模式读取实战

基于立创开发板的土壤湿度传感器模块移植与ADC/GPIO双模式读取实战

最近在做一个智能浇花的小项目,需要用到土壤湿度传感器。手头正好有一块立创的开发板(主控是R7FA6E2BB3CNE)和一个常见的土壤湿度模块。网上资料虽然多,但直接能用在立创板子上的完整教程却很少。今天我就把整个移植和调试的过程记录下来,从硬件连接到软件驱动,再到数据读取,手把手带你走一遍。无论你是刚接触嵌入式的新手,还是想快速在立创平台上验证传感器的朋友,这篇教程都能帮到你。

咱们的目标很明确:让开发板既能通过ADC读取精确的模拟湿度值(百分比),也能通过GPIO快速判断土壤是“干”还是“湿”。下面就开始吧。

1. 认识你的土壤湿度传感器模块

在动手写代码之前,咱们先得搞清楚手头的传感器是怎么工作的。我用的这个模块非常常见,淘宝上几块钱就能买到,长这样:

  • 核心功能:检测土壤含水量。
  • 输出模式:它有两个输出口,这是关键!
    • AO(模拟输出):输出一个连续的电压信号,土壤越湿,电压越高(或越低,取决于模块设计)。这个信号需要接到单片机的ADC引脚,经过模数转换得到一个数字值,从而计算出更精确的湿度百分比。
    • DO(数字输出):输出一个简单的高低电平。模块上有个蓝色的电位器,你可以调节一个阈值。当土壤湿度超过这个阈值时,DO引脚输出一种电平(比如低电平);低于阈值时,输出另一种电平(比如高电平)。它相当于一个简单的开关,告诉你“干了”还是“没干”。
  • 工作原理:模块附带两个叉子状的探针。把它插入土壤,土壤中的水分会让两个探针之间导电。水分越多,导电性越好,输出的模拟电压就会变化。
  • 硬件参数
    • 工作电压:3.3V - 5V(和立创开发板兼容)
    • 工作电流:约150mA
    • 接口:4个2.54mm间距的排针(VCC, GND, DO, AO)

提示:你可以做个简单测试,用一根导线或金属镊子同时接触两个探针,模拟土壤非常湿润的状态,这时模块上的DO指示灯应该会亮起。这能快速验证模块好坏。

2. 硬件连接与引脚配置

首先,把传感器和立创开发板连起来。连接很简单,就是四根线:

传感器模块引脚连接到立创开发板
VCC5V0 (5V电源输出)
GNDGND (地)
DOP407 (用作GPIO输入)
AOP000 (用作ADC输入)

这里我选择P000作为ADC输入通道0,P407作为普通GPIO输入。你当然可以根据自己的板子资源选择其他引脚,只要功能对应就行。

接下来,我们需要在开发环境里配置这些引脚。立创的开发环境通常有图形化配置工具(如RASC),操作如下:

  1. 打开项目的图形化配置界面。
  2. 配置P000为ADC功能:找到P000引脚,将其功能选择为“ADC0”或对应的ADC输入通道。
  3. 配置P407为GPIO输入:找到P407引脚,将其功能设置为“GPIO Input”。
  4. 按下Ctrl + S保存配置。
  5. 点击界面上的Generate Project Content按钮生成底层驱动代码。

完成这一步后,工具会自动生成初始化ADC和GPIO的代码框架,我们后续的代码会基于这个框架来写。

3. 驱动代码编写:创建传感器专属文件

为了代码整洁和可复用,我们新建两个文件:bsp_soilhumidity.cbsp_soilhumidity.h(“bsp”意为板级支持包)。记得把包含头文件的路径添加到你的编译器设置里。

3.1 头文件定义 (bsp_soilhumidity.h)

头文件里主要做宏定义和函数声明。

#ifndef BSP_CODE_BSP_SOILHUMIDITY_H_ #define BSP_CODE_BSP_SOILHUMIDITY_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_us #define delay_us(x) R_BSP_SoftwareDelay(x, BSP_DELAY_UNITS_MICROSECONDS) #endif // 类型简写 #ifndef u8 #define u8 uint8_t #endif #ifndef u16 #define u16 uint16_t #endif // 硬件相关宏定义(根据你的配置修改) #define BSP_ADC_CHANNEL ADC_CHANNEL_0 // 对应P000,ADC通道0 #define BSP_DO_GPIO_PIN BSP_IO_PORT_04_PIN_07 // 对应P407 // 采样次数,用于软件滤波 #define SAMPLES 5 // 函数声明 void Module_BSP_Init(void); // 初始化ADC int Get_Adc_Value(void); // 获取ADC原始值(多次平均) uint8_t Get_SH_Percentage_value(void); // 获取湿度百分比 char Get_SH_DO_value(void); // 获取DO数字状态 #endif /* BSP_CODE_BSP_SOILHUMIDITY_H_ */

3.2 源文件实现 (bsp_soilhumidity.c)

这里是具体的功能实现,咱们一步步看。

首先,是ADC初始化和回调函数。ADC扫描完成时,会触发回调函数,我们用一个标志位来通知主程序。

#include "bsp_soilhumidity.h" #include <stdio.h> // ADC扫描完成标志 volatile bool adc_flag = false; // ADC回调函数 void adc_callback(adc_callback_args_t *p_args) { FSP_PARAMETER_NOT_USED(p_args); // 避免未使用参数警告 adc_flag = true; // 设置标志位,表示一次ADC采样完成 } // 初始化ADC模块 void Module_BSP_Init(void) { fsp_err_t err = FSP_SUCCESS; // 1. 打开ADC设备 err = R_ADC_Open(&g_adc0_ctrl, &g_adc0_cfg); if (FSP_SUCCESS != err) { printf("ADC Open Failed! \n"); return; } // 2. 配置ADC扫描(图形化工具已生成配置,这里直接应用) err = R_ADC_ScanCfg(&g_adc0_ctrl, &g_adc0_channel_cfg); if (FSP_SUCCESS != err) { printf("ADC Scan Config Failed! \n"); R_ADC_Close(&g_adc0_ctrl); // 如果失败,关闭已打开的ADC return; } }

接着,是核心的ADC读取函数。这个函数负责启动一次ADC转换,并等待读取结果。

// 内部函数:执行一次ADC采样并读取结果 static int ADC_GET(void) { int gAdcResult = 0; int timeOut = 1000; // 超时计数器,防止卡死 fsp_err_t err = FSP_SUCCESS; // 1. 启动ADC扫描 err = R_ADC_ScanStart(&g_adc0_ctrl); if (FSP_SUCCESS != err) { printf("ADC扫描启动失败! \n"); return 9999; // 返回一个明显的错误值 } // 2. 等待ADC转换完成(标志位由回调函数设置) while(!adc_flag && timeOut--) { delay_us(1); // 短暂延时,避免空循环耗尽CPU } // 3. 清除标志位,为下一次采样做准备 adc_flag = false; // 4. 检查是否超时 if(!timeOut) { printf("ADC_GET Failed!!!\r\n"); return 0; } // 5. 读取ADC通道0的结果 err = R_ADC_Read(&g_adc0_ctrl, BSP_ADC_CHANNEL, (uint16_t *)&gAdcResult); if (FSP_SUCCESS != err) { printf("ADC Read Failed!\n"); return 9999; } return gAdcResult; // 返回12位ADC原始值(0-4095) }

单次ADC采样可能受噪声干扰,所以我们需要一个函数来读取多次并求平均值,这样数据更稳定。

// 获取ADC原始值(经过多次采样平均) int Get_Adc_Value(void) { int Data = 0; int i; // 采样SAMPLES次(例如5次),然后累加 for(i = 0; i < SAMPLES; i++) { Data += ADC_GET(); delay_ms(5); // 每次采样间隔5ms } Data = Data / SAMPLES; // 计算平均值 return Data; }

有了稳定的ADC原始值,我们就可以把它转换成更直观的湿度百分比了。这里假设ADC值越大代表湿度越高(请根据你的模块实际特性调整,有些模块是反比的)。

// 将ADC值转换为湿度百分比(0%~100%) uint8_t Get_SH_Percentage_value(void) { int adc_max = 4095; // 立创开发板ADC是12位,最大值4095 int adc_new = 0; uint8_t Percentage_value = 0; adc_new = Get_Adc_Value(); // 获取平均后的ADC值 // 计算百分比:(当前值 / 最大值) * 100 Percentage_value = ((float)adc_new / (float)adc_max) * 100.0f; return Percentage_value; }

最后,是读取DO数字引脚状态的函数。这个就简单多了,直接读取GPIO电平即可。

// 读取DO引脚电平状态 char Get_SH_DO_value(void) { bsp_io_level_t pin_level; fsp_err_t err = R_IOPORT_PinRead(&g_ioport_ctrl, BSP_DO_GPIO_PIN, &pin_level); if(err != FSP_SUCCESS) { printf("GPIO Input Read Failed!!\r\n"); return -1; // 读取失败返回-1 } // 根据模块逻辑返回。假设DO输出低电平表示湿度足够(LED亮) if(pin_level == BSP_IO_LEVEL_LOW) { return 0; // 可以定义为“湿” } else { return 1; // 可以定义为“干” } }

注意:Get_SH_DO_value函数返回值的含义(0是湿还是1是湿)取决于你的模块逻辑和电位器调节方向。调试时,用手捏住探针(模拟湿润),观察返回值和模块指示灯的变化来确定。

4. 主程序验证与数据读取

驱动写好了,最后就是在主函数里调用它们,并打印出结果看看。在app.c或你的主循环文件里,可以这样写:

#include "app.h" #include "stdio.h" #include "bsp_uart.h" // 用于串口打印 #include "bsp_soilhumidity.h" void Run(void) { // 初始化调试串口(用于打印信息到电脑) UART0_Debug_Init(); printf("\r\n=== 土壤湿度传感器测试开始 ===\r\n"); // 初始化土壤湿度传感器(主要是ADC) Module_BSP_Init(); printf("土壤湿度传感器初始化完成.\r\n"); while(1) { // 读取并打印三种数据 int raw_adc = Get_Adc_Value(); uint8_t percentage = Get_SH_Percentage_value(); char do_state = Get_SH_DO_value(); printf("\r\n"); printf("ADC原始值: %d\r\n", raw_adc); printf("湿度百分比: %d%%\r\n", percentage); printf("DO状态(0湿/1干): %d\r\n", do_state); printf("----------------------------\r\n"); delay_ms(1000); // 每秒读取一次 } }

编译代码并烧录到立创开发板。打开串口调试助手(如SecureCRT、Putty等),设置好波特率(通常是115200),你就能看到每秒输出的传感器数据了。

如何调试和校准?

  1. 测试ADC:将传感器探针完全置于空气中(干燥状态),记录下ADC原始值和百分比。然后将其浸入水中(小心别淹到电路板),再记录一组值。你就得到了湿度和ADC值的对应范围。
  2. 调节DO阈值:旋转模块上的蓝色电位器。在土壤处于你想要的“临界干湿状态”时,调节电位器直到模块上的DO指示灯刚好改变状态(亮或灭)。这时Get_SH_DO_value()的返回值也会随之改变。
  3. 实际应用:在自动浇花系统中,你可以用Get_SH_DO_value()进行快速判断(低于阈值就启动水泵),同时用Get_SH_Percentage_value()来记录更精细的土壤湿度变化曲线。

好了,整个移植和双模式读取的过程就完成了。代码我已经在实际项目里跑过,稳定可用。遇到问题多看看串口打印的调试信息,硬件连接确保牢靠,剩下的就是根据你的具体应用场景调整逻辑了。

http://www.cnnetsun.cn/news/1272246.html

相关文章:

  • 用快马平台十分钟复刻Notepad++:快速构建文本编辑器原型验证核心逻辑
  • 从零构建:在Keil MDK中为STM32F103搭建RT-Thread Nano开发环境
  • 如何用3步搞定演唱会抢票?开源自动抢票工具全攻略
  • [模电]从原理到实战:二极管核心特性与经典电路设计
  • STM32嵌入式视觉循迹系统设计与优化
  • AI赋能浏览器:基于快马平台快速开发集成大模型的智能扩展
  • AI辅助开发:让Kimi分析激活函数优劣,自动生成集成Swish等新函数的GRU情感分析模型
  • 【环境排障】PyCharm中torch子模块导入失败:从命名冲突到解释器重置的深度修复指南
  • Vue3 PrimeVue 后台管理系统开发实战:从零搭建高效UI框架
  • 实战应用:基于快马ai构建可插拔的消息通知系统核心spi模块
  • YOLO11快速上手:Jupyter一键运行,小白也能轻松训练模型
  • 3步实现多平台高效直播:obs-multi-rtmp插件全攻略
  • 【杰理蓝牙AC696X】蓝牙名称与提示音自定义实战指南
  • wan2.1-vae开源可部署方案:基于Qwen-Image-2512的轻量化文生图平台
  • 在Termux上搭建宝塔面板:从零到一的移动服务器部署指南
  • Qwen Pixel Art多模型协同:与SDXL-Pixel插件联动生成混合风格像素图
  • 数学建模实战:插值与拟合在工程数据分析中的应用
  • 利用快马ai平台,十分钟快速生成你的第一个windows桌面应用原型
  • DDR时序探秘:读写操作中DQS与DQ对齐策略的工程权衡
  • 阿里Wan2.1模型创作实例:如何用一句话生成“宇航员漫步火星”科幻视频
  • LongCat-Image-Editn多场景应用:海报改版、证件照修正、营销图动态更新
  • Transformer在图像超分中的革新:从全局建模到纹理迁移
  • 立创Echo-Mate AI桌面机器人:基于RV1106的硬件架构与多模态AI应用开发全解析
  • 优化el-dialog与el-image的ESC键关闭逻辑:分层处理与事件控制
  • VideoAgentTrek-ScreenFilter提示词工程:优化输入描述以提升过滤精准度
  • 深入解析HTML5 draggable属性:从基础拖拽到实战应用
  • 【Linux】CentOS启动失败报错initramfs/rdsosreport.txt的深度分析与修复指南
  • Allwinner D1s RISC-V开发板硬件设计详解
  • 基于SpringBoot和Leaflet的行政区划地图掩膜效果实战
  • Qwen3-Reranker-4B与小模型协同:构建高效检索系统