一、SysTick简介
SysTick —系统定时器是属于 CM3 内核中的一个外设,内嵌在 NVIC 中。系统定时器是一个 24bit 的向下递减的计数器,计数器每计数一次的时间为 1/SYSCLK,一般我们设置系统时钟 SYSCLK 等于 72M。当重装载数值寄存器的值递减到 0 的时候,系统定时器就产生一次中断,以此循环往复。
因为 SysTick 是属于 CM3 内核的外设,所以所有基于 CM3 内核的单片机都具有这个系统定时器,使得软件在 CM3 单片机中可以很容易的移植。系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。
二、新建工程
1. 打开 STM32CubeMX 软件,点击“新建工程”

2. 选择 MCU 和封装

3. 配置时钟
RCC 设置,选择 HSE(外部高速时钟) 为 Crystal/Ceramic Resonator(晶振/陶瓷谐振器)

选择 Clock Configuration,配置系统时钟 SYSCLK 为 72MHz
修改 HCLK 的值为 72 后,输入回车,软件会自动修改所有配置

4. 配置调试模式
非常重要的一步,否则会造成第一次烧录程序后续无法识别调试器
SYS 设置,选择 Debug 为 Serial Wire

5. 配置GPIO
GPIO 设置,在右边图中找到 LED 灯对应引脚,选择 GPIO_Output,输出低电平点亮,可以添加自定义标签


6. 生成代码
输入项目名和项目路径

选择应用的 IDE 开发环境 MDK-ARM V5

每个外设生成独立的 ’.c/.h’ 文件
不勾:所有初始化代码都生成在 main.c
勾选:初始化代码生成在对应的外设文件。 如 GPIO 初始化代码生成在 gpio.c 中。

点击 GENERATE CODE 生成代码

三、普通延时
3.1 修改main函数,实现流水灯
在 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 // 当计数器的值减小到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 // 当计数器的值减小到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(); 四、中断中延时 在 STM32CubeMX学习笔记(3)——EXTI(外部中断)接口使用 的 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 中断的抢占优先级和外部中断的抢占优先级是一样的,那么在外部中断触发时肯定不能接着触发 Systick 中断了,问题已经找到,只需要简单地将外部中断的抢占优先级改低即可。 抢占优先级,数字越小,优先级越高 若抢占优先级相同,判断子优先级,同样,数字越小,优先级越高 五、注意事项 用户代码要加在 USER CODE BEGIN N 和 USER CODE END N 之间,否则下次使用 STM32CubeMX 重新生成代码后,会被删除。
HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) 对应 SysTick_Config(SystemCoreClock/1000000)
HAL_Delay(500); 对应 SysTick_Delay_Ms(500);

上一篇:STM32CubeMX学习笔记(5)——基本定时器接口使用
下一篇:STM32CubeMX学习笔记(3)——EXTI(外部中断)接口使用
推荐阅读最新更新时间:2026-03-23 21:45
- LTC2172CUKG-12、12 位、65Msps 低功耗四通道 ADC 的典型应用电路
- 使用 ROHM Semiconductor 的 BD5339 的参考设计
- 使用 Diodes Incorporated 的 PT8A3517 的参考设计
- LT5527 400MHz 至 3.7GHz 高信号电平下变频混频器的典型应用
- AD5340 并行接口、单电压输出、12 位 DAC 的典型应用
- 30W、-27V、5.8V、5.8V、15V、24V、33V交流转直流多路输出电源
- OP213FSZ-REEL7 低噪声运算放大器电压基准的典型应用
- LT3579/LT3579-1 演示板,升压 / 反相 DC/DC 转换器
- L7815A 光控制器稳压器的典型应用 (Vo(min) = Vxx + VBE)
- 具有关断功能的 LT1086CT-5 5V 稳压器的典型应用

基于 X-Cube-FreeRTOS_Heap4 和 CubeMX 生成 UCPD 项目介绍
STM32使用stm32cubemx 写的tcp基础程序
Follow me第三季第1期STM32F429作品代码
非常经典的关于LLC的杨波博士论文
XC6406PP60DL






京公网安备 11010802033920号