//############################################################ //近期在用STM32F103编写无刷电机矢量控制,在配置ADC模式时遇到很多奇怪的问题,网上能说清楚的资料太少, //公布我配置的结果,实测OK //3组规则通道连续转换+DMA //2组注入通道TIM1的4通道触发(规格书未说明是上升沿还是下降沿触发,实测波形为上升沿触发) //############################################################ #include "ADC_int.h" #include "GPIO_int.h" #include "Task_function.h" #include "Tim1_PWM.h"
#define ADC1_DR_Address 0x4001244C
extern logic logicContr; extern ADCSamp ADCSampPare; uint16_t ADC_ConvertedValue[3]={0}; uint16_t BUS_CurrProtection=600; //通过母线电流值保护硬件 软件处理 3A左右为600峰值 extern uint8_t flag_injectedoffset; extern uint8_t flag_regularoffset;
uint8_t injectedoffsecount = 0; uint8_t regularoffsecount = 0;
void ADC1_Configuration(void) { ADC_InitTypeDef ADC_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;
/* ADC1 Periph clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); /* ADC1 DeInit */ ADC_DeInit(ADC1); /* Initialize ADC structure */ ADC_StructInit(&ADC_InitStructure); 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 = 3; //设置转换序列长度为2 ADC_Init(ADC1, &ADC_InitStructure); RCC_ADCCLKConfig( RCC_PCLK2_Div2 ); // 72/2 ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 1, ADC_SampleTime_13Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 2, ADC_SampleTime_13Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_13,3, ADC_SampleTime_13Cycles5); ADC_InjectedSequencerLengthConfig(ADC1, 2); ADC_InjectedChannelConfig(ADC1, ADC_Channel_3, 1,ADC_SampleTime_13Cycles5); ADC_InjectedChannelConfig(ADC1, ADC_Channel_6, 2,ADC_SampleTime_13Cycles5); ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_T1_CC4); ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE); //使能或者失能 ADCx 的经外部触发启动注入组转换功能 ADC_ITConfig(ADC1,ADC_IT_JEOC,ENABLE); //ENABLE INJECTED INTERRUPT
ADC_AutoInjectedConvCmd(ADC1, DISABLE); //使能或者失能指定 ADC 在规则组转化后自动开始注入组转换 ADC_ExternalTrigConvCmd(ADC1, DISABLE); //软件启动注入组转换 // Enable ADC1 ADC_Cmd(ADC1, ENABLE); // 开启ADC的DMA支持(要实现DMA功能,还需独立配置DMA通道等参数) ADC_DMACmd(ADC1, ENABLE); // 下面是ADC自动校准,开机后需执行一次,保证精度 // Enable ADC1 reset calibaration register ADC_ResetCalibration(ADC1); // Check the end of ADC1 reset calibration register while(ADC_GetResetCalibrationStatus(ADC1));
// Start ADC1 calibaration ADC_StartCalibration(ADC1); // Check the end of ADC1 calibration while(ADC_GetCalibrationStatus(ADC1)); // ADC自动校准结束--------------- //启动第一次AD转换 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //因为已经配置好了DMA,接下来AD自动连续转换,结果自动保存在RegularConvData_Tab处
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//指定抢占优先级1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//指定响应优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }
void DMA_Configuration(void) { DMA_InitTypeDef DMA_InitStructure; // NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //BufferSize=2,因为ADC转换序列有2个通道 //如此设置,使序列1结果放在RegularConvData_Tab[0],序列2结果放在RegularConvData_Tab[1] DMA_InitStructure.DMA_BufferSize = 3; 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; //循环模式开启,Buffer写满后,自动回到初始地址开始传输 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); //配置完成后,启动DMA通道 DMA_Cmd(DMA1_Channel1, ENABLE); // DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE); //配置DMA发送完成后产生中断 // //配置TIM1的更新中断使能 // NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn; // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//指定抢占优先级1 // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//指定响应优先级0 // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // NVIC_Init(&NVIC_InitStructure); // }
void ADC_InjectedOffset( void ) { static uint32_t sum_U = 0; static uint32_t sum_V = 0;
if( injectedoffsecount < 128 ) { sum_U += ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1); sum_V += ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_2); injectedoffsecount++; } else { ADCSampPare.OffsetPhaseU_Curr = sum_U / 128; ADCSampPare.OffsetPhaseV_Curr = sum_V / 128; flag_injectedoffset = 1; injectedoffsecount = 0; sum_U = 0; sum_V = 0; } }
void ADC_InjectedSample( void ) { ADCSampPare.PhaseU_Curr = ( ( ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1) - ADCSampPare.OffsetPhaseU_Curr ) << 1 ); ADCSampPare.PhaseV_Curr = ( ( ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_2) - ADCSampPare.OffsetPhaseV_Curr ) << 1 ); // Q12格式左移1位,放大5倍,采样电阻0.05R = 1/5/0.05 = 4,左移2位 }
//校准作用,电流传感器的偏移值为1.65V void ADC_RegularOffset(void) // 没有PWM输出是调用 { static uint32_t sum_BUS = 0; if( regularoffsecount < 128 ) { sum_BUS += ADC_ConvertedValue[0]; regularoffsecount++; } else { ADCSampPare.OffsetBUS_Curr = sum_BUS / 128; flag_regularoffset = 1; regularoffsecount = 0; sum_BUS = 0; } }
void ADC_RegularSample( void ) // 放在PWM中断进来后,采样时间为1us左右,(7cycles) 保证在PWM中断后进来采样后为在PWM中间采集相电流 { // 把电流采集运算偏执后,左移1为,乘2倍后将电流传感器AD采集值转换IQ12格式 -4096到4096 // 此电流乘2倍与硬件差分放大电流2K/1K电阻放大2倍没有关系 // 此传感器量程,100毫欧 运算放大器2倍,硬件0到3.3等效-1.6到1.6,100mr电阻传感器量程大约±8A // 若硬件修改,按照此算法比例计算 ADCSampPare.BUS_Curr = ( ( -ADC_ConvertedValue[0] + ADCSampPare.OffsetBUS_Curr ) << 1 ) + 25; // 补偿一阶低通滤波后的小的插值25经验值 ADCSampPare.RP_speed_Voltage = ADC_ConvertedValue[1];
if( ADCSampPare.RP_speed_Voltage > 2048 ) { ADCSampPare.RP_speed_Voltage -= 2048; } else { ADCSampPare.RP_speed_Voltage = 0; } ADCSampPare.RP_speed_Voltage = ADCSampPare.RP_speed_Voltage << 1; ADCSampPare.BUS_Voltage = ADC_ConvertedValue[2]; // 一阶低通数字滤波器 公式查文献百度 历史量0.96 采集新值0.04 ADCSampPare.BUS_CurrF = _IQ10mpy( ADCSampPare.Coeff_filterK1, ADCSampPare.BUS_CurrF ) + _IQ10mpy( ADCSampPare.Coeff_filterK2, ADCSampPare.BUS_Curr );
}
void Protection_software(void) //通过母线电流值保护硬件 软件处理 3A左右为600 { if( Abs( ADCSampPare.BUS_CurrF ) > BUS_CurrProtection ) // 大约为3A { Stop_Motor(); // 关闭电机停止 logicContr.Start_order=0; } }
|