分享

STM32 ADC规则组和注入组配置方法

 得思 2020-03-13

//############################################################
//近期在用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;
}
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多