伺服开发驱动中,ADC的采集是重点中的重点。本开发板中的模拟量是:三相电流、1个总线电压、1个温度(板载传感器)。三相电流经过ADC采集转化后,经过矢量变换(Clarke变换和Park变换),转化为励磁电流Id和转矩电流Iq,再经过速度控制器的控制,对电机转速进行调速。
总线电压和温度主要是对电路进行安全保护。
1.硬件电路设计
(1)三相电流经过1W,0.33Ω采样后,经比例放大1.53倍后输入到单片机模拟通道,单片机经逐次逼近采样运算得到结果。
其中A相电流连接的是PA0,ADC通道为ADC1_IN0;B相电流连接的是PC1,ADC通道为ADC1_IN11和ADC2_IN11;C相电流连接的是PC0,ADC通道为ADC2_IN10;
(2)VBUS电压连接的是PA1,ADC通道为ADC1_IN1;
温度连接的是PC2,ADC通道为ADC1_IN12;
2.软件设计
(1)ADC简介
12 位 ADC 是逐次趋近型模数转换器。它具有多达 19 个复用通道,可测量来自 16 个外部源、 两个内部源和 VBAT 通道的信号。这些通道的 A/D 转换可在单次、连续、扫描或不连续采样 模式下进行。ADC 的结果存储在一个左对齐或右对齐的 16 位数据寄存器中。 ADC 具有模拟看门狗特性,允许应用检测输入电压是否超过了用户自定义的阈值上限或下限。
(2)ADC结构框图
ADC拥有非常多功能,是由ADC内部结构所决定。要更好的理 解STM32F7的ADC,就需要了解它内部的结构。如下图所示:(查看《STM32F10x中文参考手册》-15模数转换器(ADC)章-ADC功 能说明)。
图中1号:参考电压输入引脚
ADC输入电压范围为: VREF- ≤ VIN ≤ VREF+。由 VREF-、 VREF+ 、 VDDA 、 VSSA这四个外部引脚决定。通常我们把 VSSA和 VREF-接地 ,把 VREF+和 VDDA 接 3.3V,因此ADC的输入电压范围为:0~3.3V。我 们使用的开发板ADC输入电压范围为0~3.3V。
图中2号:输入通道
STM32 的 ADC的输入通道多达 19个,其中外部的 16 个通道就是框 图中的 ADCx_IN0、ADCx_IN1...ADCx_IN5(x=1/2/3,表示ADC数),通 过这16个外部通道可以采集模拟信号。这 16 个通道对应着不同的 IO 口, 具体是哪一个 IO 口可以从数据手册查询到。其中 ADC1 还有2 个内部通道:ADC1 的通道16连接到了芯片内部的温度传感器,通道17连 接到了内部参考电压 VREFINT。
图中3号:通道转换顺序和触发源(外部触发和软件触发)
外部的 16 个通道在转换的时候可分为2组通道:规则通道组和注入 通道组,其中规则通道组最多有16路,注入通道组最多有 4 路。 规则通道组:从名字来理解,规则通道就是一种规规矩矩的通道,类 似于正常执行的程序,通常我们使用的都是这个通道。 注入通道组:从名字来理解,注入即为插入,是一种不安分的通道, 类似于中断。当程序正常往下执行时,中断可以打断程序的执行。同样 如果在规则通道转换过程中,有注入通道插入,那么就要先转换完注入 通道,等注入通道转换完成后再回到规则通道的转换流程。 每个组包含一个转换序列,该序列可按任意顺序在任意通道上完成。 例如,可按以下顺序对序列进行转换: ADC_IN3、ADC_IN8、 ADC_IN2、 ADC_IN2、 ADC_IN0、 ADC_IN2、 ADC_IN2、 ADC_IN15。
选择好输入通道,设置好转换顺序,接下来就可以开始转换。要开启 ADC转换,可以直接设置ADC 控制寄存器ADC_CR2 的 ADON位为1,即使能 ADC。当然ADC还支持外部事件触发转换,触发源有很多,具体选择哪一 种触发源,由 ADC 控制寄存器2:ADC_CR2 的 EXTSEL[3:0]和 JEXTSEL[3:0]位来控制。EXTSEL[3:0]用于选择规则通道的触发源, JEXTSEL[3:0]用于选择注入通道的触发源。选定好触发源之后,可以通过设置 ADC 控制寄存器 2:ADC_CR2 的EXTEN[1:0]和 JEXTEN[1:0]来控制触发极性和使能,可以有 4 种 状态,分别是:禁止触发检测、上升沿检测、下降沿检测以及上升沿和 下降沿均检测。
图中4号:中断标志
当发生如下事件且使能相应中断标志位时,ADC能产生中断。
1.转换结束(规则转换)与注入转换结束
2.模拟看门狗事件
3.DMA请求
图中5号:数据寄存器
ADC 转换后的数据根据转换组的不同,规则组的数据放在ADC_DR 寄 存器内,注入组的数据放在 JDRx内。 因为STM32F7的ADC是12位转换精度,而数据寄存器是16位,所以ADC 在存放数据的时候就有左对齐和右对齐区分。如果是左对齐,AD转换完 成数据存放在 ADC_DR 寄存器的[4:15]位内;如果是右对齐,则存放在 ADC_DR 寄存器的[0:11]位内。具体选择何种存放方式,需通过ADC_CR2 的 11 位 ALIGN 设置。
图中6号:ADC时钟
ADC 输入时钟 ADC_CLK 由 APB2经过分频产生,最大值是54MHz,分 频因子由 RCC 时钟配置寄存器 RCC_CCR 的位 17:16 ADCPRE[1:0]设置 ,可以是 2/4/6/8 分频。
(3)软件编写
根据硬件和ADC的框图,配置ADC1和ADC2:
/**
* [url=home.php?mod=space&uid=159083]@brief[/url] ADC1 Initialization Function
* @param None
* @retval None
*/
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
//PA0:A相电流,ADC1_IN0;
//PC1:B相电流,ADC1_IN11;ADC2_IN11
//PA1:VBUS电压,ADC1_IN1;
//PC2:温度,ADC1_IN12;
/* USER CODE END ADC1_Init 0 */
ADC_InjectionConfTypeDef sConfigInjected = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;//ADC1
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //ADC1时钟4分频
hadc1.Init.Resolution = ADC_RESOLUTION_12B; //分辨率为12位
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; //扫描模式开启
hadc1.Init.ContinuousConvMode = DISABLE; //连续采样模式关闭
hadc1.Init.DiscontinuousConvMode = DISABLE;//非连续采样模式关闭
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //禁止触发检测,使用软件触发
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发
hadc1.Init.DataAlign = ADC_DATAALIGN_LEFT; //数据左对齐
hadc1.Init.NbrOfConversion = 2; //配置为2通道
hadc1.Init.DMAContinuousRequests = DISABLE; //关闭DMA传输数据
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;//使能EOC标志位
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time
*/
//为选定的 ADC 注入通道配置其在定序器中的相应等级及其采样时间
sConfigInjected.InjectedChannel = ADC_CHANNEL_0; //ADC1通道0
sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;//注入组排序器中的排名为1
sConfigInjected.InjectedNbrOfConversion = 2;//指定将在注入的组序列器中转换的等级数为2
sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_15CYCLES;//通道的采样时间为15
sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONVEDGE_RISING;//选择注入组的外部触发沿为上升沿
sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJECCONV_T1_CC4;//选择用于触发注入组转换开始的外部事件。
sConfigInjected.AutoInjectedConv = DISABLE;//禁用选定的 ADC 自动注入组转换后定期转换
sConfigInjected.InjectedDiscontinuousConvMode = ENABLE;//指定注入组的转换序列是以完整序列(主序列细分为连续部分)进行。
sConfigInjected.InjectedOffset = 0;//要从原始转换数据中减去的偏移量为0
if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK)//初始化ADC1
{
Error_Handler();
}
/** Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time
*/
sConfigInjected.InjectedChannel = ADC_CHANNEL_11;//ADC1通道11
sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;//注入组排序器中的排名为2
if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK)//初始化
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_1;//常规ADC通道1
sConfig.Rank = ADC_REGULAR_RANK_1;//指定常规组排序器中的排名为1
sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES;//采样周期为28
sConfig.Offset = 0;//偏移量为0
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)//初始化
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_12;//常规ADC通道12
sConfig.Rank = ADC_REGULAR_RANK_2;//指定常规组排序器中的排名为2
sConfig.Offset = 0;//偏移量为0
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)//初始化
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
/**
* @brief ADC2 Initialization Function
* @param None
* @retval None
*/
static void MX_ADC2_Init(void)
{
/* USER CODE BEGIN ADC2_Init 0 */
//PC0:C相电流,ADC2_IN10;
//PC1:B相电流,ADC1_IN11;ADC2_IN11
/* USER CODE END ADC2_Init 0 */
ADC_InjectionConfTypeDef sConfigInjected = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC2_Init 1 */
/* USER CODE END ADC2_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc2.Instance = ADC2;//ADC2
hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;//ADC2时钟4分频
hadc2.Init.Resolution = ADC_RESOLUTION_12B;//分辨率为12位
hadc2.Init.ScanConvMode = ADC_SCAN_ENABLE;//扫描模式开启
hadc2.Init.ContinuousConvMode = DISABLE;//连续采样模式关闭
hadc2.Init.DiscontinuousConvMode = DISABLE;//非连续采样模式关闭
hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;//禁止触发检测,使用软件触发
hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;//软件触发
hadc2.Init.DataAlign = ADC_DATAALIGN_LEFT;//数据左对齐
hadc2.Init.NbrOfConversion = 1;//配置为1通道
hadc2.Init.DMAContinuousRequests = DISABLE;//关闭DMA传输数据
hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;//使能EOC标志位
if (HAL_ADC_Init(&hadc2) != HAL_OK)//初始化ADC2
{
Error_Handler();
}
/** Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time
*/
//为选定的 ADC 注入通道配置其在定序器中的相应等级及其采样时间
sConfigInjected.InjectedChannel = ADC_CHANNEL_11;//ADC2通道11
sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;//注入组排序器中的排名为1
sConfigInjected.InjectedNbrOfConversion = 2;//指定将在注入的组序列器中转换的等级数为2
sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_15CYCLES;//通道的采样时间为15
sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONVEDGE_RISING;//选择注入组的外部触发沿为上升沿
sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJECCONV_T1_CC4;//选择用于触发注入组转换开始的外部事件。
sConfigInjected.AutoInjectedConv = DISABLE;//禁用选定的 ADC 自动注入组转换后定期转换
sConfigInjected.InjectedDiscontinuousConvMode = ENABLE;//指定注入组的转换序列是以完整序列(主序列细分为连续部分)进行。
sConfigInjected.InjectedOffset = 0;//要从原始转换数据中减去的偏移量为0
if (HAL_ADCEx_InjectedConfigChannel(&hadc2, &sConfigInjected) != HAL_OK)//初始化注入模式
{
Error_Handler();
}
/** Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time
*/
sConfigInjected.InjectedChannel = ADC_CHANNEL_10;//ADC2通道10
sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;//注入组排序器中的排名为2
if (HAL_ADCEx_InjectedConfigChannel(&hadc2, &sConfigInjected) != HAL_OK)//初始化注入模式
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_10;//常规ADC通道10
sConfig.Rank = ADC_REGULAR_RANK_1;//指定常规组排序器中的排名为2
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;//采样周期为3
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)//初始化常规ADC
{
Error_Handler();
}
/* USER CODE BEGIN ADC2_Init 2 */
/* USER CODE END ADC2_Init 2 */
}