STM32
直播中

123

9年用户 799经验值
擅长:可编程逻辑
私信 关注
[问答]

如何在STM32CubeMX软件上新建一个系统定时器呢

Systick是什么?

如何在STM32CubeMX软件上新建一个系统定时器呢?

回帖(1)

白珊

2021-10-28 14:28:27
  一、SysTick简介
  系统定时器-系统定时器是属于CM3内核中的一个外设,内嵌在NVIC。中系统定时器是一个24位的向下递减的计数器,计数器每计数一次的时间为1 / SYSCLK,一般我们设置系统时钟SYSCLK等于72M。当重装载数值寄存器的值递减到0的时候,系统定时器就产生一次中断,以此循环往复。
  因为系统定时器是属于CM3内核的外设,所以所有基于CM3内核的单片机都具有这个系统唤醒,使用软件在CM3中可以很容易的移植。系统日常用于日常,用于时基,维持睡眠的呼吸。
  二、新建工程
  1. 打开STM32CubeMX软件,点击“新建工程”
  
  2.选择MCU和封装
  
  3。配置时钟
  RCC设置,选择HZ外部高速
  
  时钟)为/CeramicReCrystalReCrystal(晶振/陶瓷器)选择时钟配置,系统时钟
  SYS为72MHz HCLK的值为72后,输入回,软件会自动修改修改
  
  4.所有配置 配置调试
  非常重要的一步,否则会造成第一次烧录视频程序无法识别调试器
  ,选择调试为串口线
  
  5.配置GPIO
  GPIO设置,在右边靠近LED灯对应模式,选择GPIO_Output模式,输出低触发,可以添加自定义标签
  
  
  6. 生成代码
  输入项目名和项目路径
  
  选择应用的IDE 开发环境MDK-ARM V5
  
  外设生成独立的‘.c/.h’ 文件
  不勾:所有初始化代码都生成在main.c
  :初始化代码生成在对应的外设文件。如GPIO初始化代码生成在gpio.c中
  
  点击GENERATE CODE生成代码
  
  三、普通加上
  3.1修改主函数,实现流水灯
  在while()循环中加入输出置反函数HAL_GPIO_TogglePin。 () 和其他函数 HAL_Delay()。
  /**
  * @brief The application entry point.
  * @retval int
  */
  int main(void)
  {
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */
  /* MCU Configuration--------------------------------------------------------*/
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* USER CODE BEGIN Init */
  /* USER CODE END Init */
  /* Configure the system clock */
  SystemClock_Config();
  /* USER CODE BEGIN SysInit */
  /* USER CODE END SysInit */
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
  HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
  HAL_Delay(500);
  HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
  HAL_GPIO_TogglePin(LED_B_GPIO_Port,LED_B_Pin);
  HAL_Delay(500);
  HAL_GPIO_TogglePin(LED_B_GPIO_Port,LED_B_Pin);
  /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
  }
  3.2 HAL库与标准库代码比较
  STM32CubeMX使用HAL库生成的代码:
  /**
  * @brief The application entry point.
  * @retval int
  */
  int main(void)
  {
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */
  /* MCU Configuration--------------------------------------------------------*/
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* USER CODE BEGIN Init */
  /* USER CODE END Init */
  /* Configure the system clock */
  SystemClock_Config();
  /* USER CODE BEGIN SysInit */
  /* USER CODE END SysInit */
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
  HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
  HAL_Delay(500);
  HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
  HAL_GPIO_TogglePin(LED_B_GPIO_Port,LED_B_Pin);
  HAL_Delay(500);
  HAL_GPIO_TogglePin(LED_B_GPIO_Port,LED_B_Pin);
  /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
  }
  HAL_StatusTypeDef HAL_Init(void)
  {
  /* Configure Flash prefetch */
  #if (PREFETCH_ENABLE != 0)
  #if defined(STM32F101x6) || defined(STM32F101xB) || defined(STM32F101xE) || defined(STM32F101xG) ||
  defined(STM32F102x6) || defined(STM32F102xB) ||
  defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG) ||
  defined(STM32F105xC) || defined(STM32F107xC)
  /* Prefetch buffer is not available on value line devices */
  __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
  #endif
  #endif /* PREFETCH_ENABLE */
  /* Set Interrupt Group Priority */
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
  /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
  HAL_InitTick(TICK_INT_PRIORITY);
  /* Init the low level hardware */
  HAL_MspInit();
  /* Return function status */
  return HAL_OK;
  }
  __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;
  }
  /**
  * @brief This function handles System tick timer.
  */
  void SysTick_Handler(void)
  {
  /* USER CODE BEGIN SysTick_IRQn 0 */
  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */
  /* USER CODE END SysTick_IRQn 1 */
  }
  使用STM32标准库的代码:
  /**
  * @brief 主函数
  * @param 无
  * @retval 无
  */
  int main(void)
  {
  /* LED 端口初始化 */
  LED_GPIO_Config();
  /* 配置SysTick 为10us中断一次 */
  SysTick_Init();
  for(;;)
  {
  LED1( ON );
  SysTick_Delay_Ms( 1000 );
  LED1( OFF );
  LED2( ON );
  SysTick_Delay_Ms( 1000 );
  LED2( OFF );
  }
  }
  /**
  * @brief 启动系统滴答定时器 SysTick
  * @param 无
  * @retval 无
  */
  void SysTick_Init(void)
  {
  /* SystemFrequency / 1000 1ms中断一次
  * SystemFrequency / 100000 10us中断一次
  * SystemFrequency / 1000000 1us中断一次
  */
  // if (SysTick_Config(SystemFrequency / 100000)) // ST3.0.0库版本
  if (SysTick_Config(SystemCoreClock / 100000)) // ST3.5.0库版本
  {
  /* Capture error */
  while (1);
  }
  }
  // couter 减1的时间 等于 1/systick_clk
  // 当counter 从 reload 的值减小到0的时候,为一个循环,如果开启了中断则执行中断服务程序,
  // 同时 CTRL 的 countflag 位会置1
  // 这一个循环的时间为 reload * (1/systick_clk)
  void SysTick_Delay_Us( __IO uint32_t us)
  {
  uint32_t i;
  SysTick_Config(SystemCoreClock/1000000);
  for(i=0;i《us;i++)
  {
  // 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
  while( !((SysTick-》CTRL)&(1《《16)) );
  }
  // 关闭SysTick定时器
  SysTick-》CTRL &=~SysTick_CTRL_ENABLE_Msk;
  }
  void SysTick_Delay_Ms( __IO uint32_t ms)
  {
  uint32_t i;
  SysTick_Config(SystemCoreClock/1000);
  for(i=0;i《ms;i++)
  {
  // 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
  // 当置1时,读取该位会清0
  while( !((SysTick-》CTRL)&(1《《16)) );
  }
  // 关闭SysTick定时器
  SysTick-》CTRL &=~ SysTick_CTRL_ENABLE_Msk;
  }
  HAL_InitTick(TICK_INT_PRIORITY); SysTick_Init();
  HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) 对应 SysTick_Config(SystemCoreClock/1000000)
  HAL_Delay(500); 对应SysTick_Delay_Ms(500);
  四,中中断延时
  在ESP8266学习笔记(3) - GPIO使用接口的HAL_GPIO_EXTI_Callback中加入按键消抖
  /* USER CODE BEGIN 1 */
  void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
  {
  if(GPIO_Pin==KEY1_Pin)
  {
  HAL_Delay(100);
  if(HAL_GPIO_ReadPin(KEY1_Pin_Port,KEY1_Pin)==1)
  {
  HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
  }
  }
  }
  /* USER CODE END 1 */
  现在下载进单片机只会让它在按键按下后没有任何反应,这又是为什么呢,其实问题出在HAL_Delay()上。
  在进入回调函数之后就一直在HAL_Delay陷入了死循环中,原因是SYSTICK优先级太低造成的。
  
  SYSTICK中断的抢占优先级和外部中断的抢占优先级是一样的,那么在外部中断触发时肯定不能接着触发系统定时器中断了,问题已经找到了,只需要简单地将外部破坏的抢占优先级低分类。
  抢占优先级,数字越小,优先级
  如果抢占优先级相同,判断子优先级,同样,数字越小,优先级等级
  
  五、注意事项
  用户代码要加在 USER CODE BEGIN N 和 USER CODE END N 之间,否则可以使用 STM32CubeMX 重生成代码后,会被删除。
  
举报

更多回帖

发帖
×
20
完善资料,
赚取积分