STM32 ADC - Analog to Digital Converter

Table of contents

1. ADC functional block diagram

1. Voltage input range

2. Input channel

3. Conversion order

4. Trigger source

5. Conversion time

6. Data Register

2. Introduction to ADC initialization structure

3. ADC common firmware library functions

4. Experimental design

1. Independent mode - single channel - interrupt read

2. Independent mode - (single) multi-channel - must use DMA to read

3. Dual mode - multi-channel - rule synchronization


Introduction: STM32 MCU contains

1-Three independent ADCs 1/2/3

2- Resolution is 12 bit

3- Each ADC has 18 channels, including 16 external channels, which can measure 16 external and 2 internal signal sources.

For example: temperature sensor/VREFINT internal channel: the temperature sensor is connected to the channel ADC1_IN16, and the internal reference voltage VREFINT is connected to ADC1_IN17. These two inner channels can be transformed as injection or regular channels.

1. ADC functional block diagram

1. Voltage input range

Input voltage: VREF- ≤ VIN ≤ VREF+

Pins that determine the input voltage: VREF-, VREF+, VDDA, VSSA

The reference negative voltage VREF is connected to VSSA, and VSSA is grounded; the reference positive voltage VREF+ is connected to VDDA, and VDDA is connected to 3V3. The input voltage range of the ADC is: 0~3.3V .

Since the chip of the MINI board uses 64 pins, there are no VREF- and VREF+ pins, and the input voltage range is only determined by VDDA and VSSA. Only chips with more than 100 pins have these two pins.

2. Input channel

Due to the shortage of pin resources on the board, we only leave channel 11: PC1 as a separate ADC channel, which is not related to any other peripherals.

When using ADC conversion, the pins of VAR and PC1 should be short-circuited , we can unplug the buzzer and the pins of A15 to use.

The 16 external channels are divided into regular channels and injection channels during conversion , among which the regular channels have a maximum of 16 channels, and the injection channels have a maximum of 4 channels.

Classification of channels :

Regular channel: It means very regular, we usually use this channel.

Injection channel: Injection can be understood as insertion and queue jumping. It is a kind of forced insertion to be converted when the regular channel is converted. This is very similar to the interrupt program, the injection channel is inserted into the execution of the rule channel during execution. Therefore, the injection channel will only appear if the regular channel exists.

3. Conversion order

1 - Regular Sequence Register

If we need to convert 3 channels, the value of the lower 4 bits of the SQR1 register is 3. To set the third channel as the first conversion channel, the value of the SQ1 bit of the SQR3 register is 3, and set the second channel as the first channel. For three converted channels, the value of the SQ3 bit of the SQR3 register is 2.

2- Inject sequence register

We set 1, 5, 6, and 7 as injection channels, channel 7 as the first conversion, the JSQ1 bit of the JSQR register should be set to 7; channel 1 is the last conversion, and the JSQ4 bit of the JSQR register should be set to 1. Above This is when there are 4 injection channels. If the number of injection channels is less than 4, you need to configure according to the picture above.

4. Trigger source

1. Software trigger: ADC_CR2 control register 2: ADON/SWST (regular channel)
ART/JSWSTART (injection channel)

2. External event trigger: internal timer/external IO

Select: ADC_CR2: EXTSEL[2:0] and JEXTSEL[2:0]

Activation: ADC_CR2 :EXTEN and JEXTEN

5. Conversion time

Conversion time: Tconv = sampling time + 12.5 fixed periods

The cycle refers to ADC_CLK : ADC analog circuit clock, the maximum value is 14M, provided by PCLK2 (PCLK2=72M), and can also be divided by frequency: 2/4/6/8, and the frequency division factor is determined by ADCPRE[1: 0] setting. Usually we use 6 frequency division = 12M.

The sampling time is controlled by the ADC sampling time registers ADC_SMPR1 and ADC_SMPR2, channels 0-9 are register 2, and channels 10-17 are controlled by register 1.

Digital clock: RCC_APB2ENR for register access

6. Data Register

After everything is ready, the data converted by the ADC depends on the conversion group, the data of the rule group is placed in the ADC_DR register, and the data of the injection group is placed in JDRx .

The data of ADC1 and ADC2 share this register

1-16 bits are effective, used to store the independent mode conversion completed data
2- ADC_CR2: ALIGN bit controls left alignment or right alignment, usually right alignment

3- There is only one register. It is best to use DMA for multi-channel acquisition. Once the data is generated, it will be moved away.

1-16 bits are effective, used to store the conversion completion data of the injection channel
2- ADC_CR2: ALIGN

3 - There are 4 such registers

2. Introduction to ADC initialization structure

1-ADC_MODE: mode selection, DUALMOD bit of ADC_CR1 register

The independent mode is used the most: use ADC1/2/3 alone.

Regular synchronization mode : regular channel, two ADCs are used at the same time, one master and one slave, and the two ADCs collect conversion data at the same time. The collected data is stored in the ADC regular data register (ADC_DR)

Alternate trigger mode: two ADCs, one for data conversion while the other is collecting data, improving the efficiency of work items.

2-ADC_ScanConvMode: scan mode, SCAN bit of ADC_CR1 register

0: Disable scan mode; 1: Enable scan mode. Used in the case of multi-channel acquisition (acquisition of multiple signal sources).

3-ADC_ContinuousConvMode: Continuous conversion mode, CON bit of ADC_CR2 register

0: single conversion mode; 1: continuous conversion mode. Single conversion: collect one point and end, continuous conversion: continuously collect external signal sources and convert them into digital signal quantities.

4-ADC_ExternalTrigConv: External trigger conversion selection, EXTTRIG and EXTSEL[2:0] bits of the ADC_CR2 register

After determining how many channels to convert, after everything is ready, we need to give the ADC a signal to let it start converting. This signal can be triggered by software or externally.

External trigger: the 11 and 15 pins in the figure below, that is, the level changes of all 11 and 15 pins on the board can generate an event, which can trigger the ADC to convert.

   We usually use software triggering.

5-ADC_DataAlign: Data alignment format, the ALIGN bit of the ADC_CR2 register. We usually use right alignment.

6-ADC_NbrOfChannel: The number of converted channels, configuration rule sequence registers and injection sequence registers.

Regular Sequence Register (ADC_SQR1)

Inject Sequence Register (ADC_JSQR)

3. ADC common firmware library functions

ADC_Init(); Initialize structure members

RCC_ADCCLKConfig(); ADC clock configuration configures the frequency division factor of the sampling clock

ADC_RegularChannelConfig(); Regular channel configuration configuration sampling time, conversion order

ADC_Cmd(); 

ADC_SoftwareStartConvCmd(); software trigger

ADC_ExternalTrigConvCmd(); External trigger

ADC_DMACmd(); DMA related

4. Experimental design

1. Independent mode - single channel - interrupt read

The first is to initialize and configure the port pins. One is to configure the GPIO used by the ADC, then configure and initialize the ADC structure, and finally configure the NVIC to handle interrupts.

static void ADCx_GPIO_Config(void)//配置 ADC 用到的 GPIO
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// 打开 ADC IO端口时钟
	ADC_GPIO_APBxClock_FUN ( ADC_GPIO_CLK, ENABLE );
	
	// 配置 ADC IO 引脚模式
	// 必须为模拟输入
	GPIO_InitStructure.GPIO_Pin = ADC_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	//只有在 GPIO口 用作输出的时候才需要配置速度,输入不需要
	
	// 初始化 ADC IO
	GPIO_Init(ADC_PORT, &GPIO_InitStructure);		
}

static void ADC_Mode_Config(void)//配置、初始化 ADC 结构体
{
	ADC_InitTypeDef ADC_InitStructure;	

	// 打开ADC时钟
	ADC_APBxClock_FUN ( ADC_CLK, ENABLE );
	
	// ADC 模式配置
	// 只使用一个ADC,属于独立模式
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//配置为独立模式
	
	// 禁止扫描模式,多通道才要,单通道不需要
	ADC_InitStructure.ADC_ScanConvMode = DISABLE ; 

	// 连续转换模式
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

	// 不用外部触发转换,软件开启即可
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

	// 转换结果右对齐
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	
	// 转换通道1个
	ADC_InitStructure.ADC_NbrOfChannel = 1;	
		
	// 初始化ADC
	ADC_Init(ADCx, &ADC_InitStructure);
	
/*配置采样周期*/	
	// 配置ADC时钟为PCLK2的8分频,即9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8); 
	
	// 配置 ADC 通道转换顺序和采样时间
	ADC_RegularChannelConfig(ADCx,ADC_CHANNEL,1,ADC_SampleTime_55Cycles5);

/*数据转换结束产生中断*/	
	// ADC 转换结束产生中断,在中断服务程序中读取转换值
	ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);
	
	// 开启ADC ,并开始转换
	ADC_Cmd(ADCx, ENABLE);
	
	// 初始化ADC 校准寄存器  
	ADC_ResetCalibration(ADCx);
	// 等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADCx));
	
	// ADC开始校准
	ADC_StartCalibration(ADCx);
	// 等待校准完成
	while(ADC_GetCalibrationStatus(ADCx));
	
	// 由于没有采用外部触发,所以使用软件触发ADC转换 
	ADC_SoftwareStartConvCmd(ADCx, ENABLE);	
}

static void ADCx_NVIC_Config(void)//配置 NVIC,处理中断
{
  NVIC_InitTypeDef NVIC_InitStructure;
	// 优先级分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  // 配置中断优先级
  NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQ;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);	
}

Then write the interrupt program, after detecting the interrupt, read the conversion value of ADC.

void ADC_IRQHandler(void)
{	
	if (ADC_GetITStatus(ADCx,ADC_IT_EOC)==SET)//检测是否产生了中断 
	{
		// 读取ADC的转换值
		ADC_ConvertedValue = ADC_GetConversionValue(ADCx);
	}
	ADC_ClearITPendingBit(ADCx,ADC_IT_EOC);
}

In the main function, the converted analog quantity is converted into an externally collected analog quantity.

The analog range of the voltage is 0-3.3V, and the analog range of the digital quantity: 2 to the 12th power = 4096. 3.3 / 4096 = The minimum accuracy of analog to digital . On this basis, the converted analog quantity is equal to the externally collected analog quantity.

2. Independent mode - (single) multi-channel - must use DMA to read

Use DMA to efficiently read converted data.

We use channels 10-15 for experiments, the corresponding pins of these channels are PC0-PC5, and the clock used is the clock of the C port. But ADC2 has no DMA function, we can only use ADC1 for experiments.

First collect the data of channel 1, then perform data conversion, and put the data into the regular data register. However, since we collect data through multiple channels, if the data is not read in time, it will be overwritten, so the data should be read immediately if it is placed in the regular data register. We can pre-define an array, and the DMA will immediately read the data in the regular data register into the array (we use 6 channels from 0-5, so there are 6 data in the array). After reading the data of channel 1, collect the data of channel 2 immediately...After reading the data of all channels, read it again in a loop.

First configure the GPIO used by the ADC; then initialize the DMA and ADC structures.

static void ADCx_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// 打开 ADC IO端口时钟
	ADC_GPIO_APBxClock_FUN ( ADC_GPIO_CLK, ENABLE );
	
	// 配置 ADC IO 引脚模式
	GPIO_InitStructure.GPIO_Pin = 	ADC_PIN1|
																		ADC_PIN2|
																		ADC_PIN3|
																		ADC_PIN4|
																		ADC_PIN5|
																		ADC_PIN6;

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	
	// 初始化 ADC IO
	GPIO_Init(ADC_PORT, &GPIO_InitStructure);				
}

static void ADCx_Mode_Config(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	
	// 打开DMA时钟
	RCC_AHBPeriphClockCmd(ADC_DMA_CLK, ENABLE);
	// 打开ADC时钟
	ADC_APBxClock_FUN ( ADC_CLK, ENABLE );
	
	// 复位DMA控制器
	DMA_DeInit(ADC_DMA_CHANNEL);	
	// 配置 DMA 初始化结构体
	// 外设基址为:ADC 数据寄存器地址
	DMA_InitStructure.DMA_PeripheralBaseAddr = ( u32 ) ( & ( ADC_x->DR ) );
	// 存储器地址
	DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedValue;	
	// 数据源来自外设
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;	
	// 缓冲区大小,应该等于数据目的地的大小
	DMA_InitStructure.DMA_BufferSize = NOFCHANEL;	
	// 外设寄存器只有一个,地址不用递增
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	// 存储器地址递增
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 	
	// 外设数据大小为半字,即两个字节
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;	
	// 内存数据大小也为半字,跟外设数据大小相同
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;	
	// 循环传输模式
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;	
	// DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;	
	// 禁止存储器到存储器模式,因为是从外设到存储器
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;	
	// 初始化DMA
	DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStructure);	
	// 使能 DMA 通道
	DMA_Cmd(ADC_DMA_CHANNEL , ENABLE);
	
	// ADC 模式配置
	// 只使用一个ADC,属于单模式
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	
	// 扫描模式
	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_InitStructure.ADC_NbrOfChannel = NOFCHANEL;			
	// 初始化ADC
	ADC_Init(ADC_x, &ADC_InitStructure);	
	// 配置ADC时钟N狿CLK2的8分频,即9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8); 
	
	// 配置ADC 通道的转换顺序和采样时间
	ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL1, 1, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL2, 2, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL3, 3, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL4, 4, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL5, 5, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL6, 6, ADC_SampleTime_55Cycles5);
	
	// 使能ADC DMA 请求
	ADC_DMACmd(ADC_x, ENABLE);
	
	// 开启ADC ,并开始转换
	ADC_Cmd(ADC_x, ENABLE);
	
	// 初始化ADC 校准寄存器  
	ADC_ResetCalibration(ADC_x);
	// 等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADC_x));
	
	// ADC开始校准
	ADC_StartCalibration(ADC_x);
	// 等待校准完成
	while(ADC_GetCalibrationStatus(ADC_x));
	
	// 由于没有采用外部触发,所以使用软件触发ADC转换 
	ADC_SoftwareStartConvCmd(ADC_x, ENABLE);
}

Note: The IO used for ADC acquisition must not be multiplexed, otherwise the acquisition voltage will be affected.

The mode used by the I/O of the ADC is analog input, which is neither pulled up nor pulled down. The collected value depends entirely on the analog value you want to collect.

3. Dual mode - multi-channel - rule synchronization

Dual ADCs for acquisition, ADC1 as the master, ADC2 as the slave, and one channel for acquisition. The acquisition and conversion of both are carried out simultaneously. The data of ADC1 is placed in the lower 16 bits of the regular data register, and the data of ADC2 is placed in the upper 16 bits of the regular data register. After the data is placed, the DMA will read the data and read it into a pre-defined array (same as above). The array must be defined as 32 bits . There was only one ADC before, so only a 16-bit array is required.

First configure the GPIO used by the ADC; then initialize the structures of DMA and ADC1 and 2.

static void ADCx_GPIO_Config(void)//ADC 的GPIO配置、初始化
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// ADCx_1 GPIO 初始化
	ADCx_1_GPIO_APBxClock_FUN ( ADCx_1_GPIO_CLK, ENABLE );
	GPIO_InitStructure.GPIO_Pin = ADCx_1_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(ADCx_1_PORT, &GPIO_InitStructure);

	// ADCx_2 GPIO 初始化
	ADCx_1_GPIO_APBxClock_FUN ( ADCx_2_GPIO_CLK, ENABLE );
	GPIO_InitStructure.GPIO_Pin = ADCx_2_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(ADCx_2_PORT, &GPIO_InitStructure);	
}

static void ADCx_Mode_Config(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	
	// 打开DMA时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	// 打开ADC时钟
	ADCx_1_APBxClock_FUN ( ADCx_1_CLK, ENABLE );
	ADCx_2_APBxClock_FUN ( ADCx_2_CLK, ENABLE );
	
  /* ------------------DMA模式配置---------------- */	
	// 复位DMA控制器
	DMA_DeInit(ADC_DMA_CHANNEL);	
	// 配置 DMA 初始化结构体
	// 外设基址为:ADC 数据寄存器地址
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&( ADCx_1->DR ));	
	// 存储器地址
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValue;	
	// 数据源来自外设
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;	
	// 缓冲区大小,应该等于数据目的地的大小
	DMA_InitStructure.DMA_BufferSize = NOFCHANEL;	
	// 外设寄存器只有一个,地址不用递增
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	// 存储器地址递增
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 	
	// 外设数据大小
	DMA_InitStructure.DMA_PeripheralDataSize = 
	                                  DMA_PeripheralDataSize_Word;	
	// 内存数据大小,跟外设数据大小相同
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;	
	// 循环传输模式
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;	
	// DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;	
	// 禁止存储器到存储器模式,因为是从外设到存储器
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;	
	// 初始化DMA
	DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStructure);	
	// 使能 DMA 通道
	DMA_Cmd(ADC_DMA_CHANNEL , ENABLE);
	
	/* ----------------ADCx_1 模式配置--------------------- */
	// 双ADC的规则同步
	ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;	
	// 扫描模式
	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_InitStructure.ADC_NbrOfChannel = NOFCHANEL;			
	// 初始化ADC
	ADC_Init(ADCx_1, &ADC_InitStructure);	
	// 配置ADC时钟N狿CLK2的8分频,即9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8); 	
	// 配置ADC 通道的转换顺序和采样时间
	ADC_RegularChannelConfig(ADCx_1, ADCx_1_CHANNEL, 1, 
	                         ADC_SampleTime_239Cycles5);	
	// 使能ADC DMA 请求
	ADC_DMACmd(ADCx_1, ENABLE);
	
	
		/* ----------------ADCx_2 模式配置--------------------- */
	// 双ADC的规则同步
	ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;	
	// 扫描模式
	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_InitStructure.ADC_NbrOfChannel = NOFCHANEL;			
	// 初始化ADC
	ADC_Init(ADCx_2, &ADC_InitStructure);	
	// 配置ADC时钟为PCLK2的8分频,即9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8); 	
	// 配置ADC 通道的转换顺序和采样时间
	ADC_RegularChannelConfig(ADCx_2, ADCx_2_CHANNEL, 1, 
	                         ADC_SampleTime_239Cycles5);
	/* 使能ADCx_2的外部触发转换 */
  ADC_ExternalTrigConvCmd(ADC2, ENABLE);
	
	/* ----------------ADCx_1 校准--------------------- */
	// 开启ADC ,并开始转换
	ADC_Cmd(ADCx_1, ENABLE);	
	// 初始化ADC 校准寄存器  
	ADC_ResetCalibration(ADCx_1);
	// 等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADCx_1));	
	// ADC开始校准
	ADC_StartCalibration(ADCx_1);
	// 等待校准完成
	while(ADC_GetCalibrationStatus(ADCx_1));
	
  /* ----------------ADCx_2 校准--------------------- */
		// 开启ADC ,并开始转换
	ADC_Cmd(ADCx_2, ENABLE);	
	// 初始化ADC 校准寄存器  
	ADC_ResetCalibration(ADCx_2);
	// 等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADCx_2));	
	// ADC开始校准
	ADC_StartCalibration(ADCx_2);
	// 等待校准完成
	while(ADC_GetCalibrationStatus(ADCx_2));

	// 由于没有采用外部触发,所以使用软件触发ADC转换 
	ADC_SoftwareStartConvCmd(ADCx_1, ENABLE);
}

Note: Why does ADC2 use external trigger?

In dual acquisition mode, ADC1 is master and ADC2 is slave . Internally, ADC1 will give ADC2 a trigger signal, which is automatically started by hardware in dual mode. If you want this startup to be successful, you must turn on the switch of ADC2's external trigger (this signal is given to it by ADC1, which is equivalent to the external one).

In the experiment, we can use the ADC1 (PC1) and ADC2 (PC4) without the jumper cap. We observe the data of ADC1 and connect PC1 and 3V3 with a Dupont line; when observing the data of ADC2, we can use Dupont Connect PC4 (the pin below the LCD screen) to 3V3 with a wire.

 

Guess you like

Origin blog.csdn.net/ChenWenHaoHaoHao/article/details/128435988