|
#申请原创# #技术资源#
使用APM32F425/APM32F427开发伺服或其他电机控制代码中,ADC配置是最为重要的一部分,它实际影响整个电机运行的性能。本帖就以实际通用伺服的ADC注入通道配置来举例说明。 本伺服案例实际ADC使用情况为:ADC1负责电压采样以及模拟量输入采样,共三路;ADC2负责U相电流采样,采用过采样技术,共4路输入;ADC3负责V相电流采样,采用过采样技术,共4路输入。这里展示V相电流采样的配置代码来进行说明。代码采用极海自己开发的底层驱动库函数进行编写,想要学习使用原厂SDK搭建工程的同学可以看看如何调用底层函数。 配置ADC注入通道的基本步骤 1. 使能ADC时钟:确保ADC外设的时钟已经使能。 2. 配置GPIO:选择要使用的注入通道及其对应的外部输入引脚。 3. 配置ADC模式:选择单次转换模式或连续转换模式。 4. 设置注入通道的触发源:可以选择软件触发或外部触发。 5. 配置ADC转换顺序:定义注入通道的转换顺序。 6. 使能ADC:使能ADC并开始转换。 使用极海SDK库函数编写的ADC配置函数如下: void MX_ADC3_Init(void) { GPIO_Config_T gpioConfig = {0}; ADC_Config_T adcConfig = {0}; ADC_CommonConfig_T adcCommonConfig ; /* Peripheral clock enable */ RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC3); RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOC); /**ADC3 GPIO Configuration PC0 ------> ADC3_IN10 PC1 ------> ADC3_IN11 PC2 ------> ADC3_IN12 PC3 ------> ADC3_IN13 */ gpioConfig.pin = ISU1_Pin|ISU2_Pin|ISU3_Pin|ISU4_Pin; gpioConfig.mode = GPIO_MODE_AN; gpioConfig.pupd = GPIO_PUPD_NOPULL; GPIO_Config(GPIOC, &gpioConfig); adcCommonConfig.mode = ADC_MODE_INDEPENDENT; adcCommonConfig.prescaler = ADC_PRESCALER_DIV4;//30MHZ adc ADC_CommonConfig(&adcCommonConfig); adcConfig.continuousConvMode = DISABLE; adcConfig.dataAlign = ADC_DATA_ALIGN_RIGHT; adcConfig.extTrigConv = ADC_EXT_TRIG_CONV_TMR1_CC1; adcConfig.extTrigEdge = ADC_EXT_TRIG_EDGE_NONE; adcConfig.nbrOfChannel = 3; adcConfig.resolution = ADC_RESOLUTION_12BIT; adcConfig.scanConvMode = ENABLE; ADC_Config(ADC3, &adcConfig); ADC_ConfigExternalTrigInjectedConv(ADC3,ADC_EXT_TRIG_INJEC_CONV_TMR1_TRGO); ADC_ConfigExternalTrigInjectedConvEdge(ADC3,ADC_EXT_TRIG_INJEC_EDGE_FALLING); ADC_ConfigInjectedSequencerLength(ADC3,4); ADC_ConfigInjectedChannel(ADC3,ADC_CHANNEL_10,1,ADC_SAMPLETIME_3CYCLES); ADC_ConfigInjectedChannel(ADC3,ADC_CHANNEL_11,2,ADC_SAMPLETIME_3CYCLES); ADC_ConfigInjectedChannel(ADC3,ADC_CHANNEL_12,3,ADC_SAMPLETIME_3CYCLES); ADC_ConfigInjectedChannel(ADC3,ADC_CHANNEL_13,4,ADC_SAMPLETIME_3CYCLES); ADC_Enable(ADC3); } 使用ST LL库函数编写的ADC配置函数如下: void MX_ADC3_Init(void) { LL_ADC_InitTypeDef ADC_InitStruct = {0}; LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0}; LL_ADC_INJ_InitTypeDef ADC_INJ_InitStruct = {0}; LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0}; /* Peripheral clock enable */ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC3); LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOC); /**ADC3 GPIO Configuration PC0 ------> ADC3_IN10 PC1 ------> ADC3_IN11 PC2 ------> ADC3_IN12 PC3 ------> ADC3_IN13 */ GPIO_InitStruct.Pin = ISU1_Pin|ISU2_Pin|ISU3_Pin|ISU4_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(GPIOC, &GPIO_InitStruct); ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B; ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT; ADC_InitStruct.SequencersScanMode = LL_ADC_SEQ_SCAN_ENABLE; LL_ADC_Init(ADC3, &ADC_InitStruct); ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE; ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE; ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE; ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_CONTINUOUS; ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE; // ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN; LL_ADC_REG_Init(ADC3, &ADC_REG_InitStruct); LL_ADC_REG_SetFlagEndOfConversion(ADC3, LL_ADC_REG_FLAG_EOC_UNITARY_CONV); // LL_ADC_EnableInternalRegulator(ADC1); ADC_CommonInitStruct.CommonClock = LL_ADC_CLOCK_SYNC_PCLK_DIV4; ADC_CommonInitStruct.Multimode = LL_ADC_MULTI_TRIPLE_REG_SIM_INJ_ALT; LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC3), &ADC_CommonInitStruct); ADC_INJ_InitStruct.TriggerSource = LL_ADC_INJ_TRIG_EXT_TIM1_TRGO; ADC_INJ_InitStruct.SequencerLength = LL_ADC_INJ_SEQ_SCAN_ENABLE_4RANKS; ADC_INJ_InitStruct.SequencerDiscont = LL_ADC_INJ_SEQ_DISCONT_DISABLE;//LL_ADC_INJ_SEQ_DISCONT_DISABLE; ADC_INJ_InitStruct.TrigAuto = LL_ADC_INJ_TRIG_INDEPENDENT; //LL_ADC_INJ_TRIG_FROM_GRP_REGULAR LL_ADC_INJ_Init(ADC3, &ADC_INJ_InitStruct); /** Configure Injected Channel */ LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_10, LL_ADC_SAMPLINGTIME_28CYCLES); LL_ADC_INJ_SetSequencerRanks(ADC3, LL_ADC_INJ_RANK_1, LL_ADC_CHANNEL_10); LL_ADC_INJ_SetOffset(ADC3, LL_ADC_INJ_RANK_1, 0); LL_ADC_INJ_StartConversionExtTrig(ADC3, LL_ADC_INJ_TRIG_EXT_RISING); LL_ADC_EnableIT_JEOS(ADC3); LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_11, LL_ADC_SAMPLINGTIME_28CYCLES); LL_ADC_INJ_SetSequencerRanks(ADC3, LL_ADC_INJ_RANK_2, LL_ADC_CHANNEL_11); LL_ADC_INJ_SetOffset(ADC3, LL_ADC_INJ_RANK_2, 0); LL_ADC_INJ_StartConversionExtTrig(ADC3, LL_ADC_INJ_TRIG_EXT_RISING); LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_12, LL_ADC_SAMPLINGTIME_28CYCLES); LL_ADC_INJ_SetSequencerRanks(ADC3, LL_ADC_INJ_RANK_3, LL_ADC_CHANNEL_12); LL_ADC_INJ_SetOffset(ADC3, LL_ADC_INJ_RANK_3, 0); LL_ADC_INJ_StartConversionExtTrig(ADC3, LL_ADC_INJ_TRIG_EXT_RISING); LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_13, LL_ADC_SAMPLINGTIME_28CYCLES); LL_ADC_INJ_SetSequencerRanks(ADC3, LL_ADC_INJ_RANK_4, LL_ADC_CHANNEL_13); LL_ADC_INJ_SetOffset(ADC3, LL_ADC_INJ_RANK_4, 0); LL_ADC_INJ_StartConversionExtTrig(ADC3, LL_ADC_INJ_TRIG_EXT_RISING); //LL_ADC_DisableIT_JEOS(ADC3); LL_ADC_EnableIT_JEOS(ADC3); SET_BIT(ADC3->CR1,ADC_CR1_JAUTO); SET_BIT(ADC3->CR1,ADC_CR1_EOCIE); }
|