土壤湿度传感器它利用电磁脉冲原理、根据电磁波在介质中传播频率来测量土壤的表观介电常数,从而得到土壤相对含水量。
代码流程
1.看原理图确定GPIO与ADC通道 PA5, ADC1IN5
2.配置GPIO为模拟模式
3.ADC初始化
a.结构体申明 ADC_CommonInitTypeDef
b.时钟使能
c.结构体配置
d.初始化
4.ADC通道初始化
a.结构体申明 ADC_InitTypeDef
b.结构体配置
c.初始化
5.可以进行中断配置
记得开中断,规则通道结束中断标志为ADC_IT_EOC
6.各种使能
a.ADC通道使能
b.ADC使能
c.软件开启ADC转换
ADC结构体的介绍在上一篇文章有讲
ADC等结构体的配置
void ADC_SOIL_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;//通用初始化结构体,决定三个ADC 共用的工作环境,比如模式选择、ADC 时钟等等
ADC_InitTypeDef ADC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN;
//GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; //单路模式
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div6; //四分频,84/4 = 21Mhz ,低于36Mhz
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_10Cycles; //两次混合采样的周期延迟,独立模式怎么设置都不影响
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //是否扫面
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //是否连续
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //无边沿检测
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //右对齐
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_84Cycles);
ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); //开启规则转换结束中断
ADC_Cmd(ADC1, ENABLE); //使能ADC
ADC_SoftwareStartConv(ADC1); //软件触发,开始转换
}
土壤湿度检测模块的引脚配置
void Gpio_Soil_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定义一个设置GPIO的变量给土壤湿度检测器 - PA1
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能GPIOA端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //设置PA1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //设置PA
}
获得 ADC 值
//ch:通道值 0~16 ADC_Channel_0~ADC_Channel_16
//返回值:转换结果
u16 Get_Adc_Soil(u8 ch)
{
//设置指定 ADC 的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_480Cycles );
ADC_SoftwareStartConv(ADC1); //使能指定的 ADC3 的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次 ADC3 规则组的转换结果
}
平均多次ADC结果,提高精度
/*参 数:channel: 通道数
/*参 数:count: 平均次数
int Get_Adc_Soil_Average(int channel,int count)
{
int sum_val=0;
char t;
for(t=0;t<count;t++) //循环读取times次
{
sum_val+=Get_Adc_Soil(channel); //计算总值
Delay_ms(5); //延时
}
return sum_val/count; //返回平均值
}
实现功能函数
这里我用的是OLED显示汉字和数据(字模可以用取模软件得到),没配置OLED的可以用串口打印一下
void soil_moisture(void)
{
float raindata; //接受雨滴数据
float voltage;//水位数据
raindata = 90 - (((float)Get_Adc_Soil_Average(3,20))*(3.3/4096)*30);
printf("雨水值:%.2f\r\n",raindata);
if(raindata > 40)
{
printf("有雨水出现!\r\n");
}
else
{
printf("没有雨水出现!\r\n");
}
int i;
for(i = 0;i < 4; i++)
{
OLED_ShowSoil(1,i+1,i);//显示汉字 - 土壤湿度
}
OLED_ShowString(1,9,":");
OLED_ShowNum(1,10,(int)raindata,2);
}