【RT-thread studio 下使用STM32F103-学习sem-信号量-初步使用-线程之间控制-基础样例】
- 1、前言
- 2、环境
- 3、事项了解
- (1)了解sem概念-了解官网消息
- (2)根据自己理解,设计几个使用方式
- (3)不建议运行中,反复删除,在运行线程。
- 4、实验过程
- 实验说明
- 1、第一部分实验
- (1)实验说明-创建工程
- (2)编写代码
- (3)验证结果
- 2、第二部分实验
- (1)实验说明
- (2)编写代码
- (3)验证结果
- 3、第三部分实验
- (1)实验说明
- (2)编写代码
- (3)验证结果
- 5、代码链接
- 6、细节部分
- 1、dome 文件报错
- 7、总结
1、前言
最近,在使用rt-thread的时候,想要用一个线程控制另一个线程的暂停与运行,
但看资料的时候,发现删除线程和重启线程的时候,好像不太理想,这么弄是容易出现问题的,但通过信号量的方式,比较好,所以这次咱们一起来学习下sem。
自己也从新手的角度,一点点学习。整个rt-thread 还是挺大的,不是深耕多年,很难面面聚到,不过用那学哪里。
2、环境
3、事项了解
(1)了解sem概念-了解官网消息
大概看了一遍整个资料,还是挺多的,当你想要使用的时候,其实多少还是有些摸不到头脑的。
但既然要使用Rt-thread的,官方的文档还是要读一下。
链接:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/ipc1/ipc1?id=%e4%bf%a1%e5%8f%b7%e9%87%8f
(2)根据自己理解,设计几个使用方式
我们使用某种RT-thread带有的功能,是为了解决我们自己出现的问题。
设计实验1:
通过使用sem信号量,当一个线程先运行后,再运行另一个线程。这样其实就是让线程之间形成先后关系,适合一定是某个线程完成后,在运行另一个线程。
设计实验2:
通过使用sem信号量,用一个线程,或者一个变量,控制或者暂停另一个线程。这样其实就是有个主线程,或不一定是主线程,可以控制其他线程运行。
以上都是小的功能模块,但是大的项目,都是小模块一点点搭建起来,这算是其中一个砖块,使用的时候,根据自己情况再调整下。
(3)不建议运行中,反复删除,在运行线程。
在看网上资料是,看到有说到,其实不建议反复挂起或删除创建线程,很容易出现问题。
当时看到了资料忘记去哪里,不过本片将有关sem信号量的。
4、实验过程
实验说明
1、第一部分实验
万事皆有要基础,一步一个脚印,如果环境不能使用的话,后续代码都是无用的,所以第一步是要搭建一个可以运行的程序。自己这块没注意,认为软件装好后,随便创建一个工程,就可以运行,没想到卡了一下。
(1)实验说明-创建工程
(2)编写代码
以下内容,RT-Thread Studio工具会自动生成的。
int main(void)
{int count = 1;while (count++){LOG_D("Hello RT-Thread!");rt_thread_mdelay(1000);}return RT_EOK;
}
(3)验证结果
这块其实遇到一个内存相关报错,更细节部分可以看细节说明部分。
上述问题解决后,然后连接硬件代码,进行下载验证。
2、第二部分实验
(1)实验说明
此部分,主要是让一个线程先运行,运行完毕,再运行了另一个线程。在现实应用中,很多情况下,都是需要的,并且有实际意义的。
举个例子,现实中,有很多测温需求,温度过高过低,都需要做些事情,相当触发异常,这个时候,温度异常,必须先出现,才做后面事情,可以用这样逻辑解决。
(2)编写代码
/** Copyright (c) 2006-2024, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2024-06-21 RT-Thread first version*/#include <rtthread.h>#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>//第一步
//#include <rtthread.h>static rt_sem_t sem; // 信号量//第二步
void sem1_init(void)
{// 创建一个信号量,初始值为 0sem = rt_sem_create("sem", 0, RT_IPC_FLAG_FIFO);if (sem == RT_NULL){rt_kprintf("create semaphore failed.\n");}
}
//第三步
void thread1_entry(void *parameter)
{while (1){// 尝试获取信号量,如果信号量值为 0,则线程将被阻塞rt_sem_take(sem, RT_WAITING_FOREVER);rt_kprintf("Thread 1 is running.\n");rt_thread_mdelay(1000); // 模拟线程工作}
}
//第四步
void thread2_entry(void *parameter)
{while (1){rt_thread_mdelay(3000); // 等待 3 秒rt_kprintf("Thread 2 releases semaphore.\n");rt_sem_release(sem); // 释放信号量}
}int main(void)
{int count = 1;//第五步 应用sem1_init();// 创建线程 1rt_thread_t tid1 = rt_thread_create("thread1",thread1_entry, RT_NULL,1024, 10, 10);if (tid1 != RT_NULL)rt_thread_startup(tid1);// 创建线程 2rt_thread_t tid2 = rt_thread_create("thread2",thread2_entry, RT_NULL,1024, 10, 10);if (tid2 != RT_NULL)rt_thread_startup(tid2);while (count++){//LOG_D("Hello RT-Thread!");rt_thread_mdelay(1000);}return RT_EOK;
}
(3)验证结果
如下为具体实验验证,必须是线程2运行完,才会运行线程1,是按照顺序运行。
3、第三部分实验
(1)实验说明
这种情况,更为复杂些,需要一个线程控制另一个线程,虽然实现方式很多,不一定非要使用这种,但是工具给你准备好了,使不使用看自己,并且是实现比较简单,实际项目,根据自己需求使用。
(2)编写代码
简单讲解下,本实验中,主要是根据a的值,来决定是否运行线程1。
/** Copyright (c) 2006-2024, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2024-06-21 RT-Thread first version*/#include <rtthread.h>#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>//第一步
static rt_sem_t sem; // 信号量
volatile int a = 0; // 控制变量//第二步
void sem_init(void)
{// 创建一个信号量,初始值为 0sem = rt_sem_create("sem", 0, RT_IPC_FLAG_FIFO);if (sem == RT_NULL){rt_kprintf("create semaphore failed.\n");}
}
//第三步
void thread1_entry(void *parameter)
{while (1){// 尝试获取信号量,如果信号量值为 0,则线程将被阻塞rt_sem_take(sem, RT_WAITING_FOREVER);rt_kprintf("Thread 1 is running.\n");rt_thread_mdelay(1000); // 模拟线程工作}
}
//第四步
void thread2_entry(void *parameter)
{while (1){rt_thread_mdelay(1000); // 每秒检查一次变量 a 的值if (a == 1){// 如果 a == 1,则释放信号量,允许线程 1 运行if (rt_sem_release(sem) == RT_EOK){rt_kprintf("Thread 2 releases semaphore.\n");}}else{// 如果 a == 0,则确保信号量不会释放,线程 1 将被暂停rt_kprintf("Thread 2: a is 0, thread 1 will pause.\n");}}
}void set_a(int value)
{a = value;rt_kprintf("Variable a set to %d\n", a);
}int main(void)
{int count = 1;// 初始化信号量sem_init();// 创建线程 1rt_thread_t tid1 = rt_thread_create("thread1",thread1_entry, RT_NULL,1024, 10, 10);if (tid1 != RT_NULL)rt_thread_startup(tid1);// 创建线程 2rt_thread_t tid2 = rt_thread_create("thread2",thread2_entry, RT_NULL,1024, 10, 10);if (tid2 != RT_NULL)rt_thread_startup(tid2);while (count++){set_a(0);rt_thread_mdelay(10000);set_a(1);//LOG_D("Hello RT-Thread!");rt_thread_mdelay(10000);}return RT_EOK;
}
(3)验证结果
5、代码链接
代码链接:https://download.csdn.net/download/qq_22146161/89466496
6、细节部分
1、dome 文件报错
7、总结
一个砖一个砖,垒起来。