📄 stm32f10x_svpwm_1shunt.c
字号:
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name : STM32x_svpwm_1shunt.c
* Author : IMS Systems Lab
* Date First Issued : Mar/08
* Description : 1 shunt resistor current reading module
********************************************************************************
* History:
* 29/05/08 v2.0
* 02/07/08 v2.0.1
* 03/07/08 v2.0.2
* 11/07/08 v2.0.3
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* THIS SOURCE CODE IS PROTECTED BY A LICENSE.
* FOR MORE INFORMATION PLEASE CAREFULLY READ THE LICENSE AGREEMENT FILE LOCATED
* IN THE ROOT DIRECTORY OF THIS FIRMWARE PACKAGE.
*******************************************************************************/
#include "STM32F10x_MCconf.h"
#ifdef SINGLE_SHUNT
/* Includes-------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "stm32f10x_svpwm_1shunt.h"
#include "MC_Globals.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define NB_CONVERSIONS 16
#define SQRT_3 1.732051
#define T (PWM_PERIOD * 4)
#define T_SQRT3 (u16)(T * SQRT_3)
#define SECTOR_1 (u32)1
#define SECTOR_2 (u32)2
#define SECTOR_3 (u32)3
#define SECTOR_4 (u32)4
#define SECTOR_5 (u32)5
#define SECTOR_6 (u32)6
#define REGULAR ((u8)0)
#define BOUNDARY_1 ((u8)1) // Two small, one big
#define BOUNDARY_2 ((u8)2) // Two big, one small
#define BOUNDARY_3 ((u8)3) // Three equal
#define PHASE_B_ADC_CHANNEL ADC_Channel_15 //B 相电流检测使用AD15通道,PC5脚。
#define ADC_PRE_EMPTION_PRIORITY 1
#define ADC_SUB_PRIORITY 0
#define BRK_PRE_EMPTION_PRIORITY 0
#define BRK_SUB_PRIORITY 0
#define TIM1_UP_PRE_EMPTION_PRIORITY 0
#define TIM1_UP_SUB_PRIORITY 0
#ifdef IR_2101S
#define LOW_SIDE_POLARITY TIM_OCNIdleState_Reset //停车不锁转子,转子可以自由转动
//#define LOW_SIDE_POLARITY TIM_OCNIdleState_Set //停车锁定转子,绕组刹车
#endif
#ifdef IR_2103S
#define LOW_SIDE_POLARITY TIM_OCNIdleState_Set //停车不锁转子,转子可以自由转动
//#define LOW_SIDE_POLARITY TIM_OCNIdleState_Reset //停车锁定转子,绕组刹车
#endif
// Direct address of the registers used by DMA
#define TIM1_CCR1_Address 0x40012C34
#define TIM1_CCR2_Address 0x40012C38
#define TIM1_CCR3_Address 0x40012C3C
#define TIM1_CCR4_Address 0x40012C40
#define TIM1_DMAR_Address 0x40012C4C
#define CCMR1_OC1PE_BB 0x4225830C // TIMR1_CCMR1_OC1PE 的BITBAND位地址。
#define CCMR1_OC2PE_BB 0x4225832C // TIMR1_CCMR1_OC2PE 的BITBAND位地址。
#define CCMR2_OC3PE_BB 0x4225838C // TIMR1_CCMR1_OC3PE 的BITBAND位地址。
#define CH1NORMAL 0x0060
#define CH2NORMAL 0x6000
#define CH3NORMAL 0x0060
#define CH4NORMAL 0x7000
#define CH1TOGGLE 0x0030
#define CH2TOGGLE 0x3000
#define CH3TOGGLE 0x0030
#define CH4TOGGLE 0x3000
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
u8 bSector;
u16 hPhaseOffset=0;
u8 bInverted_pwm=INVERT_NONE,bInverted_pwm_new=INVERT_NONE;
u8 bStatorFluxPos, bStatorFluxPosOld;
DUTYVALUESTYPE dvDutyValues;
CURRENTSAMPLEDTYPE csCurrentSampled;
u8 bError=0;
s16 hCurrAOld,hCurrBOld,hCurrCOld;
s16 hDeltaA,hDeltaB,hDeltaC;
u8 bReadDelta;
u16 hPreloadCCMR1Disable;
u16 hPreloadCCMR1Set;
u16 hPreloadCCMR2Disable;
u16 hPreloadCCMR2Set;
u16 hCCDmaBuffCh1[4];
u16 hCCDmaBuffCh2[4];
u16 hCCDmaBuffCh3[4];
u16 hCCDmaBuffCh4[4];
u16 hCCRBuff[4];
u8 bStBd3 = 0;
u8 bDistEnab = 0;
/* Private function prototypes -----------------------------------------------*/
void SVPWM_InjectedConvConfig(void);
/*******************************************************************************
* Function Name : SVPWM_1ShuntInit
* Description : It initializes PWM and ADC peripherals
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SVPWM_1ShuntInit(void)
{
ADC_InitTypeDef ADC_InitStructure;
TIM_TimeBaseInitTypeDef TIM1_TimeBaseStructure;
TIM_OCInitTypeDef TIM1_OCInitStructure;
TIM_BDTRInitTypeDef TIM1_BDTRInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
/* ADC1, ADC2, DMA, GPIO, TIM1 clocks enabling -----------------------------*/
/* ADCCLK = PCLK2/6 */
RCC_ADCCLKConfig(RCC_PCLK2_Div6); // ADCCLK = 12MHZ
/* Enable DMA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* Enable GPIOA, GPIOC, GPIOE, AFIO clocks */
// 这里忘了设置PB口的时钟使能,造成不用JLINK时程序不正常。原来使用了PE口。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOE, ENABLE);
/* Enable ADC1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* Enable ADC2 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
/* Enable TIM1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/* ADC1, ADC2, PWM pins configurations -------------------------------------*/
GPIO_StructInit(&GPIO_InitStructure);
/****** Configure PC.00,01,2,3,4,5 (ADC Channels [10..15]) as analog input ****/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_StructInit(&GPIO_InitStructure);
/****** Configure PA.06,07(ADC Channels [6..7]) as analog input ****/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_StructInit(&GPIO_InitStructure);
/****** Configure PB.00,01(ADC Channels [8..9]) as analog input ****/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// After reset value of DMA buffers
hCCDmaBuffCh1[0] = PWM_PERIOD-HTMIN;
hCCDmaBuffCh1[1] = PWM_PERIOD-HTMIN;
hCCDmaBuffCh1[2] = PWM_PERIOD >> 1;
hCCDmaBuffCh1[3] = PWM_PERIOD >> 1;
;
hCCDmaBuffCh2[0] = PWM_PERIOD-HTMIN;
hCCDmaBuffCh2[1] = PWM_PERIOD-HTMIN;
hCCDmaBuffCh2[2] = PWM_PERIOD >> 1;
hCCDmaBuffCh2[3] = PWM_PERIOD >> 1;
hCCDmaBuffCh3[0] = PWM_PERIOD-HTMIN;
hCCDmaBuffCh3[1] = PWM_PERIOD-HTMIN;
hCCDmaBuffCh3[2] = PWM_PERIOD >> 1;
hCCDmaBuffCh3[3] = PWM_PERIOD >> 1;
// Default Update DMA buffer Ch 1,2,3,4 after reset
hCCRBuff[0] = PWM_PERIOD >> 1;
hCCRBuff[1] = PWM_PERIOD >> 1;
hCCRBuff[2] = PWM_PERIOD >> 1;
hCCRBuff[3] = (PWM_PERIOD >> 1) - TBEFORE;
// After reset value of dvDutyValues
dvDutyValues.hTimePhA = PWM_PERIOD >> 1;
dvDutyValues.hTimePhB = PWM_PERIOD >> 1;
dvDutyValues.hTimePhC = PWM_PERIOD >> 1;
/* TIM1 Channel 1 toggle mode */
/* DMA Channel2 configuration ----------------------------------------------*/
DMA_DeInit(DMA1_Channel2);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)TIM1_CCR1_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(hCCDmaBuffCh1);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; // 外设作为数据传输的目的地
DMA_InitStructure.DMA_BufferSize = 4;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址寄存器递增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 数据宽度为 16 位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 工作在循环缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; // DMA通道 x拥有高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // DMA通道 x没有设置为内存到内存传输
DMA_Init(DMA1_Channel2, &DMA_InitStructure);
/* Enable DMA Channel2 */
//DMA_Cmd(DMA_Channel2, ENABLE);
DMA_Cmd(DMA1_Channel2, DISABLE);
/* TIM1 Channel 2 toggle mode */
/* DMA Channel3 configuration ----------------------------------------------*/
DMA_DeInit(DMA1_Channel3);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)TIM1_CCR2_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(hCCDmaBuffCh2);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 4;
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;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel3, &DMA_InitStructure);
/* Enable DMA Channel3 */
//DMA_Cmd(DMA_Channel3, ENABLE);
DMA_Cmd(DMA1_Channel3, DISABLE);
/* TIM1 Channel 3 toggle mode */
/* DMA Channel6 configuration ----------------------------------------------*/
DMA_DeInit(DMA1_Channel6);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)TIM1_CCR3_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(hCCDmaBuffCh3);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 4;
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;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel6, &DMA_InitStructure);
/* Enable DMA Channel6 */
DMA_Cmd(DMA1_Channel6, DISABLE);
/* TIM1 Channel 4 PWM2 or toggle mode */
/* DMA channel4 configuration */
DMA_DeInit(DMA1_Channel4);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)TIM1_CCR4_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(hCCDmaBuffCh4);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 2;
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;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel4, ENABLE);
/* DMA TIM1 update configuration */
DMA_DeInit(DMA1_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)TIM1_DMAR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(hCCRBuff);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 4;
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;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel5, ENABLE);
/* TIM1 Peripheral Configuration -------------------------------------------*/
/* TIM1 Registers reset */
TIM_DeInit(TIM1);
TIM_TimeBaseStructInit(&TIM1_TimeBaseStructure);
/* Time Base configuration */
TIM1_TimeBaseStructure.TIM_Prescaler = 0x0; //TIM1_Prescaler设置了用来作为 TIM1时钟频率除数的预分频值。
//它的取值必须在 0x0000 和0xFFFF 之间
TIM1_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned3; //TIM1 中央对齐模式 3 在计数器向上和向下计数都触发中断
TIM1_TimeBaseStructure.TIM_Period = PWM_PERIOD; //参考TIM1_CR1控制寄存器的5-6位
TIM1_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV2; //为了设置死区时间和数字滤波
// Initial condition is REP=0 to set the UPDATE only on the underflow
TIM1_TimeBaseStructure.TIM_RepetitionCounter = REP_RATE;
TIM_TimeBaseInit(TIM1, &TIM1_TimeBaseStructure);
//==============================================================================
// 设置TIM1_CH1\CH2\CH3的工作状态,使用IR2103或者IR2101应该设定不同的
// 有效边沿。
TIM_OCStructInit(&TIM1_OCInitStructure);
/* Channel 1, 2,3 in PWM mode */
TIM1_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // TIM1 脉冲宽度调制模式 1
// 和PWM模式2正好相反,具体参考TIM1_CCMR1
// 寄存器的4-6位。
TIM1_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 使能输出比较状态
TIM1_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //使能输出比较 N状态
TIM1_OCInitStructure.TIM_Pulse = PWM_PERIOD >> 1; // 50%占空比
TIM1_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // TIM1 输出比较极性高
//设置使用IR2101S或者IR2103S
#ifdef IR_2101S
TIM1_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; //IR2101S
#endif
#ifdef IR_2103S
TIM1_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; //IR2103S
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -