4668 views|4 replies

1412

Posts

3

Resources
The OP
 

[Application development based on NUCLEO-F746ZG motor] 7. Program framework - two important interrupts [Copy link]

The previous post [Development and application based on NUCLEO-F746ZG motor] 6. The program framework mentioned that after the system is initialized, it enters the main loop. There is no task execution in the main function, and all tasks are in interrupts. There are mainly two interrupts: Systick interrupt and ADC interrupt. Systick interrupt executes safety tasks and medium frequency tasks, and ADC interrupt mainly executes high frequency tasks. This post will introduce in detail:

1. Systick interruption

Systick system timer is a peripheral in CM7 core, embedded in NVIC. System timer is a 24-bit down-counting counter, and the time for each count of the counter is 1/SYSCLK. When the value of the reload value register decreases to 0, the system timer generates an interrupt, and the cycle repeats. Because SysTick is a peripheral of CM7 core, all microcontrollers based on CM7 core have this system timer, so that the software can be easily ported in CM7 microcontrollers. System timer is dedicated to real-time operating system, used to generate time base and maintain the heartbeat of operating system.

In this program, the Systick interrupt defaults to a 1ms timing, in which the safety task is executed in this interrupt, and the intermediate frequency task (speed loop) is also executed in this interrupt.

Systick interrupt initialization code is as follows:

__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  /* Configure the SysTick to have interrupt in 1ms time basis*/
  if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
  {
    return HAL_ERROR;
  }

  /* Configure the SysTick IRQ priority */
  if (TickPriority < (1UL << __NVIC_PRIO_BITS))
  {
    HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
    uwTickPrio = TickPriority;
  }
  else
  {
    return HAL_ERROR;
  }

  /* Return function status */
  return HAL_OK;
}

Interrupt function:

void SysTick_Handler(void)
{
    MC_RunMotorControlTasks();
}

In the MC_RunMotorControlTasks() function, the safety task and the intermediate frequency task are executed:

__weak void MC_RunMotorControlTasks(void)
{
  if ( bMCBootCompleted ) {
    /* ** Medium Frequency Tasks ** */ 
    MC_Scheduler(); //中频任务

    /* Safety task is run after Medium Frequency task so that
     * it can overcome actions they initiated if needed. */
    TSK_SafetyTask(); //安全任务

    /* ** User Interface Task ** */
    UI_Scheduler();  //用户界面任务
  }
}

2. ADC interrupt

ADC interrupt completes high frequency task, ADC sampling starts triggered by TIM1 hardware. FOC coordinate transformation, SVPWM execution and PWM duty cycle adjustment output of TIM1 are executed in the interrupt.

This program uses ADC1 to collect current, bus voltage, and temperature. The main process is as follows:

ADC1 initialization code is as follows:

static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_InjectionConfTypeDef sConfigInjected = {0};
  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //ADC1时钟4分频
  hadc1.Init.Resolution = ADC_RESOLUTION_12B; //分辨率为12位
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; //扫描模式开启
  hadc1.Init.ContinuousConvMode = DISABLE; //连续采样模式关闭
  hadc1.Init.DiscontinuousConvMode = DISABLE;//非连续采样模式关闭
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //禁止触发检测,使用软件触发
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发
  hadc1.Init.DataAlign = ADC_DATAALIGN_LEFT; //数据左对齐
  hadc1.Init.NbrOfConversion = 2; //配置位2通道
  hadc1.Init.DMAContinuousRequests = DISABLE; //关闭DMA传输数据
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;//使能EOC标志位
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time
  */
  sConfigInjected.InjectedChannel = ADC_CHANNEL_0; //ADC1通道0
  sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
  sConfigInjected.InjectedNbrOfConversion = 2;
  sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_15CYCLES;
  sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONVEDGE_RISING;
  sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJECCONV_T1_CC4;
  sConfigInjected.AutoInjectedConv = DISABLE;
  sConfigInjected.InjectedDiscontinuousConvMode = ENABLE;
  sConfigInjected.InjectedOffset = 0;
  if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time
  */
  sConfigInjected.InjectedChannel = ADC_CHANNEL_11;
  sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;
  if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES;
  sConfig.Offset = 0;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_12;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  sConfig.Offset = 0;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

ADC interrupt function:

void ADC_IRQHandler(void)
{
  /* USER CODE BEGIN ADC_IRQn 0 */

  /* USER CODE END ADC_IRQn 0 */
  if ( LL_ADC_IsActiveFlag_JEOS( ADC1 ) )//检查ADC转化标志
  {
    LL_ADC_ClearFlag_JEOS( ADC1 );//清除标志
  }

  // Highfrequency task Single or M1
  UI_DACUpdate(TSK_HighFrequencyTask()); //高频任务
  /* USER CODE BEGIN ADC_IRQn 1 */

  /* USER CODE END ADC_IRQn 1 */
}

As can be seen from the program, there is only one task in ADC, the high-frequency task. Why is the high-frequency task placed here? Because ADC needs to collect the current and voltage values in a timely and accurate manner, give them to FOC for calculation, and then convert the calculated values into output waveforms through timer TIM1 to make the motor run.

Latest reply

Very good, thank you for sharing, I have learned a lot, thumbs up   Details Published on 2023-11-13 14:27
Personal signature

没有什么不可以,我就是我,不一样的烟火! 

 
 

6547

Posts

0

Resources
2
 

The OP has explained the Systick interrupt and ADC interrupt very clearly.

Comments

Thank you, I am also sharing while learning.  Details Published on 2021-9-23 09:23
Thank you, I am also sharing while learning.  Details Published on 2021-9-23 09:23
 
 
 

1412

Posts

3

Resources
3
 
Jacktang posted on 2021-9-23 07:09 The OP explained the Systick interrupt and ADC interrupt very clearly

Thank you, I am also sharing while learning.

Personal signature

没有什么不可以,我就是我,不一样的烟火! 

 
 
 

1412

Posts

3

Resources
4
 
Jacktang posted on 2021-9-23 07:09 The OP explained the Systick interrupt and ADC interrupt very clearly

If there is anything wrong, please correct it immediately.

Personal signature

没有什么不可以,我就是我,不一样的烟火! 

 
 
 

25

Posts

1

Resources
5
 

Very good, thank you for sharing, I have learned a lot, thumbs up

 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list