STM32 ADC規則組和注入組配置方法


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM