992|3

1011

帖子

3

资源

版主

【基于NUCLEO-F746ZG电机开发应用】7.程序框架-两个重要中断 [复制链接]

      上个帖子【基于NUCLEO-F746ZG电机开发应用】6.程序框架中说到系统在初始化完成后,进入到主循环中,主函数中没有任何任务执行,所有的任务都在中断中。主要在两个中断中:Systick中断和ADC中断。Systick中断执行安全任务和中频任务,ADC中断主要执行高频任务。本贴将详细介绍一下:

1.Systick中断

      Systick系统定时器是属于CM7内核中的一个外设,内嵌在NVIC中。系统定时器是一个24bit的向下递减的计数器,计数器每计数一次的时间为1/SYSCLK。当重装载数值寄存器的值递减到0的时候,系统定时器就产生一次中断,以此循环往复。因为SysTick是属于CM7内核的外设,所以所有基于CM7内核的单片机都具有这个系统定时器,使得软件在CM7单片机中可以很容易的移植。系统定时器专用于实时操作系统,用于产生时基,维持操作系统的心跳。

      本程序中Systick中断默认为1ms的定时,其中安全任务执行在这个中断中,中频任务(速度环)也执行在这个中断中。

Systick中断初始化代码如下:

__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;
}

中断函数:

void SysTick_Handler(void)
{
    MC_RunMotorControlTasks();
}

其中MC_RunMotorControlTasks()函数中,执行的是安全任务和中频任务:

__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中断

ADC中断完成高频任务,ADC采样开始由TIM1硬件触发。在中断中执行  FOC坐标变换 , SVPWM的执行 和 TIM1的PWM占空比调整输出。

本程序中使用的是ADC1,完成对电流、母线电压、温度的采集。主要流程如下:

ADC中断.jpg ADC1初始化代码如下:

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中断函数:

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 */
}

从程序中可以看出,ADC中就只有一个任务,高频任务。为什么要把高频任务放在这里,是因为ADC要及时准确把电流电压的值采集完成后,给到FOC进行计算,然后将计算的值通过定时器TIM1转化为输出波形,使电机运行起来。

 

个人签名

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


回复

6203

帖子

0

资源

五彩晶圆(初级)

楼主把Systick中断和ADC中断说的很清楚了

点评

有什么不对的及时指正  详情 回复 发表于 2021-9-23 09:23
谢谢,我也是一边学习一边分享。  详情 回复 发表于 2021-9-23 09:23

回复

1011

帖子

3

资源

版主

Jacktang 发表于 2021-9-23 07:09 楼主把Systick中断和ADC中断说的很清楚了

谢谢,我也是一边学习一边分享。

个人签名

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


回复

1011

帖子

3

资源

版主

Jacktang 发表于 2021-9-23 07:09 楼主把Systick中断和ADC中断说的很清楚了

有什么不对的及时指正

个人签名

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


回复
您需要登录后才可以回帖 登录 | 注册

最新文章 更多>>
    关闭
    站长推荐上一条 1/10 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2021 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表