当前位置: 首页 > article >正文

STM32-笔记12-实现SysTick模拟多线程流水灯

1、前言

        正常STM32实现多线程,需要移植一个操作系统FreeRTOS。但是在这里不移植FreeRTOS怎么实现多线程呢?使用SysTick,那么怎么使用SysTick来模拟多线程呢?前面我们知道SysTick就是一个定时器,它不是在主函数的while循环里实现的,就是在旁边自己玩自己的。所以我们可以理解成,main函数是主线程,而SysTick在一边实现自己的,在SysTick里面。可以通过配置让SysTick每一秒钟中断一次,在中断服务函数里面干其他的事情,这样就实现了多线程。

2、动手实现双线程

使用项目文件11-带操作系统的延时函数,复制,重命名为12-SysTick模拟多线程流水灯

打开文件,找到SysTick_Handler函数

在.s文件(只有一个.s文件)中找到SysTick_Handler

ctrl+f查找文件

 在主函数的HAL_Init();函数中

        可以看到HAL_IncTick();函数设置了一个1ms的中断,所以我们不需要配置额外的配置了,只需要在中断服务函数中做自己想要做的事就可以了。

        现在在主函数中,在流水灯中是每隔500ms换一次led1和led2的闪烁情况,现在我们换一下,让led1每隔1000ms闪烁一次,led2每隔500ms闪烁一次,主函数实现led2的闪烁情况,SysTick实现led1的闪烁情况。

主函数情况如下:

这里的定义和头文件都是为了方便才放到这里的

这样就实现了上述描述的实验

还可以都在HAL_IncTick();函数中实现,先把主函数中的实现给注释掉,具体代码如下:

3、遇到多线程

遇到很多条线程的时候,我们不可能每一条都那么写,会显得很冗余

在该目录文件下,新建文件夹tasks,和相应的.c .h文件

用来存放所有的线程,将文件加载进工程文件中

在.c文件中引入#include "tasks.h"

编译,搞出.h文件,打开.h文件

 编译->下载,运行结果一致

但是,没有完,接着做进一步的改装

        这是一个中断服务函数,现在只是点亮led灯不算复杂,未来我们要使用SysTick的时候不可以在这里很复杂的事情,不可以在这里延时很久的时间。

        让sysTick_isr();函数只起到一个计数的功能,并不在这个函数里面延时(现在点灯操作,还没有实现延迟),定义两个flag,用来标志是否达到指定的数目,如果达到,就在另一个线程函数中实现点灯(未来实现延迟功能)。

代码如下:

tasks.c

#include "tasks.h"
#include "led.h"

uint32_t task1_cnt = 0; //定义一个变量用来计数
uint32_t task2_cnt = 0; //定义一个变量用来计数
uint8_t task1_flag = 0;
uint8_t task2_flag = 0;



void sysTick_isr(void)
{
    if(task1_cnt <1000)
       task1_cnt++;
    else
    {
        task1_flag = 1;
        task1_cnt = 0;
    }
    if(task2_cnt <500)
        task2_cnt++;
    else
    {
        task2_flag = 1;
        task2_cnt = 0;
    }
    
}
void task1(void)
{
    if(task1_flag == 0)
        return;
    task1_flag = 0;//置位
    led1_toggle();
    
}
void task2(void)
{
    if(task2_flag == 0)
        return;
    task2_flag = 0;
    led2_toggle();
    
}

tasks.h

#ifndef __TASKS_H__
#define __TASKS_H__

#include "sys.h"

void sysTick_isr(void);
void task1(void);
void task2(void);

#endif

main.c

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "tasks.h"


int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */
    led_init();                         /* 初始化LED灯 */

    while(1)
    {
        //一直在while循环中不断的重复执行task()函数
        //task()函数只有在满足对应条件的时候才会点灯,否则不点灯,白执行
        task1();
        task2();
    }
}

代码分析:

主函数不断在while中调用task1(); 和task2();函数,当task1(); 和task2();函数中,标志位满足相应的条件就会执行点灯操作,否则不满足不执行直接return返回,对于标志位的操作是看是否满足其数量,如果到指定数目,则标志位为1,否则依旧为0。


http://www.kler.cn/a/455394.html

相关文章:

  • 探秘 Chrome 隐藏配置项:chrome://net-internals
  • PCA降维MATLAB代码解释及应用场景
  • OpenCV相机标定与3D重建(37)计算两幅图像之间单应性矩阵(Homography Matrix)的函数findHomography()的使用
  • 使用c#制作坐标
  • c++基于过程
  • UGUI简单动画制作
  • QML和QWidget混合编程方式
  • MySQL —— 配置文件
  • vue3 ref reactive响应式数据,赋值的问题、解构失去响应式问题
  • 下划线表示任意单个字符引发的bug
  • 三相电的相电压、线电压、额定值、有效值,变比,零序电压,零序电流,三相三线制的三角形连接,三相四线制的星形连接
  • C++ 学生成绩信息管理
  • Unity开发AR之Vuforia-MultiTarget笔记
  • 华为战略解码-162页 八大章节 精读
  • 量子退火与机器学习(1):少量数据求解未知QUBO矩阵,以少见多
  • 【代码随想录】刷题记录(86)-跳跃游戏 II
  • Web API和Web Services的区分
  • IDEA错题集
  • HarmonyOS实战开发之HMRouter实现跳转
  • 【源码+文档+调试讲解】电影交流平台小程序
  • GB/T34944-2017 《Java语言源代码漏洞测试规范》解读——安全功能
  • 【C++】——精细化哈希表架构:理论与实践的综合分析
  • 鸿蒙Next如何实现打开相册选图片功能?
  • 服务器与电脑主机各自的优势
  • 麦吉尔大学Ding Lab基于深度学习开发单细胞水平转座子位点表达定量模型,登Nature子刊
  • matrix-breakout-2-morpheus