欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ADC的DMA多通道数据采集(雨滴传感器+光敏传感器)

程序员文章站 2022-04-18 08:09:42
...

AADC1跟ADC3可以用DMA,因为多通道,然而ADC只有一个数据寄存器,因此可以用DMA开一个数组来存数据

 ADC1只能用DMA1的通道1

ADC的DMA多通道数据采集(雨滴传感器+光敏传感器)

  ADC3只能用DMA2的通道5

ADC的DMA多通道数据采集(雨滴传感器+光敏传感器)

最近在学模拟量的测试,我用了光敏传感器和雨滴传感器,跟上一篇的光敏传感器差不多,只不过这里多了DMA的初始,可以实现独立ADC的多通道数据采集。

adc.h

#ifndef ADC_H
#define ADC_H

#include "sys.h"

void ADC3_Init(void);
//u16 ADC3_Get(u8 ch);
u16 ADC3_GetLightValue(void);
u16 ADC3_GetYuDiValue(void);
//u16 ADC3_GetSmogValue(void);
#endif /* ADC_H */

adc.c

#include "adc.h"
#include "delay.h"
#include "usart.h"

//ADC3使用的是DMA2的通道5

u16 ADC_ConversionValue[2] = {0,0};
void ADC3_Init(void)
{
	DMA_InitTypeDef DMA_InitStruct;
	ADC_InitTypeDef ADC_InitStruct;

	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);	  //开启时钟
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,ENABLE);		  //复位
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,DISABLE);	  //关闭
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);			//时钟分频,ADC不能超过14Mhz,不然会不精准,系统内部时钟是72Mhz,所以要分频
	
	//DMA设置
	DMA_DeInit(DMA2_Channel5);
	
	DMA_InitStruct.DMA_PeripheralBaseAddr = (u32)(&ADC3->DR);//外设的基地址
	DMA_InitStruct.DMA_MemoryBaseAddr = (u32)&ADC_ConversionValue;	//内存存储地址,即数据的基地址
	DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;//数据来源于外设
	DMA_InitStruct.DMA_BufferSize = 2;//缓冲区大小,数组的长度
	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//只有一个外设,地址不增
	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址递增,即数组地址增
	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据大小为半字,也就是两个字节
	DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//内存大小为半字,也就是两个字节
	DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;//循环传输
	DMA_InitStruct.DMA_Priority	= DMA_Priority_High;//DMA通道优先级为高,当使用一个DMA通道是,优先级不影响
	DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;	//外设到内存模式
	DMA_Init(DMA2_Channel5, &DMA_InitStruct);
	DMA_Cmd(DMA2_Channel5, ENABLE);
	
	//ADC设置
	ADC_DeInit(ADC3);

	ADC_InitStruct.ADC_Mode	= ADC_Mode_Independent; //独立模式
	ADC_InitStruct.ADC_ScanConvMode	= ENABLE;	  //模数转换工作在多通道模式
	ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;  //连续转换
	ADC_InitStruct.ADC_ExternalTrigConv	= ADC_ExternalTrigConv_None;  //不使用外部触发
	ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;		//转换结果右对齐,放在低12位
	ADC_InitStruct.ADC_NbrOfChannel = 2;   //顺序进行规则转换的ADC通道的数目
	ADC_Init(ADC3, &ADC_InitStruct);

	
	ADC_RegularChannelConfig(ADC3, ADC_Channel_4, 1, ADC_SampleTime_55Cycles5);//规则通道,ADC3,通道4,第一个转换,采样时间为55.5周期
	ADC_RegularChannelConfig(ADC3, ADC_Channel_5, 2, ADC_SampleTime_55Cycles5);//规则通道,ADC3,通道5,第一个转换,采样时间为55.5周期
//	ADC_RegularChannelConfig(ADC3, ADC_Channel_6, 3, ADC_SampleTime_55Cycles5);
	
	ADC_DMACmd(ADC3, ENABLE);  //使能ADC的DMA请求
	ADC_Cmd(ADC3, ENABLE);

	ADC_ResetCalibration(ADC3);	//重置指定的ADC3的复位寄存器
    while(ADC_GetResetCalibrationStatus(ADC3));	//获取ADC3重置校准寄存器的状态,设置状态则等待
	ADC_StartCalibration(ADC3);	 //开启精准计算
	while(ADC_GetCalibrationStatus(ADC3));
	ADC_SoftwareStartConvCmd(ADC3, ENABLE);	//使能指定的ADC3的软件转换启动功能


}
 
u16 ADC3_GetLightValue(void)
{
//	 printf("ADC_ConversionValue[0]:%d\r\n", ADC_ConversionValue[0]);
	 return (u16)ADC_ConversionValue[0];
}

u16 ADC3_GetYuDiValue(void)
{
//	 printf("ADC_ConversionValue[1]:%d\r\n", ADC_ConversionValue[0]);
	 return (u16)ADC_ConversionValue[1];
}
//
//u16 ADC3_GetSmogValue(void)
//{
//	 printf("ADC_ConversionValue[1]:%d\r\n", ADC_ConversionValue[0]);
//	 return (u16)ADC_ConversionValue[2];
//}

光敏传感器

lightsensor.h

 

 

lightsensor.c

#include "lightsensor.h"
#include "adc.h"
#include "delay.h"
#include "led.h"
#include "usart.h"

//extern u16 ADC_ConversionValue[2] = {0,0};
//光敏传感器PF6/ADC3_IN4
void LighrSensor_Init(void)				//初始化GPIO
{
	GPIO_InitTypeDef GPIO_InitStruct;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
	
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;		  //采用ADC的时候,这里要用模拟输入模式
	GPIO_Init(GPIOF, &GPIO_InitStruct);

	ADC3_Init();
}
//光敏传感器模拟值0-100
u8 LightSensor_Val(void)
{
	u32 temp = 0;
	u8 t;
	for(t=0;t<LightSensor_read_time;t++)		  // LightSensor_read_time:采集次数
	{
//		temp += ADC3_Get(LSENS_ch);				  //多次采集的数据和
		temp =temp + ADC3_GetLightValue();
//		printf("temp:%d\r\n", temp);
		delay_ms(5);
	}
	temp /= LightSensor_read_time;				 //	平均值:多次采集的数据和除以采集次数
	printf("temp:%d\r\n", temp);
	if(temp > 4000) 							  
	{
	   temp = 4000;

	}else
	{
	   LED1 = 0;
	}
	return (u8)(100-(temp/40)); 				  //模拟量输出范围为 0-100
}

雨滴传感器

mdrh.h

#ifndef __MHRD_H
#define __MHRD_H

#include "sys.h"

#define YU_DO	 PAin(5)// PB5

void DO_Init(void);//这个是雨滴传感器作为TTL的高低电平初始化
void MHRD_AO_Init(void);//这个雨滴传感器的模拟初始化
u8 YuDi_Val(void);
#endif /* __MHRD_H */

mdrh.c

#include "mhrd.h"
#include "adc.h"
#include "delay.h"
#include "beep.h"
//PA5 - DO 低电平有效
void DO_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能PA端口时钟
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;				 //DO-->PA.5 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA.5
 GPIO_SetBits(GPIOA,GPIO_Pin_5);						 //PB.5 输出高,关闭

}

void MHRD_AO_Init(void)
{
	
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);	 //使能PF端口时钟
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;				 //AO-->PF.7 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 		 //模拟输入
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOF, &GPIO_InitStructure);					 //根据设定参数初始化GPIOF7
 ADC3_Init();
}

//雨滴传感器模拟值0-200
u8 YuDi_Val(void)
{
	u32 temp = 0;
	u8 t;
	for(t=0;t<10;t++)		  // LightSensor_read_time:采集次数
	{
//		temp += ADC3_Get(LSENS_ch);				  //多次采集的数据和
		temp += ADC3_GetYuDiValue();
		delay_ms(5);
	}
	temp /= 10;				 //	平均值:多次采集的数据和除以采集次数
	if(temp > 4000) 							  
	{
	   temp = 4000;
	   BEEP(1);		//蜂鸣器响,这个是用来检测没有水的时候,蜂鸣器会响,雨滴的值为0
	}else
	{
	   BEEP(0);
	}
	return (u8)(200-(temp/20)); 				  //模拟量输出范围为 0-200
}

 

相关标签: 传感器