STM32_ADC————ADC+DMA多路数据传输,看门狗中断,传感器控制LED

本文介绍了如何在STM32微控制器上使用ADC、DMA和看门狗中断来控制LED灯。通过DMA传输ADC采集的光敏传感器数据,设置看门狗中断阈值,当ADC读数超出范围时,LED灯闪烁。文章详细阐述了ADC和DMA的初始化流程,以及中断处理程序,提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要内容:

一:介绍ADC与DMA的基本情况与初始化

二:利用ADC+DMA+看门狗中断+传感器控制LED灯代码

三:总结实验过程中碰到的错误与问题

实验说明:

通过DMA转运ADC的数据,设置ADC的中断看门狗阈值,当光敏传感器的ADC采样值在看门狗高低阈值中间,不触发中断,如果超过看门狗的高低阈值就会触发中断,LED灯进行闪烁,并且利用串口打印出四个通道的ADC采样值(本实验传感器的D0口接PA0)。

1:介绍ADC与DMA的基本情况与初始化:

(1):ADC的模块框图,更多内容可以参考STM32官方文档。

 (2)根据上图对照总结出大致ADC的执行流程图如下。

 根据STM32F103系列可知,

ADC内有18个通道:

其中16个位外部通道和2个内部通道信号源。

ADC的转换器通道有两种:

规则组:ADC可以对一组指定的通道,按照指定的顺序,逐个转换这组通道,转换结束后,再从头循环;这指定的通道组就称为规则组。

注入组:但是实际应用中,有可能需要临时中断规则组的转换,对某些通道进行转换,这些需要中断规则组而进行转换的通道组,就称为注入组。

ADC模式选择:

独立模式:ADC转换完1个通道的数据后才能转换下一个通道的数据。

双重模式:具有两个ADC时可实现。

三重模式:具有三个 ADC时可实现

本次实验选择一个ADC独立模式,我们可以根据需求进行单通道,不循环模式。单通道,循环模式。多通道,不循环模式。多通道,循环模式。

ADC配置的大致流程:

选择配置好相关ADC的GPIO口后,根据ADC的初始化可选择所需要的转换通道(规则组或注入组),开启ADC_Cmd(),ADC校准,软件触发。如果需要看门狗中断就进行初始化。

(3)  ADC的模块框图,更多内容可以参考STM32官方文档。

 (4)根据上图对照总结出大致DMA的执行流程图如下。

 DMA的传输模式:

外设与存储器之间:当配置完外设之后,就进行外设应答传输,将外设获取到的数据通过总线传输到存储器中。

存储器与存储器之间:当启动DMA传输模式后,DMA外设通过DMA总线,总线矩阵将Flash中的数据直接写到SRAM中。

 一般ADC都会与DMA搭配进行使用,因为ADC获取数据之后如果在很短的时间内不转运出去就会被下一波数据覆盖掉,所以需要DMA进行数据的搬运,DMA的搬运不需要消耗CPU资源。

DMA的实现过程:

在发生一个事件后,外设向DMA控制器发送一个请求信号。DMA控制器根据通道的优先权处理 请求。当DMA控制器开始访问发出请求的外设时,DMA控制器立即发送给它一个应答信号。当 DMA控制器得到应答信号时,外设立即释放它的请求。一旦外设释放了这个请求,DMA控制器同时撤销应答信号。如果有更多的请求时,外设可以启动下一个周期。

DMA配置的大致流程:

根据DMA的初始化配置,选择外设地址,内存储器地址,传输方向,缓存方向等,最后如果和ADC进行搭配一定要开启ADC_DMACmd()函数,进行ADC与DMA的硬件连接,最后开启DMA_Cmd().

二:利用ADC+DMA+看门狗中断+传感器控制LED灯代码

本次实验利用的是ADC+DMA多通道循环模式

(1)各种宏定义,方便后续移植。

#ifndef __ADG_H
#define __ADG_H
#include "stm32f10x.h"
#define				ADC_x                                 ADC1
#define       ADC_Channel_x                               ADC_Channel_0
#define       ADC_RCC_APB2Periph_ADC1                     RCC_APB2Periph_ADC1
#define 			ADC_RCC_APB2PeriphClockCmd            RCC_APB2PeriphClockCmd

#define       DMAy_Channelx                               DMA1_Channel1
#define       RCC_AHBPeriph_DMAx                          RCC_AHBPeriph_DMA1
#define       GPIO_x                                      GPIOA
#define       GPIO_PIN_x                                  GPIO_Pin_0
#define       GPIO_Pin_x1                                 GPIO_Pin_1
#define       GPIO_Pin_x2                                 GPIO_Pin_2
#define       GPIO_Pin_x3                                 GPIO_Pin_3
#define       GPIO_RCC_APB2Periph_ADC1                    RCC_APB2Periph_GPIOA
#define       GPIO_RCC_APB2PeriphClockCmd                 APB2PeriphClockCmd

void AD_DMA_GetValue(void);
extern uint16_t Value[4];
void   ADCInit(void);
void AD_DMA_GetValue(void);
void ADC_Config(void);
#endif

 (2)ADC的GPIO的初始化,这里特别注意配置GPIO_MODE模式一定要选择模拟输入GPIO_Mode_AIN。

//ADC的GPIO口初始化
void	ADC_GPIOInit(void)
{
            //开启GPIO的时钟
			ADC_RCC_APB2PeriphClockCmd(GPIO_RCC_APB2Periph_ADC1,ENABLE);
			GPIO_InitTypeDef		GPIO_InitStruture;
			GPIO_InitStruture.GPIO_Mode = GPIO_Mode_AIN;
			GPIO_InitStruture.GPIO_Pin = GPIO_PIN_x |  GPIO_Pin_x1 | GPIO_Pin_x2 | GPIO_Pin_x3;
			GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
			GPIO_Init(GPIO_x, &GPIO_InitStruture);
}


 (3) 模拟看门狗的初始化,特别注意看门狗的高低阈值内不发生中断。

void WatchDog_ADInit()
{
		//模拟看门狗的单通道
		ADC_AnalogWatchdogSingleChannelConfig(ADC_x, ADC_Channel_x);
		//设置模拟看门狗的高低,看门狗的高低值内不触发中断
		ADC_AnalogWatchdogThresholdsConfig(ADC_x,HighThreshold,LowThreshold); 
		//打开看门狗的单通道检测
		ADC_AnalogWatchdogCmd(ADC_x,ADC_AnalogWatchdog_SingleRegEnable);
		//使能中断
		ADC_ITConfig(ADC_x,ADC_IT_AWD,ENABLE);
}

 (4)中断优先级的设置。

//中断优先级的设置
void  ADC_NVICInit(void)
{
        //设置中断组
		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
		NVIC_InitTypeDef				NVIC_InitStruture;
        //设置中断源
		NVIC_InitStruture.NVIC_IRQChannel = ADC1_2_IRQn;
        //设置主优先级
		NVIC_InitStruture.NVIC_IRQChannelPreemptionPriority = 1; 
        //设置子优先级
		NVIC_InitStruture.NVIC_IRQChannelSubPriority = 2;
        //使能中断
		NVIC_InitStruture.NVIC_IRQChannelCmd = ENABLE;
		NVIC_Init(&NVIC_InitStruture);
		
}

 (5)DMA初始化。

void ADC_DMA_Init(void)
{
	   
			RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMAx,ENABLE);
	
		  DMA_InitTypeDef		DMA_InitStruture;
	    //将DMA的通道1寄存器重设为缺省值 
	    DMA_DeInit(DMA1_Channel1);                                            
		  //外设站点的地址
			DMA_InitStruture.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;              
	    //外设寄存器低16位地址
			DMA_InitStruture.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 
	    //外设地址寄存器不变
	    DMA_InitStruture.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
 	    //传输的目的地址
			DMA_InitStruture.DMA_MemoryBaseAddr = (uint32_t)Value;         
	    //选择内部寄存器的低16位地址
			DMA_InitStruture.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;   
	    //选择内存地址寄存器递增
		  DMA_InitStruture.DMA_MemoryInc = DMA_MemoryInc_Enable;   
	    //传输方向,从外设到内设
			DMA_InitStruture.DMA_DIR = DMA_DIR_PeripheralSRC;  
	    //DMA通道的DMA缓存的大小
			DMA_InitStruture.DMA_BufferSize = 4; 
			//选择正常模式还是循环模式 
	    DMA_InitStruture.DMA_Mode = DMA_Mode_Circular;  
      //非内存到内存传输
			DMA_InitStruture.DMA_M2M = DMA_M2M_Disable;                                  
			//DMA通道X拥有中优先级
			DMA_InitStruture.DMA_Priority = DMA_Priority_Medium;                         
					
			DMA_Init(DMAy_Channelx,&DMA_InitStruture);
			//使能DMA
			DMA_Cmd(DMAy_Channelx, ENABLE);
	
}

 (6)ADC初始化。

void   ADCInit(void)
{
	  //开启ADC的时钟
		ADC_RCC_APB2PeriphClockCmd(ADC_RCC_APB2Periph_ADC1,ENABLE);
	  //ADC的时钟分频
		RCC_ADCCLKConfig(RCC_PCLK2_Div6);
		//输入规则组的通道的选择(扫描通道)
		ADC_RegularChannelConfig(ADC_x,ADC_Channel_0,1, ADC_SampleTime_55Cycles5);
		ADC_RegularChannelConfig(ADC_x,ADC_Channel_1,2, ADC_SampleTime_55Cycles5);
		ADC_RegularChannelConfig(ADC_x,ADC_Channel_2,3, ADC_SampleTime_55Cycles5);
		ADC_RegularChannelConfig(ADC_x,ADC_Channel_3,4, ADC_SampleTime_55Cycles5);
		ADC_InitTypeDef   	ADC_InitStruture;
		//模式选择
		ADC_InitStruture.ADC_Mode = ADC_Mode_Independent;
		//选择多通道模式或单通道模式
		ADC_InitStruture.ADC_ScanConvMode = ENABLE;
		//指定选择模式是单词还是多次
		ADC_InitStruture.ADC_ContinuousConvMode = DISABLE;
	  //软件触发
		ADC_InitStruture.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
		//选择右对其方式
		ADC_InitStruture.ADC_DataAlign = ADC_DataAlign_Right;
		//选择使用的通道
		ADC_InitStruture.ADC_NbrOfChannel = 4;
		ADC_Init(ADC_x,&ADC_InitStruture);
	
		//使能ADC
		ADC_Cmd(ADC_x, ENABLE);   
		//使能ADC与DMA的硬件连接
		ADC_DMACmd(ADC_x,ENABLE);                                             
    //复位校准	
		ADC_ResetCalibration(ADC_x);                        	
		//返回复位校准的状态
		while(ADC_GetResetCalibrationStatus(ADC_x) != RESET); 
    //启动校准
		ADC_StartCalibration(ADC_x);                          
		//获取校准的状态
		while(ADC_GetCalibrationStatus(ADC_x) != RESET);	    
		//:软件触发
		ADC_SoftwareStartConvCmd(ADC_x,ENABLE);               
		
		
	}		

(7)整体初始化放到一个函数中,特别注意WatchDog_ADInit();的位置,一定要放到ADC初始化的后面。

void ADC_Config(void)
{
		ADC_GPIOInit();
		ADC_NVICInit();
		ADC_DMA_Init();
		ADCInit();
	    WatchDog_ADInit();
}
	

(8)判断DMA获取的标志位,不断进行软件触发。

void AD_DMA_GetValue(void)
{
	
		DMA_SetCurrDataCounter(DMAy_Channelx,4);  //设置传输数据传输通道数
	
		DMA_Cmd(DMAy_Channelx,ENABLE);
		
		ADC_SoftwareStartConvCmd(ADC_x,ENABLE);   //软件触发开启
		
		while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);//获取标志位状态
		DMA_ClearFlag(DMA1_FLAG_TC1);
}

(9)中断函数。

void ADC1_2_IRQHandler(void)
{
        //获取中断标志中断位
		if(ADC_GetITStatus(ADC_x,ADC_IT_AWD) == SET)
		{
		
				LED_R(ON);
				Delay(0xFFFFF);
				LED_R(OFF);
				Delay(0xFFFFF);
                //清楚中断标志位
				ADC_ClearITPendingBit(ADC_x,ADC_IT_AWD);
                //清楚ADC的标志位
				ADC_ClearFlag(ADC_x,ADC_FLAG_AWD);
		}
	
		
}

 (10)实验完整代码。

//main.c

#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp.usart.h"
#include "adg.h"
#include <stdio.h>
unsigned int AD_Value;

void Delay(uint32_t count)
{

	for(int i =0;i<count;count--);

}

int main(void)
{
		
	  LED_GPIO_Config();
		USART_Config();

	  ADC_Config();
		while(1)
   	{         
					AD_DMA_GetValue();
					printf("AD0 = %d\n",Value[0]);
					printf("AD1 = %d\n",Value[1]);
					printf("AD2 = %d\n",Value[2]);
					printf("AD3 = %d\n",Value[3]);
					Delay(0xFFFFF);
					
	  }
}


//stm32f10x_it.c

void ADC1_2_IRQHandler(void)
{
		if(ADC_GetITStatus(ADC_x,ADC_IT_AWD) == SET)
		{
				//BrightEnough = 0;
				LED_R(ON);
				Delay(0xFFFFF);
				LED_R(OFF);
				Delay(0xFFFFF);
				ADC_ClearITPendingBit(ADC_x,ADC_IT_AWD);
				ADC_ClearFlag(ADC_x,ADC_FLAG_AWD);
		}
	
		
}


//adg.c
   #include "adg.h"
unsigned  int   HighThreshold = 200;           
unsigned  int   LowThreshold =150;
extern unsigned int AD_Value;
uint16_t Value[4];
void	ADC_GPIOInit(void)
{	
			ADC_RCC_APB2PeriphClockCmd(GPIO_RCC_APB2Periph_ADC1,ENABLE);
			GPIO_InitTypeDef		GPIO_InitStruture;
			GPIO_InitStruture.GPIO_Mode = GPIO_Mode_AIN;
			GPIO_InitStruture.GPIO_Pin = GPIO_PIN_x |  GPIO_Pin_x1 | GPIO_Pin_x2 | GPIO_Pin_x3;
			GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
			GPIO_Init(GPIO_x, &GPIO_InitStruture);
}

void WatchDog_ADInit()
{
		//模拟看门狗的单通道
		ADC_AnalogWatchdogSingleChannelConfig(ADC_x, ADC_Channel_x);
		//设置模拟看门狗的高低,看门狗的高低值内不触发中断
		ADC_AnalogWatchdogThresholdsConfig(ADC_x,HighThreshold,LowThreshold); 
		//打开看门狗的单通道检测
		ADC_AnalogWatchdogCmd(ADC_x,ADC_AnalogWatchdog_SingleRegEnable);
		//使能中断
		ADC_ITConfig(ADC_x,ADC_IT_AWD,ENABLE);
}
//中断优先级的设置
void  ADC_NVICInit(void)
{
		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
		NVIC_InitTypeDef				NVIC_InitStruture;
		NVIC_InitStruture.NVIC_IRQChannel = ADC1_2_IRQn;
		NVIC_InitStruture.NVIC_IRQChannelPreemptionPriority = 1;
		NVIC_InitStruture.NVIC_IRQChannelSubPriority = 2;
		NVIC_InitStruture.NVIC_IRQChannelCmd = ENABLE;
		NVIC_Init(&NVIC_InitStruture);
		
}
void ADC_DMA_Init(void)
{
	   
			RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMAx,ENABLE);
	
		  DMA_InitTypeDef		DMA_InitStruture;
	    //将DMA的通道1寄存器重设为缺省值 
	    DMA_DeInit(DMA1_Channel1);                                            
		  //外设站点的地址
			DMA_InitStruture.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;              
	    //外设寄存器低16位地址
			DMA_InitStruture.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 
	    //外设地址寄存器不变
	    DMA_InitStruture.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
 	    //传输的目的地址
			DMA_InitStruture.DMA_MemoryBaseAddr = (uint32_t)Value;         
	    //选择内部寄存器的低16位地址
			DMA_InitStruture.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;   
	    //选择内存地址寄存器递增
		  DMA_InitStruture.DMA_MemoryInc = DMA_MemoryInc_Enable;   
	    //传输方向,从外设到内设
			DMA_InitStruture.DMA_DIR = DMA_DIR_PeripheralSRC;  
	    //DMA通道的DMA缓存的大小
			DMA_InitStruture.DMA_BufferSize = 4; 
			//选择正常模式还是循环模式 
	    DMA_InitStruture.DMA_Mode = DMA_Mode_Circular;  
      //非内存到内存传输
			DMA_InitStruture.DMA_M2M = DMA_M2M_Disable;                                  
			//DMA通道X拥有中优先级
			DMA_InitStruture.DMA_Priority = DMA_Priority_Medium;                         
					
			DMA_Init(DMAy_Channelx,&DMA_InitStruture);
			//使能DMA
			DMA_Cmd(DMAy_Channelx, ENABLE);
	
}

void   ADCInit(void)
{
	  //开启ADC的时钟
		ADC_RCC_APB2PeriphClockCmd(ADC_RCC_APB2Periph_ADC1,ENABLE);
	  //ADC的时钟分频
		RCC_ADCCLKConfig(RCC_PCLK2_Div6);
		//输入规则组的通道的选择(扫描通道)
		ADC_RegularChannelConfig(ADC_x,ADC_Channel_0,1, ADC_SampleTime_55Cycles5);
		ADC_RegularChannelConfig(ADC_x,ADC_Channel_1,2, ADC_SampleTime_55Cycles5);
		ADC_RegularChannelConfig(ADC_x,ADC_Channel_2,3, ADC_SampleTime_55Cycles5);
		ADC_RegularChannelConfig(ADC_x,ADC_Channel_3,4, ADC_SampleTime_55Cycles5);
		ADC_InitTypeDef   	ADC_InitStruture;
		//模式选择
		ADC_InitStruture.ADC_Mode = ADC_Mode_Independent;
		//选择多通道模式或单通道模式
		ADC_InitStruture.ADC_ScanConvMode = ENABLE;
		//指定选择模式是单词还是多次
		ADC_InitStruture.ADC_ContinuousConvMode = DISABLE;
	  //软件触发
		ADC_InitStruture.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
		//选择右对其方式
		ADC_InitStruture.ADC_DataAlign = ADC_DataAlign_Right;
		//选择使用的通道
		ADC_InitStruture.ADC_NbrOfChannel = 4;
		ADC_Init(ADC_x,&ADC_InitStruture);
	
		//使能ADC
		ADC_Cmd(ADC_x, ENABLE);   
		//使能ADC与DMA的硬件连接
		ADC_DMACmd(ADC_x,ENABLE);                                             
    //复位校准	
		ADC_ResetCalibration(ADC_x);                        	
		//返回复位校准的状态
		while(ADC_GetResetCalibrationStatus(ADC_x) != RESET); 
    //启动校准
		ADC_StartCalibration(ADC_x);                          
		//获取校准的状态
		while(ADC_GetCalibrationStatus(ADC_x) != RESET);	    
		//:软件触发
		ADC_SoftwareStartConvCmd(ADC_x,ENABLE);               
		
		
	}		

void ADC_Config(void)
{
		ADC_GPIOInit();
		ADC_NVICInit();
		ADC_DMA_Init();
		ADCInit();
	  WatchDog_ADInit();
}
//可以获取ADC单个值	
unsigned int  ADC_GetADVal()
{
		ADC_SoftwareStartConvCmd(ADC_x,ENABLE);
		while(ADC_GetFlagStatus(ADC_x,ADC_FLAG_EOC) == 0);
		//等待规则转换完成
		ADC_SoftwareStartConvCmd(ADC_x,DISABLE);
		return(ADC_GetConversionValue(ADC_x));
}

void AD_DMA_GetValue(void)
{
	
		DMA_SetCurrDataCounter(DMAy_Channelx,4);  //设置传输数据传输通道数
	
		DMA_Cmd(DMAy_Channelx,ENABLE);
		
		ADC_SoftwareStartConvCmd(ADC_x,ENABLE);   //软件触发开启
		
		while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);//获取标志位状态
		DMA_ClearFlag(DMA1_FLAG_TC1);
}

//adg.h

#ifndef __ADG_H
#define __ADG_H
#include "stm32f10x.h"
#define				ADC_x                                       ADC1
#define       ADC_Channel_x                               ADC_Channel_0
#define       ADC_RCC_APB2Periph_ADC1                     RCC_APB2Periph_ADC1
#define 			ADC_RCC_APB2PeriphClockCmd                  RCC_APB2PeriphClockCmd

#define       DMAy_Channelx                               DMA1_Channel1
#define       RCC_AHBPeriph_DMAx                          RCC_AHBPeriph_DMA1
#define       GPIO_x                                      GPIOA
#define       GPIO_PIN_x                                  GPIO_Pin_0
#define       GPIO_Pin_x1                                 GPIO_Pin_1
#define       GPIO_Pin_x2                                 GPIO_Pin_2
#define       GPIO_Pin_x3                                 GPIO_Pin_3
#define       GPIO_RCC_APB2Periph_ADC1                    RCC_APB2Periph_GPIOA
#define       GPIO_RCC_APB2PeriphClockCmd                 APB2PeriphClockCmd

void AD_DMA_GetValue(void);
extern uint16_t Value[4];
//extern char  BrightEnough;
void   ADCInit(void);
unsigned int  ADC_GetADVal();
void AD_DMA_GetValue(void);
void ADC_Config(void);
#endif




三:总结实验过程中碰到的错误与问题

1:DMA_PeripheralDataSize_HalfWord与DMA_MemoryDataSize_HalfWord在配置过程中十分相似,如果在配置DMA_PeripheralDataSize使用DMA_MemoryDataSize_HalfWord;就会丢失高位数据。

2:注意开启ADC_DMACmd();函数。不然ADC与DMA无法进行连接。

3:注意在DMA内存地址一定要uint32_t 强制转化,而且注意内存地址一定对照清楚。

4:注意在最后设置DMA完成的标志位判定,并进行ADC软件触发,不然就只会转运第一个ADC接收到转运的数据,不再工作。

5:注意DMA配置DMA_DIR时DMA_DIR_PeripheralSRC(外设到内存的配置)。

void ADC_DeInit(void); /* Initialization and Configuration functions *********************************/ void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct); void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct); void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct); void ADC_CommonStructInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct); void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState); /* Analog Watchdog configuration functions ************************************/ void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog); void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold,uint16_t LowThreshold); void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel); /* Temperature Sensor, Vrefint and VBAT management functions ******************/ void ADC_TempSensorVrefintCmd(FunctionalState NewState); void ADC_VBATCmd(FunctionalState NewState); /* Regular Channels Configuration functions ***********************************/ void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); void ADC_SoftwareStartConv(ADC_TypeDef* ADCx); FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx); void ADC_EOCOnEachRegularChannelCmd(ADC_TypeDef* ADCx, FunctionalState NewState); void ADC_ContinuousModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number); void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx); uint32_t ADC_GetMultiModeConversionValue(void); /* Regular Channels DMA Configuration functions *******************************/ void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState); void ADC_DMARequestAfterLastTransferCmd(ADC_TypeDef* ADCx, FunctionalState NewState); void ADC_MultiModeDMARequestAfterLastTransferCmd(FunctionalState NewState); /* Injected channels Configuration functions **********************************/ void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length); void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset); void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv); void ADC_ExternalTrigInjectedConvEdgeConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConvEdge); void ADC_SoftwareStartInjectedConv(ADC_TypeDef* ADCx); FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx); void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel); /* Interrupts and flags management functions **********************************/ void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState); FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG); void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG); ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT); void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT); 1. 上面这些函数那个函数是用来ADC校准的
04-09
<think>嗯,用户问的是关于ADC校准的函数,但给出的函数列表里好像没有直接提到校准相关的函数。首先,我需要仔细看一下用户提供的所有函数名称,确认是否有遗漏。比如,常见的ADC校准函数可能有ADC_Calibration或类似的名称,但这里没有。 接下来,我需要回忆一下STM32ADC模块常见函数。通常,校准过程可能包括ADC_StartCalibration和ADC_GetCalibrationStatus这样的函数。但用户提供的列表里确实没有这些。这可能意味着用户提供的代码片段不完整,或者他们使用的是某个特定系列的库,可能函数命名有所不同。 另外,考虑到有些库函数可能将校准步骤集成在初始化函数中,比如ADC_Init可能会调用校准程序,但这需要查看具体实现。不过根据标准库,通常校准是独立的步骤,需要手动启动。例如,在STM32的标准外设库中,校准函数是ADC_Calibrate,但用户提供的列表里没有这个函数。 也有可能用户提到的函数属于某个特定版本或配置,可能校准函数被其他函数间接调用。比如,ADC_Cmd在启用ADC之前可能需要校准,但这也只是推测。根据用户给出的函数列表,确实没有直接的校准函数。 因此,正确的结论应该是用户提供的这些函数中没有用于ADC校准的。可能需要检查是否有遗漏,或者参考对应芯片的参考手册确认校准函数的具体名称和用法。</think>在您提供的函数列表中,**没有直接用于ADC校准的函数**。根据STM32标准外设库的常规设计,ADC校准通常需要以下两个关键函数: 1. **ADC_ResetCalibration()** - 功能:启动ADC校准复位 - 用法示例:`ADC_ResetCalibration(ADC1);` 2. **ADC_GetResetCalibrationStatus()** - 功能:检查校准复位是否完成 - 用法示例:`while(ADC_GetResetCalibrationStatus(ADC1));` 3. **ADC_StartCalibration()** - 功能:启动ADC校准过程 - 用法示例:`ADC_StartCalibration(ADC1);` 4. **ADC_GetCalibrationStatus()** - 功能:检查校准是否完成 - 示例:`while(ADC_GetCalibrationStatus(ADC1));` --- ### 可能的原因分析: 您提供的函数列表可能存在以下情况: 1. **代码片段不完整**:可能未包含校准相关函数 2. **库版本差异**:不同STM32系列(如F1/F4/H7)的库函数命名可能有区别 3. **隐性操作**:某些初始化函数(如`ADC_Cmd()`)可能隐式触发校准,但需参考具体芯片手册验证 --- ### 建议操作步骤: 1. **查阅芯片参考手册**:搜索 "ADC calibration" 章节 2. **检查库文件源码**:查找 `stm32fxxx_adc.c` 文件中的校准函数实现 3. **标准校准流程参考**: ```c ADC_Cmd(ADC1, ENABLE); // 先使能ADC ADC_ResetCalibration(ADC1); // 复位校准寄存器 while(ADC_GetResetCalibrationStatus(ADC1)); // 等待复位完成 ADC_StartCalibration(ADC1); // 开始校准 while(ADC_GetCalibrationStatus(ADC1)); // 等待校准完成 ``` --- 如果需要更具体的实现细节,请提供以下信息: 1. 使用的STM32具体型号(如STM32F103C8T6) 2. 使用的库版本(标准外设库/HAL库/LL库) 3. 当前遇到的校准相关问题描述
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值