stm32c8t6智能大棚,如何用FC-28土壤湿度检测器检测土壤湿度,代码怎么写,需要建立哪些文件,每个文件写什么代码,已有主函数如下,主函数如何在保持原有的功能下修改代码 #include "stm32f10x.h" // Device header #include "delay.h" #include "OLED.h" #include "dht11.h" #include "Serial.h" #include "FAN.h" #include "math.h" #include "LightSensor.h" #include "soil_moisture.h" #define TEMP_THRESHILD 28.0f #define HUMI_THRESHILD 60 u8 temp,humi; static float filtered_temp = 0.0; static float last_display_temp = 0.0; static uint16_t light_adc = 0; int main(void) { uint32_t bufe[5]; OLED_Init(); DHT11_Init(); Fan_Init(); LightSensor_Init(); ADC1_Init(); SoilMoisture_Init(); OLED_ShowChinese(0, 0, "温度:"); OLED_ShowChinese(94, 0, "℃"); OLED_ShowChinese(0, 16, "湿度:"); OLED_ShowChinese(0, 48, "土壤:"); OLED_ShowChinese(0, 32, "光照强度:"); OLED_ShowString(94,16,"RH",OLED_8X16); OLED_ShowString(40,48," %",OLED_8X16); OLED_ShowString(112,32,"LX",OLED_8X16); OLED_Update(); while(1) { if(DHT11_Read_Data(&temp,&humi) == SUCCESS) { filtered_temp = filtered_temp * 0.7 + temp * 0.3; char temp_str[8]; sprintf(temp_str, "%2.1f", filtered_temp); if(fabs(filtered_temp - last_display_temp) >= 0.3) { OLED_ShowString(32,0,temp_str,OLED_8X16); last_display_temp = filtered_temp; bufe[0]=temp; bufe[1]=humi; soil_adc = Get_SoilMoisture_ADC(); soil_percent = map(soil_adc, SOIL_DRY_ADC, SOIL_WET_ADC, 0, 100); soil_percent = (soil_percent > 100) ? 100 : soil_percent; // 限幅处理 OLED_ShowNum(40, 48, soil_percent, 3, OLED_8X16); // 显示百分比 OLED_ShowNum(32,16,bufe[1],2,OLED_8X16); if(filtered_temp > TEMP_THRESHILD){ Fan_On(); }else{ Fan_Off(); } OLED_Update(); //将OLED显存数组更新到OLED屏幕 } else { OLED_ShowString(0,48,"DHT11 Error!",OLED_8X16); } Delay_ms(2000); uint16_t light_raw = Get_LightIntensity(); uint16_t light_value = (uint16_t)((light_raw * 999.0f) / 4095.0f); OLED_ShowNum(64, 32, light_value, 3, OLED_8X16); } } }
时间: 2025-07-16 13:01:07 浏览: 2
<think>嗯,用户之前问过FC-28和C8T6的连接问题,现在他们进一步想用STM32C8T6做一个智能大棚,需要具体的代码和文件结构。看起来他们已经有一个主函数,需要在此基础上整合土壤湿度检测。我需要先理清他们的需求。
首先,用户的主函数已经包含了DHT11、OLED、风扇、光照传感器和土壤湿度的初始化。但代码中可能有些错误,比如soil_adc和soil_percent变量未声明,还有map函数的实现问题。我需要指出这些错误并提供修正方法。
接下来,用户需要知道如何建立所需的文件,比如soil_moisture.h和.c,这些文件负责ADC初始化和读取土壤湿度。我要确保代码结构清晰,模块化,方便维护。
然后,用户的主函数里需要添加土壤湿度的读取和显示。现有的代码中,soil_adc和soil_percent可能没有定义,需要补充变量声明。同时,map函数可能需要自己实现,因为标准C库中没有这个函数,用户可能不知道这一点,需要提供示例代码。
另外,用户可能对滤波处理感兴趣,比如对土壤湿度进行滑动平均滤波,以提高数据稳定性。这可以作为优化建议提出,但需要确保代码不过于复杂,适合他们的当前水平。
还要注意代码中的条件判断是否正确,比如DHT11读取失败时的处理,以及OLED显示的位置是否正确,避免覆盖其他内容。用户可能忽略了某些细节,比如变量作用域或函数调用的顺序。
最后,确保所有建议都保持原有功能,同时整合新的土壤湿度检测。需要检查代码结构,比如while循环的括号是否正确,是否有遗漏的分号,以及函数调用的正确性。可能用户提供的代码中存在语法错误,需要指出并修正。
总结来说,我需要分步骤引导用户添加必要的文件,修正变量声明,实现map函数,优化数据读取,并确保主函数逻辑正确。同时,提供代码示例和注意事项,帮助他们顺利集成FC-28到项目中。</think>我们将分步骤构建STM32C8T6智能大棚的土壤湿度检测系统,保持原有代码框架的基础上进行扩展:
**1. 文件架构建议**
```
Project/
├── User/
│ ├── main.c // 主程序(已有)
│ ├── soil_moisture.h // 新增
│ ├── soil_moisture.c // 新增
│ └── ...其他已有驱动文件
```
**2. 新增文件内容**
➤ `soil_moisture.h` 头文件:
```c
#ifndef __SOIL_MOISTURE_H
#define __SOIL_MOISTURE_H
#include "stm32f10x.h"
// 校准参数(需根据实测调整)
#define SOIL_DRY_ADC 2500 // 完全干燥时的ADC值
#define SOIL_WET_ADC 1200 // 完全湿润时的ADC值
void SoilMoisture_Init(void);
uint16_t Get_SoilMoisture_ADC(void);
uint8_t Get_SoilMoisture_Percent(void);
#endif
```
➤ `soil_moisture.c` 源文件:
```c
#include "soil_moisture.h"
#include "delay.h"
static uint16_t ADC_Filter(void) {
// 滑动平均滤波
static uint16_t buf[5];
uint32_t sum = 0;
for(uint8_t i=0; i<4; i++)
buf[i] = buf[i+1];
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
buf[4] = ADC_GetConversionValue(ADC1);
for(uint8_t i=0; i<5; i++)
sum += buf[i];
return sum / 5;
}
uint16_t Get_SoilMoisture_ADC(void) {
return ADC_Filter();
}
uint8_t Get_SoilMoisture_Percent(void) {
uint16_t adc_val = Get_SoilMoisture_ADC();
// 带限幅的线性映射
if(adc_val <= SOIL_WET_ADC) return 100;
if(adc_val >= SOIL_DRY_ADC) return 0;
return (uint8_t)((adc_val - SOIL_WET_ADC) * 100.0 / (SOIL_DRY_ADC - SOIL_WET_ADC));
}
void SoilMoisture_Init(void) {
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE);
// 配置ADC通道(假设使用PA1)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
}
```
**3. 主函数修改要点**
在现有代码基础上进行以下调整:
```c
// 在全局变量区添加
static uint16_t soil_adc = 0;
static uint8_t soil_percent = 0;
// 自定义映射函数(替代Arduino风格的map)
static uint8_t map_adc(uint16_t x, uint16_t in_min, uint16_t in_max, uint8_t out_min, uint8_t out_max) {
if(x <= in_min) return out_max;
if(x >= in_max) return out_min;
return (uint8_t)(out_max - (x - in_min) * (out_max - out_min) / (in_max - in_min));
}
// 主循环修改部分
while(1)
{
// 原有DHT11代码保持不变...
// 添加土壤湿度处理(在OLED更新前)
soil_adc = Get_SoilMoisture_ADC();
soil_percent = map_adc(soil_adc, SOIL_DRY_ADC, SOIL_WET_ADC, 0, 100);
// 显示优化:避免频繁刷新
static uint8_t last_soil = 0;
if(abs(soil_percent - last_soil) > 2) {
OLED_ShowNum(40, 48, soil_percent, 3, OLED_8X16);
last_soil = soil_percent;
}
// 保持原有控制逻辑...
// 调整采样周期
Delay_ms(1000); // 从2000改为1000
}
```
**4. 关键修改说明**
1. **ADC滤波优化**:
- 使用5点滑动平均滤波:$$ \bar{x}_n = \frac{1}{5}\sum_{i=0}^{4}x_{n-i} $$
- 避免因传感器噪声导致的数值跳动
2. **湿度映射算法改进**:
- 带限幅的线性转换:$$ \text{percent} = \begin{cases}
100\% & \text{if } ADC \leq WET\_ADC \\
0\% & \text{if } ADC \geq DRY\_ADC \\
\frac{ADC - WET\_ADC}{DRY\_ADC - WET\_ADC} \times 100\% & \text{otherwise}
\end{cases} $$
3. **显示刷新优化**:
- 仅当湿度变化超过2%时更新显示,降低OLED刷新频率
**5. 硬件连接验证**
```
FC-28 → STM32C8T6
VCC → 3.3V
GND → GND
AO → PA1 (ADC1通道1)
DO → 可不接(未使用数字输出)
```
**6. 校准建议**
1. 将传感器完全插入干燥土壤,记录`SOIL_DRY_ADC`
2. 将传感器浸入水中,记录`SOIL_WET_ADC`
3. 修改头文件中的宏定义值
4. 校准公式:$$ \text{真实湿度} = \frac{ADC_{water} - ADC_{当前}}{ADC_{water} - ADC_{dry}} \times 100\% $$
**7. 代码稳定性增强**
- 在`soil_moisture.c`中添加超时检测:
```c
// 修改ADC读取部分
uint8_t timeout = 0;
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) && (++timeout < 100));
if(timeout >= 100) return 0xFFFF; // 返回错误值
```
**8. 最终系统工作流程**
```
[传感器] → [STM32处理] → [执行机构]
FC-28(ADC) → 滤波 → 湿度转换 → OLED显示
↓
温度/湿度阈值判断 → 风扇控制
```
以上修改在保留原有温湿度、光照检测功能的基础上,新增了土壤湿度检测模块。实际部署时建议:
1. 使用防水型FC-28探头
2. 在PA1引脚增加0.1μF滤波电容
3. 对土壤传感器供电线做RC滤波(100Ω + 10μF)
阅读全文
相关推荐


















