博客
关于我
学习应用笔记—STM32之ADC+DMA多通道模数转换
阅读量:485 次
发布时间:2019-03-07

本文共 4200 字,大约阅读时间需要 14 分钟。

在以往学习中,使用ADC采集都是规则单通道软件启动采集的那种方式,这种方式也仅限于学习。在真正的项目中会采集很多路ADC,显示上面方式不合理,这时候就可以使用ADC+DMA进行多路采集,Nice!!!

STM32 ADC 简介

在这里插入图片描述


ADC通道与GPIO管脚对应表

在这里插入图片描述


DMA简介

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

更多理论内容可以查看中文参考数据手册

知道以上东西可以撸代码了。

使用固件库配置还是挺"容易"的。看配置代码就理解了。


DMA初始化

static void ADC_DMA_Init(void){     DMA_InitTypeDef DMA_InitStructure;  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  DMA_DeInit(DMA1_Channel1);  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;  //ADC外设数据寄存器地址作为基地址  DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t)g_stTempInfo.ADC_ValTab; //存储数据内存地址  DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralSRC; //传输方向为外设到内存  DMA_InitStructure.DMA_BufferSize         = 4;		  //单位是下面的HalfWord 16bit  DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;  DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;  //用到多通道ADC,                     所以使能自动增加,一个通道转换完的数据放在g_stTempInfo.ADC_ValTab[0],                                                                   //下一个通道数据就自动存放在g_stTempInfo.ADC_ValTab[1]  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据大小为半字  DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;   //内存数据大小也为半字  DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;  //循环模式  DMA_InitStructure.DMA_Priority           = DMA_Priority_High;   //优先级高  DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;    //不使用内存到内存的传输  DMA_Init(DMA1_Channel1, &DMA_InitStructure);  /* Enable DMA1 Channel1 */  DMA_Cmd(DMA1_Channel1, ENABLE);		      //使能DMA通道1 }

模拟输入引脚初始化

static void GPIO_Init(void){   	GPIO_InitTypeDef GPIO_InitStructure;		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);	                       	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_5;         //模拟输入引脚	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		GPIO_Init(GPIOA, &GPIO_InitStructure);		GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;	 //模拟输入引脚		GPIO_Init(GPIOB, &GPIO_InitStructure);	}

PA5对应ADC1的通道5,PB0对应ADC1的通道8

ADC初始化

static void ADC_Init(void){   	ADC_InitTypeDef ADC_InitStructure; 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE );	  //使能ADC1通道时钟		RCC_ADCCLKConfig(RCC_PCLK2_Div6);          //72M/6=12,ADC最大时间不能超过14M		ADC_DeInit(ADC1);  	ADC_InitStructure.ADC_Mode               = ADC_Mode_Independent;				  //ADC工作模式:ADC1工作在独立模式	ADC_InitStructure.ADC_ScanConvMode       = ENABLE;					              //模数转换工作在扫描模式	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;				                  //模数转换工作在连续模式	ADC_InitStructure.ADC_ExternalTrigConv   = ADC_ExternalTrigConv_None;	   //转换由软件而不是外部触发启动     	ADC_InitStructure.ADC_DataAlign          = ADC_DataAlign_Right;			          //ADC数据右对齐	ADC_InitStructure.ADC_NbrOfChannel       = 2;							         //顺序进行规则转换的ADC通道的数目	ADC_Init(ADC1, &ADC_InitStructure);	   	ADC_RegularChannelConfig(ADC1,ADC_Channel_5, 1, ADC_SampleTime_239Cycles5);        //ADC1通道5配置->PA5   第3个参数为转换顺序,转换后的值存在g_stTempInfo.ADC_ValTab[0]中	ADC_RegularChannelConfig(ADC1,ADC_Channel_8, 2, ADC_SampleTime_239Cycles5);	       //ADC1通道8配置->PB0   第3个参数为转换顺序,转换后的值存在g_stTempInfo.ADC_ValTab[1]中    ADC_DMACmd(ADC1, ENABLE);                  //使能ADC1的DMA功能				 	ADC_Cmd(ADC1, ENABLE);	                     //使能ADC1		ADC_ResetCalibration(ADC1);	                 //重置指定的ADC1的校准寄存器	while(ADC_GetResetCalibrationStatus(ADC1));	//获取ADC1重置校准寄存器的状态,设置状态则等待	ADC_StartCalibration(ADC1);		            //开始指定ADC1的校准状态	while(ADC_GetCalibrationStatus(ADC1));		//获取指定ADC1的校准程序,设置状态则等待 	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能	}

初始化GPIO、DMA、ADC

void  MyADC_Init(void){    		GPIO_Init();     	ADC_DMA_Init();     //ADC DMA初始化 	ADC_Init();        //ADC初始化}

获取多个通道的ADC值

void GetAverageAdcVal(stADCTempInfo *TempInfo,u8 n){   	u8 x = 0;	u32  ledVal = 0;	u32   machineVal = 0;			if(TempInfo == NULL)	{   		printf("指针为空\r\n");		return; 	} 		for(x = 0; x < n; x++)	{   			while(!DMA_GetFlagStatus(DMA1_FLAG_TC1));        //等待DMA传输完成		ledVal     += TempInfo->ADC_ValTab[0];		machineVal += TempInfo->ADC_ValTab[1];		delay_ms(1);	}		ledVal = ledVal / n;	TempInfo->averageLedAdcVal  = ledVal;	machineVal = machineVal / n;	TempInfo->averageMachineAdcVal = machineVal;}

转载地址:http://dtzcz.baihongyu.com/

你可能感兴趣的文章
MySQL中的ON DUPLICATE KEY UPDATE详解与应用
查看>>
mysql中的rbs,SharePoint RBS:即使启用了RBS,内容数据库也在不断增长
查看>>
mysql中的undo log、redo log 、binlog大致概要
查看>>
Mysql中的using
查看>>
MySQL中的关键字深入比较:UNION vs UNION ALL
查看>>
mysql中的四大运算符种类汇总20多项,用了三天三夜来整理的,还不赶快收藏
查看>>
mysql中的字段如何选择合适的数据类型呢?
查看>>
MySQL中的字符集陷阱:为何避免使用UTF-8
查看>>
mysql中的数据导入与导出
查看>>
MySQL中的时间函数
查看>>
mysql中的约束
查看>>
MySQL中的表是什么?
查看>>
mysql中穿件函数时候delimiter的用法
查看>>
Mysql中索引的分类、增删改查与存储引擎对应关系
查看>>
Mysql中索引的最左前缀原则图文剖析(全)
查看>>
MySql中给视图添加注释怎么添加_默认不支持_可以这样取巧---MySql工作笔记002
查看>>
Mysql中获取所有表名以及表名带时间字符串使用BetweenAnd筛选区间范围
查看>>
Mysql中视图的使用以及常见运算符的使用示例和优先级
查看>>
Mysql中触发器的使用示例
查看>>
Mysql中设置只允许指定ip能连接访问(可视化工具的方式)
查看>>