博客
关于我
学习应用笔记—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 为什么需要两阶段提交?
查看>>
mysql 为某个字段的值加前缀、去掉前缀
查看>>
mysql 主从
查看>>
mysql 主从 lock_mysql 主从同步权限mysql 行锁的实现
查看>>
mysql 主从互备份_mysql互为主从实战设置详解及自动化备份(Centos7.2)
查看>>
mysql 主从关系切换
查看>>
mysql 主键重复则覆盖_数据库主键不能重复
查看>>
Mysql 优化 or
查看>>
mysql 优化器 key_mysql – 选择*和查询优化器
查看>>
MySQL 优化:Explain 执行计划详解
查看>>
Mysql 会导致锁表的语法
查看>>
mysql 使用sql文件恢复数据库
查看>>
mysql 修改默认字符集为utf8
查看>>
Mysql 共享锁
查看>>
MySQL 内核深度优化
查看>>
mysql 内连接、自然连接、外连接的区别
查看>>
mysql 写入慢优化
查看>>
mysql 分组统计SQL语句
查看>>
Mysql 分页
查看>>
Mysql 分页语句 Limit原理
查看>>