[活动] 【APM32M3514电机通用评估板评测】+ 源码分析

[复制链接]
 楼主| 穿西装的强子 发表于 2025-2-10 17:10 | 显示全部楼层 |阅读模式
经过几天的测试和使用,APM32M3514点击通用评估板已经使用的比较熟练了;
该源码除了foc和观测器代码不开源,其它的均是开源,整个控制流程与外设的配置开源给玩电驱的同学们一些参考;
先从main函数开始

  1. int main(void)
  2. {
  3.     GPIO_BSRET_T bit = Bit_RESET;
  4.     __disable_irq();                           
  5.     /*  config peripherals  */
  6.     MC_SystemClockInit();
  7.     /*  M0CP    */
  8.     M0CP_Firmware_Init();
  9.     RCM_EnableAHBPeriphReset(RCM_AHB_PERIPH_M0CP);
  10.     RCM_DisableAHBPeriphReset(RCM_AHB_PERIPH_M0CP);
  11.     RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_M0CP);
  12.     M0CP_HardInit();
  13.     *(volatile unsigned int*)(0x40024000+0x10) = 0;
  14.     /*  TIMER1      */
  15.     Drv_Pwm_Init(PWM_PERIOD,DEAD_TIME);
  16.     PWM_CompareConfig(PWM_PERIOD, PWM_PERIOD, PWM_PERIOD);
  17.     /*  ADC      */
  18.     Drv_Adc_Init();
  19.     /*  OPA      */
  20.     OPA_Init();
  21.     /*  COMP      */
  22.     COMP_Init();
  23.     /*  GPIO      */
  24.     IO_Init();
  25.         Pilot_uart_init();
  26.     /*  SYSTICK      */
  27.     Systick_Init(SystemCoreClock / 1000);
  28.     /* Initialize  motor control parameters */
  29.     Init_Parameter(&Motor_type);
  30.     /* Initialize interrupts */
  31.     Interrupt_Init();
  32.        /* Wait until ADC is ready */
  33.     while (!ADC_ReadStatusFlag(ADC_FLAG_ADRDY));
  34.     ADC_StartConversion();
  35.     WWDTInit();
  36.     __enable_irq();                             //Enable all interrupts
  37.     TMR_EnablePWMOutputs(TMR1);
  38.     while (1)
  39.     {
  40.         //Reads key from demoboard.
  41.         NewDIRKey = GPIO_ReadInputBit(GPIOC,GPIO_PIN_13); //PC13 Direction方向按键
  42.         if(NewDIRKey == BIT_RESET)
  43.         {
  44.             /*设定新方向为反转CCW*/
  45.             Motor_type.User.s8NewDir = -1;
  46.         }
  47.         else{
  48.             /*设定新方向为正转CW*/
  49.             Motor_type.User.s8NewDir = 1;
  50.         }
  51.         if(Motor_type.User.s8NewDir != Motor_type.User.s8Direction)
  52.         {
  53.             /*启动转向切换功能*/
  54.             Motor_type.User.bDirSwitchEnable = true;
  55.         }
  56.         
  57.         if(Motor_type.User.bSlowLoopFlag)
  58.         {
  59.             WWDTFeedDog();
  60.             /* Slow Loop Statemachine */
  61.             s_STATE_SLOW[eM1_MainState]();
  62.             Motor_type.User.bSlowLoopFlag =  0;
  63.         }
  64.                 if( Get_Systick_Cnt() % 300 == 0)
  65.                 {
  66.                         GPIO_WriteBitValue(GPIO_LedErr,GPIO_Pin_LedErr,bit);
  67.                         bit = !bit;
  68.                 }
  69.                 if( Get_Systick_Cnt() % 100 == 0)
  70.                 {
  71.                         //speed_rate = 20;
  72.                         speed_rpm = hall_cnt*20;
  73.                         hall_cnt = 0;
  74.                         printf("<plots,%d,%d,%d,%d>\r\n",\
  75.                                 Motor_type.Foc.s16SpdFilt,\
  76.                                 Motor_type.stc_SmoPara.s16q15_Ealpha,\
  77.                                 speed_rpm,\
  78.                                 Motor_type.Foc.stc_Idq.s16q15_Q\
  79.                         );
  80. //                        Motor_type.Foc.stc_Idq.s16q15_D,\
  81. //                        Motor_type.Foc.stc_Idq.s16q15_Q,\
  82. //                        Motor_type.Foc.stc_IdqCmd.s16q15_D,\
  83. //                        Motor_type.Foc.stc_IdqCmd.s16q15_Q);
  84.                 }
  85.     }
  86. }
main函数主要是对外设的配置初始化;
主循环是简单的按键识别反向选择、喂狗等;
主要需要看的是PWM和adc的初始化
先看pwm
  1. void  Drv_Pwm_Init(uint16_t u16_Period,uint16_t u16_DeadTime)
  2. {
  3.     TMR_TimeBase_T    TIM_TimeBaseInitStructure;
  4.     TMR_OCConfig_T    TIM_OCInitStructure;
  5.     TMR_BDTInit_T     TIM_BDTRInitStructure;
  6.   
  7.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG  | RCM_APB2_PERIPH_TMR1 );
  8.    
  9.     /* Time Base configuration ,init time1 freq*/
  10.     TIM_TimeBaseInitStructure.period            = u16_Period;  //(SYSTEM_FREQUENCY/2/8000) - 1;
  11.     TIM_TimeBaseInitStructure.div               = 0;
  12.     TIM_TimeBaseInitStructure.counterMode       = TMR_COUNTER_MODE_CENTERALIGNED2;
  13.     TIM_TimeBaseInitStructure.clockDivision     = TMR_CKD_DIV1;
  14.     TIM_TimeBaseInitStructure.repetitionCounter = 1;
  15.     TMR_ConfigTimeBase(TMR1, &TIM_TimeBaseInitStructure);

  16.     /* Automatic Output enable, Break, dead time and lock configuration*/
  17.     TIM_BDTRInitStructure.RMOS_State       = TMR_RMOS_STATE_ENABLE;//--------
  18.     TIM_BDTRInitStructure.IMOS_State       = TMR_IMOS_STATE_ENABLE;//--------
  19.     TIM_BDTRInitStructure.lockLevel        = TMR_LOCK_LEVEL_OFF;//00:锁定关闭,寄存器无写保护;01:锁定级别1,不能写入TIMx_BDTR寄存器的DTG、BKE、BKP、AOE位和TIMx_CR2寄存器的OISx/OISxN位;
  20.     TIM_BDTRInitStructure.deadTime         = u16_DeadTime;//死区时间
  21.     /**
  22.      * Brake configuration: enable brake
  23.      * Brake input polarity: active in low level   
  24.      * Auto output enable configuration: Disable MOE bit hardware control
  25.      */
  26.     TIM_BDTRInitStructure.breakState       = TMR_BREAK_STATE_ENABLE;//TMR_BREAK_STATE_ENABLE TMR_BREAK_STATE_DISABLE;
  27.     TIM_BDTRInitStructure.breakPolarity    = TMR_BREAK_POLARITY_HIGH;
  28.     TIM_BDTRInitStructure.automaticOutput  = TMR_AUTOMATIC_OUTPUT_DISABLE;
  29.     TMR_ConfigBDT(TMR1, &TIM_BDTRInitStructure);

  30.     /*pwm driver set,channel 1,2,3,4set pwm mode*/
  31.     TIM_OCInitStructure.OC_Mode         = TMR_OC_MODE_PWM2;
  32.     TIM_OCInitStructure.OC_OutputState  = TMR_OUTPUT_STATE_ENABLE;  //TMR_OUTPUT_STATE_DISABLE;
  33.     TIM_OCInitStructure.OC_OutputNState = TMR_OUTPUT_NSTATE_ENABLE; //TMR_OUTPUT_NSTATE_DISABLE;//------------
  34.     TIM_OCInitStructure.Pulse           = u16_Period;
  35.     TIM_OCInitStructure.OC_Polarity     = TMR_OC_POLARITY_HIGH;
  36.     TIM_OCInitStructure.OC_NPolarity    = TMR_OC_NPOLARITY_HIGH; //互补输出极性-------
  37.     TIM_OCInitStructure.OC_Idlestate    = TMR_OCIDLESTATE_RESET;  // TMR_OCIDLESTATE_SET; //
  38.     TIM_OCInitStructure.OC_NIdlestate   = TMR_OCNIDLESTATE_RESET; // TMR_OCNIDLESTATE_SET;//
  39.     //set OC1/OC1N
  40.     TMR_OC1Config(TMR1, &TIM_OCInitStructure);
  41.     //set oc2/oc2N
  42.     TIM_OCInitStructure.Pulse = u16_Period;
  43.     TMR_OC2Config(TMR1, &TIM_OCInitStructure);
  44.     //set OC3/OC3N
  45.     TIM_OCInitStructure.Pulse = u16_Period;
  46.     TMR_OC3Config(TMR1, &TIM_OCInitStructure);
  47.    
  48.     TIM_OCInitStructure.OC_Mode         = TMR_OC_MODE_PWM2;              //选择定时器模式:TIM脉冲宽度调制模式2
  49.     TIM_OCInitStructure.OC_OutputState  = TMR_OUTPUT_STATE_ENABLE;       //CH1比较输出使能               
  50.     TIM_OCInitStructure.OC_OutputNState = TMR_OUTPUT_NSTATE_ENABLE;      //CH1N比较输出使能       
  51.     TIM_OCInitStructure.OC_Polarity     = TMR_OC_POLARITY_HIGH;           //CH1输出极性:TIM输出比较极性高       
  52.     TIM_OCInitStructure.OC_NPolarity    = TMR_OC_NPOLARITY_HIGH;          //CH1N输出极性:TIM输出比较极性高       
  53.     TIM_OCInitStructure.OC_Idlestate    = TMR_OCIDLESTATE_RESET;         //CH1输出空闲状态:0       
  54.     TIM_OCInitStructure.OC_NIdlestate   = TMR_OCNIDLESTATE_SET;          //CH1N输出空闲状态:0       
  55.      //set OC4
  56.     TIM_OCInitStructure.Pulse = 10;
  57.     TMR_OC4Config(TMR1, &TIM_OCInitStructure);//OC4
  58.     //enable interrupt
  59.     TMR_EnableInterrupt(TMR1, TMR_INT_BRK);

  60.     TMR_EnableAUTOReload(TMR1);//TIMx_ARR寄存器被装入缓冲器
  61.     TMR_OC1PreloadConfig(TMR1,TMR_OC_PRELOAD_ENABLE);
  62.     TMR_OC2PreloadConfig(TMR1,TMR_OC_PRELOAD_ENABLE);//比较值预装载使能
  63.     TMR_OC3PreloadConfig(TMR1,TMR_OC_PRELOAD_ENABLE);
  64.     TMR_OC4PreloadConfig(TMR1,TMR_OC_PRELOAD_ENABLE);
  65.    
  66.     TMR_EnableAUTOReload(TMR1);
  67.    
  68.     TMR_Enable(TMR1);
  69.     TMR1->REPCNT = 1;
  70.     /* Main Output Enable */
  71.     TMR_EnablePWMOutputs(TMR1);
  72.    
  73.     /*  GPIO config     */
  74.     GPIO_Config_T   GPIO_InitStructure;

  75.     GPIO_InitStructure.pin      =   GPIO_PIN_PWM_UH_Mobile;
  76.     GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
  77.     GPIO_InitStructure.mode     =   GPIO_MODE_AF;
  78.     GPIO_InitStructure.pupd     =   GPIO_PUPD_PD;
  79.     GPIO_Config(GPIO_PWM_UH_Mobile, &GPIO_InitStructure);

  80.     GPIO_InitStructure.pin      =   GPIO_PIN_PWM_VH_Mobile;
  81.     GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
  82.     GPIO_InitStructure.mode     =   GPIO_MODE_AF;
  83.     GPIO_InitStructure.pupd     =   GPIO_PUPD_PD;
  84.     GPIO_Config(GPIO_PWM_VH_Mobile, &GPIO_InitStructure);

  85.     GPIO_InitStructure.pin      =   GPIO_PIN_PWM_WH_Mobile;
  86.     GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
  87.     GPIO_InitStructure.mode     =   GPIO_MODE_AF;
  88.     GPIO_InitStructure.pupd     =   GPIO_PUPD_PD;
  89.     GPIO_Config(GPIO_PWM_WH_Mobile, &GPIO_InitStructure);

  90.     GPIO_InitStructure.pin      =   GPIO_PIN_PWM_UL_Mobile;
  91.     GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
  92.     GPIO_InitStructure.mode     =   GPIO_MODE_AF;
  93.     GPIO_InitStructure.pupd     =   GPIO_PUPD_PD;
  94.     GPIO_Config(GPIO_PWM_UL_Mobile, &GPIO_InitStructure);

  95.     GPIO_InitStructure.pin      =   GPIO_PIN_PWM_VL_Mobile;
  96.     GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
  97.     GPIO_InitStructure.mode     =   GPIO_MODE_AF;
  98.     GPIO_InitStructure.pupd     =   GPIO_PUPD_PD;
  99.     GPIO_Config(GPIO_PWM_VL_Mobile, &GPIO_InitStructure);

  100.     GPIO_InitStructure.pin      =   GPIO_PIN_PWM_WL_Mobile;
  101.     GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
  102.     GPIO_InitStructure.mode     =   GPIO_MODE_AF;
  103.     GPIO_InitStructure.pupd     =   GPIO_PUPD_PD;
  104.     GPIO_Config(GPIO_PWM_WL_Mobile, &GPIO_InitStructure);

  105.     GPIO_InitStructure.pin      =   GPIO_PIN_PWM_Break_Mobile;
  106.     GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
  107.     GPIO_InitStructure.mode     =   GPIO_MODE_AF;
  108.     GPIO_InitStructure.pupd     =   GPIO_PUPD_PD;
  109.     GPIO_Config(GPIO_PWM_Break_Mobile, &GPIO_InitStructure);
  110.     //复用映射,需参考文档
  111.     GPIO_ConfigPinAF(GPIO_PWM_UH_Mobile,GPIO_PIN_SOURCE_PWM_UH_Mobile,GPIO_AF_PIN2);
  112.     GPIO_ConfigPinAF(GPIO_PWM_VH_Mobile,GPIO_PIN_SOURCE_PWM_VH_Mobile,GPIO_AF_PIN2);
  113.     GPIO_ConfigPinAF(GPIO_PWM_WH_Mobile,GPIO_PIN_SOURCE_PWM_WH_Mobile,GPIO_AF_PIN2);
  114.     GPIO_ConfigPinAF(GPIO_PWM_UL_Mobile,GPIO_PIN_SOURCE_PWM_UL_Mobile,GPIO_AF_PIN2);
  115.     GPIO_ConfigPinAF(GPIO_PWM_VL_Mobile,GPIO_PIN_SOURCE_PWM_VL_Mobile,GPIO_AF_PIN2);
  116.     GPIO_ConfigPinAF(GPIO_PWM_WL_Mobile,GPIO_PIN_SOURCE_PWM_WL_Mobile,GPIO_AF_PIN2);
  117.     GPIO_ConfigPinAF(GPIO_PWM_Break_Mobile,GPIO_PIN_SOURCE_PWM_Break_Mobile,GPIO_AF_PIN3);
  118. }
pwm使用的是timr1,频率为16K,死区时间为1us。
使用高级定时器,产生互补pwm。
其次是ADC的配置:
  1. void Drv_Adc_Init(void)
  2. {
  3.     ADC_Config_T   ADC_InitStructure;
  4.     DMA_Config_T   DMA_InitStructure;
  5.     DMA_InitStructure.peripheralAddress  = (uint32_t)&(ADC->DATA);//ADC地址
  6.     DMA_InitStructure.memoryAddress      = (uint32_t)&ADC_ConvertedValue[0]; //内存地址
  7.     DMA_InitStructure.direction          = DMA_DIR_PERIPHERAL; //方向(从外设到内存)
  8.     DMA_InitStructure.bufferSize         = TOTAL_CHANNEL;//TOTAL_CHANNEL; //传输内容的大小---传输次数
  9.     DMA_InitStructure.peripheralInc      = DMA_PERIPHERAL_INC_DISABLE; //外设地址固定
  10.     DMA_InitStructure.memoryInc          = DMA_MEMORY_INC_ENABLE;//DMA_MEMORY_INC_ENABLE; //内存地址固定  
  11.     DMA_InitStructure.peripheralDataSize = DMA_PERIPHERAL_DATASIZE_HALFWORD ; //外设数据单位
  12.     DMA_InitStructure.memoryDataSize     = DMA_MEMORY_DATASIZE_HALFWORD ;    //内存数据单位
  13.     DMA_InitStructure.circular           = DMA_CIRCULAR_ENABLE  ; //DMA模式:循环传输
  14.     DMA_InitStructure.priority           = DMA_PRIORITY_LEVEL_VERYHIGH ; //优先级:高
  15.     DMA_InitStructure.memoryTomemory     = DMA_M2M_DISABLE;   //禁止内存到内存的传输
  16.     ADC_Reset();
  17.     DMA_Config(DMA_CHANNEL_1, &DMA_InitStructure);  //配置DMA的1通道
  18.     DMA_Enable(DMA_CHANNEL_1);
  19.     ADC_ClockMode(ADC_CLOCK_MODE_ASYNCLK);//48M/4=12mADC_CLOCK_MODE_SYNCLKDIV4   
  20.     ADC_ConfigStructInit(&ADC_InitStructure);
  21.     ADC_InitStructure.convMode    = ADC_CONVERSION_SINGLE;
  22.     ADC_InitStructure.scanDir     = ADC_SCAN_DIR_UPWARD;
  23.     ADC_InitStructure.extTrigConv1 = ADC_EXT_TRIG_CONV_TRG1;  //  timer1 CC4
  24.     ADC_InitStructure.extTrigEdge1 = ADC_EXT_TRIG_EDGE_RISING;
  25.     ADC_InitStructure.dataAlign   = ADC_DATA_ALIGN_RIGHT;
  26.     ADC_InitStructure.resolution  = ADC_RESOLUTION_12B;   
  27.     ADC_Config(&ADC_InitStructure);
  28.     /*ADC_CHANNEL_2 :PA4 IV;ADC_CHANNEL_8:PB0 IU;ADC_CHANNEL_6:PA6 Vbus;ADC_CHANNEL_7:PA7 Handle;ADC_CHANNEL_12:PB10 Ibus*/
  29.     ADC_ConfigChannel(ADC_CHANNEL_2 | ADC_CHANNEL_8 | ADC_CHANNEL_6 | ADC_CHANNEL_7| ADC_CHANNEL_12 ,ADC_SAMPLE_TIME_1_5);
  30.     ADC->CFG1_B.OVRMAG = 1;   
  31.     ADC_EnableInterrupt(ADC_INT_CS);
  32. //=========================ADC中断使用=================================================
  33.     NVIC_EnableIRQ(ADC_COMP_IRQn);
  34.     NVIC_SetPriority(ADC_COMP_IRQn,0);  
  35.     ADC_DMARequestMode(ADC_DMA_MODE_CIRCULAR);
  36.     ADC_EnableDMA();
  37.     ADC_Enable();  
  38.     ADC_StartConversion();//必需要启动一下
  39.    
  40.     /*  Config IO   */
  41.     GPIO_Config_T   GPIO_InitStructure;

  42.     GPIO_InitStructure.pin      =   GPIO_Pin_ADC_VDC;
  43.     GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
  44.     GPIO_InitStructure.mode     =   GPIO_MODE_AN;
  45.     GPIO_InitStructure.pupd     =   GPIO_PUPD_NO;
  46.     GPIO_Config(GPIO_ADC_VDC, &GPIO_InitStructure);
  47.    
  48.     GPIO_InitStructure.pin      =   GPIO_Pin_ADC_Handle;
  49.     GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
  50.     GPIO_InitStructure.mode     =   GPIO_MODE_AN;
  51.     GPIO_InitStructure.pupd     =   GPIO_PUPD_NO;
  52.     GPIO_Config(GPIO_ADC_Handle, &GPIO_InitStructure);
  53.    
  54.     GPIO_InitStructure.pin      =   GPIO_Pin_ADC_IU;
  55.     GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
  56.     GPIO_InitStructure.mode     =   GPIO_MODE_AN;
  57.     GPIO_InitStructure.pupd     =   GPIO_PUPD_NO;
  58.     GPIO_Config(GPIO_ADC_IU, &GPIO_InitStructure);
  59.    
  60.     GPIO_InitStructure.pin      =   GPIO_Pin_ADC_IV;
  61.     GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
  62.     GPIO_InitStructure.mode     =   GPIO_MODE_AN;
  63.     GPIO_InitStructure.pupd     =   GPIO_PUPD_NO;
  64.     GPIO_Config(GPIO_ADC_IV, &GPIO_InitStructure);
  65.    
  66.     GPIO_InitStructure.pin      =   GPIO_Pin_ADC_IBUS;
  67.     GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
  68.     GPIO_InitStructure.mode     =   GPIO_MODE_AN;
  69.     GPIO_InitStructure.pupd     =   GPIO_PUPD_NO;
  70.     GPIO_Config(GPIO_ADC_IBUS, &GPIO_InitStructure);
  71. //    GPIO_InitStructure.pin      =   GPIO_Pin_ADC_VOT;
  72. //    GPIO_InitStructure.speed    =   GPIO_SPEED_50MHz;
  73. //    GPIO_InitStructure.mode     =   GPIO_MODE_AN;
  74. //    GPIO_InitStructure.pupd     =   GPIO_PUPD_NO;
  75. //    GPIO_Config(GPIO_ADC_VOT, &GPIO_InitStructure);
  76. }
ADC配置为DMA模式,使用TIMER1的CC4的上升沿进行触发,也就是说,TIMER1的通道4,每产生一个PWM的上升沿,就会检测一次ADC的数据;
为什么使用通道4?
因为TIMER1的通道1~3要控制三相桥,通道4空余的作为一个触发源,并不会真正的产生一个PWM信号;
会在ADC的中断内进行数据的读取;

  1. void ADC_COMP_IRQHandler(void)
  2. {   
  3.     ADC->STS =  ADC->STS;//Clear interrupt flag bit
  4.     static uint8_t u8ADCTimeCnt = 0;
  5.     static uint32_t u32IaSum = 0;
  6.     static uint32_t u32IbSum = 0;
  7.     static uint16_t u16Cnt = 0;
  8.    
  9.     if(u16Cnt <= 127)
  10.     {
  11.         u16Cnt++;
  12.         u32IbSum += (int16_t)ADC_GetValue(CURR_CHANNEL_V);
  13.         u32IaSum += (int16_t)ADC_GetValue(CURR_CHANNEL_U);
  14.     }
  15.     else if(u16Cnt == 128)
  16.     {
  17.         u16Cnt++;
  18.         u32IbSum = u32IbSum>>7;
  19.         u32IaSum = u32IaSum>>7;
  20.         Motor_type.Foc.stc_IuvwOffset.s16q15_V = u32IbSum << 3;
  21.         Motor_type.Foc.stc_IuvwOffset.s16q15_U = u32IaSum << 3;
  22.         u32IbSum = 0;
  23.         u32IaSum = 0;
  24.         Motor_type.Foc.s16q15IbusOffset = (int16_t)ADC_GetValue(IBUS_CHANNEL) << 3;
  25.     }
  26.     else
  27.     {
  28.         /*采样*/
  29.         Get_ADC_Result(&Motor_type);
  30.         /* Fast Loop Statemachine */
  31.         s_STATE_FAST[eM1_MainState]();
  32.         if(++u8ADCTimeCnt >= Motor_type.User.u16SlowLoopDiv)   //For slow loop state machine
  33.         {
  34.           u8ADCTimeCnt = 0;
  35.           Motor_type.User.bSlowLoopFlag = 1;
  36.         }
  37.     }
  38. }
在ADC的中断内进行foc算法的控制;
使用Get_ADC_Result(&Motor_type);先获取adc值;
通过s_STATE_FAST[eM1_MainState]();进行foc运算;

foc控制:
  1. static void M1_RunSpinFast(void)
  2. {
  3.     Motor_type.Foc.s16CmdTheta += Motor_type.stc_SmoPara.s16q15SpdObs*Motor_type.Foc.s16SpdToTheta >> 15;
  4.     Motor_type.Foc.stc_SinCos = sin_cos_cal(Motor_type.Foc.s16CmdTheta);
  5.     /*Current loop*/
  6.     current_ctrl(&Motor_type);
  7.     Motor_type.Foc.u16q15Vdq_sqrt = isqrt32((uint32_t)(Motor_type.Foc.stc_Vdq.s16q15_D * Motor_type.Foc.stc_Vdq.s16q15_D + Motor_type.Foc.stc_Vdq.s16q15_Q * Motor_type.Foc.stc_Vdq.s16q15_Q));

  8.     /*  observation     */
  9.     Motor_type.stc_SmoPara.s16q15_Ialpha = Motor_type.Foc.stc_Iab.s16q15_A;
  10.     Motor_type.stc_SmoPara.s16q15_Ibeta = Motor_type.Foc.stc_Iab.s16q15_B;
  11.     Motor_type.stc_SmoPara.s16q15_Ualpha = Motor_type.Foc.stc_Vab.s16q15_A;
  12.     Motor_type.stc_SmoPara.s16q15_Ubeta = Motor_type.Foc.stc_Vab.s16q15_B;
  13.     smo_cal(&Motor_type.stc_SmoPara);
  14.        
  15.     /*  PLL     */
  16.     Motor_type.stc_PiPll.s16_Error = ((-Motor_type.stc_SmoPara.s16q15_Ealpha*Motor_type.Foc.stc_SinCos.s16q15_Cos)
  17.                         - (Motor_type.stc_SmoPara.s16q15_Ebeta*Motor_type.Foc.stc_SinCos.s16q15_Sin)) >> 15;
  18.     anti_pi(&Motor_type.stc_PiPll);
  19.     Motor_type.stc_SmoPara.s16q15SpdObs = Motor_type.stc_PiPll.s32_Out;
  20.     /*  svpwm   */
  21.     Motor_type.Foc.stc_SvpwmPara.s16q15_Vbus = Motor_type.Foc.s16Vbus;
  22.     Motor_type.Foc.stc_SvpwmPara.s16q15_Valpha = Motor_type.Foc.stc_Vab.s16q15_A;
  23.     Motor_type.Foc.stc_SvpwmPara.s16q15_Vbeta = Motor_type.Foc.stc_Vab.s16q15_B;
  24.     svpwm7_cal(&Motor_type.Foc.stc_SvpwmPara);
  25.     PWM_Update(&Motor_type);
  26. }
先获取电角度,转换为正弦值,在current_ctrl函数进行clarke变化,再进行park变化,对d轴电流进行pi计算,再对q轴电流进行pi计算,计算除vq和vd值,进行反park变化;
  1. void current_ctrl(Motor_TypeDef *Motor)
  2. {
  3.     clarke(&Motor->Foc.stc_Iuvw, &Motor->Foc.stc_Iab);
  4.     park(&Motor->Foc.stc_Iab,&Motor->Foc.stc_SinCos, &Motor->Foc.stc_Idq);
  5.     /*      PI for Id       */
  6.     Motor->stc_IdPi.s16_Error = Motor->Foc.stc_IdqCmd.s16q15_D-Motor->Foc.stc_Idq.s16q15_D;
  7.     anti_pi(&Motor->stc_IdPi);

  8.     Motor->Foc.stc_Vdq.s16q15_D = Motor->stc_IdPi.s32_Out;
  9.     /*      limit the Vq    */
  10.     uint32_t u32_Temp;
  11.     int16_t s16q15Vmax = Motor->Foc.s16Vbus * 18918 >> 15;     // Vamx=Vbus/sqrt(3)
  12.     u32_Temp = s16q15Vmax*s16q15Vmax
  13.                - Motor->Foc.stc_Vdq.s16q15_D*Motor->Foc.stc_Vdq.s16q15_D;
  14.     Motor->stc_IqPi.s32_Umax = isqrt32(u32_Temp);
  15.     Motor->stc_IqPi.s32_Umin = -Motor->stc_IqPi.s32_Umax;
  16.     /*      PI for Iq       */
  17.     Motor->stc_IqPi.s16_Error = Motor->Foc.stc_IdqCmd.s16q15_Q-Motor->Foc.stc_Idq.s16q15_Q;
  18.     anti_pi(&Motor->stc_IqPi);
  19.     Motor->Foc.stc_Vdq.s16q15_Q = Motor->stc_IqPi.s32_Out;
  20.    
  21.     /*  InvPark     */
  22.     inv_park(&Motor->Foc.stc_Vdq, &Motor->Foc.stc_SinCos, &Motor->Foc.stc_Vab);
  23. }
再将换算除的vd,vq,iq,id赋值到smo滑模观测器参数内进行电角度观测;
使用pi对pll进行整定,能换算出速度值;
最后使用svpwm7_cal(&Motor_type.Foc.stc_SvpwmPara);对不同的角度区域进行换算,得到SVPWM信号,使用PWM_Update(&Motor_type);更新PWM值进行输出;
  1. void PWM_Update(Motor_TypeDef *Motor)
  2. {
  3.     if(Motor->User.s8Direction != -1)
  4.     {
  5.         Motor->PWMx.Timer->CC1 = (32768-Motor->Foc.stc_SvpwmPara.u16q15_DutyU)*PWM_PERIOD >> 15;
  6.         Motor->PWMx.Timer->CC2 = (32768-Motor->Foc.stc_SvpwmPara.u16q15_DutyV)*PWM_PERIOD >> 15;
  7.     }
  8.     else
  9.     {
  10.         Motor->PWMx.Timer->CC1 = (32768-Motor->Foc.stc_SvpwmPara.u16q15_DutyV)*PWM_PERIOD >> 15;
  11.         Motor->PWMx.Timer->CC2 = (32768-Motor->Foc.stc_SvpwmPara.u16q15_DutyU)*PWM_PERIOD >> 15;
  12.     }
  13.     Motor->PWMx.Timer->CC3 = (32768-Motor->Foc.stc_SvpwmPara.u16q15_DutyW)*PWM_PERIOD >> 15;
  14. }



这个控制是运行快速旋转的控制方法,还有慢速旋转的控制方法,可自行了解学习;

以上是源码的控制流程
可怜的小弗朗士 发表于 2025-2-14 10:27 | 显示全部楼层
这个代码量好大
您需要登录后才可以回帖 登录 | 注册

本版积分规则

62

主题

259

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部

62

主题

259

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部