【Linux】信号量操作函数

2023-05-16

文章目录

  • 二、 实验原理
    • 1、semget() 函数
      • 函数作用:
      • 参数意义:
      • 例子:
    • 2、semop()函数
      • 函数作用:
      • 参数意义:
      • struct sembuf 结构体定义如下
      • 例子:
      • 再来个完整点的例子1:
      • 再来个完整点的例子2:
    • 3、semctl()函数
      • 函数作用
        • 细致一些
      • 参数意义(4个):
      • 例子1:
        • 小问题:
      • 例子2:
        • 小问题:
  • 每天进步一点点 笔记仅供自学,用来回看复习,不一定适合你,如有错误请指出。

二、 实验原理

信号量操作函数

1、semget() 函数

#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);

函数作用:

semget() 函数是 Linux 中的一个系统调用,用于创建或获取一个信号量集的标识符。信号量集是一个包含若干个信号量的数据结构,每个信号量都是一个整型值,用于在进程之间进行同步和互斥。

参数意义:

参数含义如下:

  • key:一个整型值,用于标识信号量集。如果 key 为 0,则系统会自动生成一个唯一的 key 值。
  • nsems:表示信号量集中包含的信号量个数。
  • semflg:表示创建信号量集的权限和行为。可以使用以下值:
    IPC_CREAT:如果信号量集不存在,则创建一个新的信号量集;如果信号量集已存在,则获取它的标识符。
    IPC_EXCL:与 IPC_CREAT 一起使用时,如果信号量集已存在,则调用 semget() 函数失败,并返回错误。
    返回值:
  • 成功:返回信号量集的标识符。
  • 失败:返回 -1,并设置 errno 为相应的错误码。

例子:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int main(int argc, char** argv) 
{
	// 创建一个信号量集,并设置信号量集中信号量的值为1
	key_t key = 12345;
	int sem_id = semget(key, 1, 0666 | IPC_CREAT); // IPC_CREAT表示如果信号量集不存在,就创建它
	if (sem_id == -1) 
	{
	perror("semget error");
	exit(1);
	}
union semun 
{
	int val;
	struct semid_ds *buf;
	ushort *array;
} argument;
	argument.val = 1;
if (semctl(sem_id, 0, SETVAL, argument) == -1) 
{
	perror("semctl error");
	exit(1);
}
	return 0;
}

1、上面的代码中,首先使用semget 函数来创建一个信号量集,参数 key 指定一个唯一的键值,参数 nsems 指定信号量集中信号量的数量,这里设置为1,即只创建一个信号量。参数 semflg 指定权限和创建信号量集的选项,0666 表示允许所有用户读写信号量集,IPC_CREAT 表示如果信号量集不存在,就创建它。
2、然后使用 semctl 函数来设置信号量集中信号量的值,参数 semid 指定信号量集的标识符,参数 semnum 指定信号量的编号,这里设置为0,即设置信号量集中唯一的信号量的值,参数 cmd 指定执行的操作,这里设置为 SETVAL,表示设置信号量的值,最后一个参数 argument 是一个联合类型,用于传递信号量的值。
3、如果成功创建并设置信号量集,则 semget 函数返回信号量集的标识符,semctl 函数返回0,否则返回-1。

2、semop()函数

#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);

函数作用:

semop()函数是用于对信号量集进行操作的函数。它的作用是执行一个或多个信号量操作,如P操作或V操作。通常,semop()函数被用于控制对共享资源的访问,以保证在多个进程之间的资源共享是互斥的。
semop() 函数通过修改信号量集中每个信号量的值来实现对信号量的 P 操作和 V 操作。
semop() 函数的返回值为 0 表示执行成功,-1 表示执行失败。

参数意义:

  • semid 指信号量集的标识符;
  • sops 指向一个信号操作结构体的指针;
  • nsops 为要执行的信号操作的数量。

struct sembuf 结构体定义如下

struct sembuf 
{ 
 unsigned short int sem_num; /* 信号量的序号从 0~nsems-1 */ 
 short int sem_op; /* 对信号量的操作,>0, 0, <0 */ 
 short int sem_flg; /* 操作标识:0, IPC_WAIT, SEM_UNDO */ 
};

其中,sem_num 为信号量在信号量集中的编号
sem_op 为要执行的信号操作(P操作或V 操作)的操作数
sem_flg 为执行信号操作的标志(如是否阻塞等)。

例子:

举个例子,假设有一个信号量的值为 1,我们想要对这个信号量做 P 操作,也就是将其减 1,那么我们可以使用 semop() 函数来实现这个操作:

int sem_id; // 信号量的标识符
struct sembuf sops; // 信号量操作结构体
sops.sem_num = 0; // 信号量的编号(对应信号量集中的第几个信号量)
sops.sem_op = -1; // 要执行的操作(-1 表示 P 操作,1 表示 V 操作)
sops.sem_flg = 0; // 操作标志
semop(sem_id, &sops, 1); // 执行信号量操作

以上代码执行完之后,这个信号量的值就变成了 0。

1、上述代码中,semop 函数用来执行一个或多个信号量操作。它的第一个参数是信号量的标识符,第二个参数是一个指向结构体 sembuf 的指针,表示要执行的操作,第三个参数是要执行的操作的数量。
2、在上述代码中,sem_num 字段表示要操作的信号量在信号量集中的编号,sem_op 字段表示要执行的操作,如果为 -1,则执行 P 操作,如果为 1,则执行 V 操作。sem_flg 字段表示操作标志,通常设置为 0。

例如,如果要执行两个 P 操作,则可以这样调用 semop 函数:

struct sembuf sops[2];
sops[0].sem_num = 0;
sops[0].sem_op = -1;
sops[0].sem_flg = 0;
sops[1].sem_num = 1;
sops[1].sem_op = -1;
sops[1].sem_flg = 0;
semop(sem_id, sops, 2);

再来个完整点的例子1:

以下是一个使用 semop() 函数的简单例子:

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int main() 
{
	// 创建一个信号量集,包含一个信号量,初值为 1
	int sem_id = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
	if (sem_id < 0) {
	perror("semget error");
	return -1;
	}
	
	// 对信号量做 P 操作,即获取锁
	struct sembuf sops;
	sops.sem_num = 0;
	sops.sem_op = -1; // 操作数为 -1,即为 P 操作
	sops.sem_flg = 0;
	if (semop(sem_id, &sops, 1) < 0) {
	perror("semop error");
	return -1;
	}
	
	// 在获得锁的情况下进行关键操作
	printf("Critical section\n");
	
	// 对信号量做 V 操作,即释放锁
	sops.sem_op = 1; // 操作数为 1,即为 V 操作
	if (semop(sem_id, &sops, 1) < 0) {
	perror("semop error");
	return -1;
	}
	
	// 删除信号量集
	if (semctl(sem_id, 0, IPC_RMID) < 0) {
	perror("semctl error");
	return -1;
	}
	
	return 0;
}

1、这段代码实现了一个简单的互斥锁,通过使用信号量来保证关键操作的互斥执行。
2、首先,使用 semget() 函数创建一个信号量集,并设置信号量集中的信号量的初值为 1。
3、然后,使用 semop() 函数执行 P 操作,即获取锁。获取锁成功之后,执行关键操作。
4、最后,使用 semop() 函数执行 V 操作,即释放锁。
5、最后,使用 semctl() 函数删除信号量集。

这段代码的运行过程如下:

1、创建信号量集,并设置信号量的初值为 1。
2、执行 P 操作,即获取锁。
3、执行关键操作。
4、执行 V 操作,即释放锁。
5、删除信号量集。

再来个完整点的例子2:

#include <sys/sem.h>
#include <stdio.h>
int main()
{
	key_t key;
	int semid;
	struct sembuf sops;
	// 获取信号量集的标识符
	key = ftok("/tmp/sem.temp", 1);
	semid = semget(key, 1, 0666 | IPC_CREAT);

	// 初始化信号量
	semctl(semid, 0, SETVAL, 1);
	
	// 执行 P 操作
	sops.sem_num = 0;
	sops.sem_op = -1;
	sops.sem_flg = SEM_UNDO;
	semop(semid, &sops, 1);
	
	// 执行 V 操作
	sops.sem_num = 0;
	sops.sem_op = 1;
	sops.sem_flg = SEM_UNDO;
	semop(semid, &sops, 1);
	
	return 0;
}
  • 这是一个使用信号量实现互斥锁的例子。信号量集的标识符获取使用了 ftok 函数,信号量初始化使用了 semctl 函数,信号量 P 和 V 操作使用了 semop 函数。
  • ftok 函数用于获取文件的 IPC 键值,参数 pathname 指定文件路径,参数 proj_id 指定一个字节的整数值。ftok 函数返回的结果作为 semget 函数的第一个参数。
  • semctl 函数用于设置信号量的值,或者获取信号量的信息。参数 semid 是信号量集的标识符,参数 semnum 指定信号量集中信号量的编号,参数 cmd 指定操作的类型,参数 arg 是 cmd 的参数。semctl 函数的返回值是操作的结果。
  • semop 函数用于执行信号量操作。参数 semid 是信号量集的标识符,参数 sops 是一个指向 struct sembuf 结构体的指针,指定了要执行的信号量操作。参数 nsops 指定 sops 数组的长度。semop 函数的返回值是操作的结果。
  • 在本例中,使用了 SEM_UNDO 标志,表示若进程因意外终止,则系统会自动执行 V 操作来释放锁。这样就可以避免进程意外终止而导致的死锁问题。
  • 此外,还可以使用 semop() 函数的 sops 数组版本来执行多个信号量操作。例如,若要同时获取多个锁,可以将多个信号量的 P 操作放在 sops 数组中,并一次性执行,以达到节省时间的目的。

3、semctl()函数

#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ... /* arg */);

函数作用

semctl() 函数是 Linux 中用于控制信号量集的函数。它支持多种操作,可以用于获取信号量集的属性、设置信号量集的属性、控制信号量的值等。

细致一些

semctl() 函数是用来控制信号量的函数,它接受三个参数:信号量集的标识符、信号量的编号、控制命令。
根据不同的控制命令,可以进行不同的操作,比如设置信号量的值、获取信号量的值、删除信号量集等。

参数意义(4个):

  • semid:信号量集的标识符。
  • semnum:要操作的信号量的编号。是信号量在信号量集中的编号
  • cmd 是要执行的命令,后面的参数是根据 cmd 的值而定的。
    如果 cmd 为 SETVAL 或 SETALL,则此参数被忽略
    cmd:指定要执行的操作。(操作命令
    可以是以下值之一:
    GETVAL:获取信号量的值。
    SETVAL:设置信号量的值,取自 arg 的 val 元素。
    GETPID:返回最后一个执行 semop 函数的进程的进程号。
    GETNCNT:获取当前等待信号量为正值的进程数。
    GETZCNT:获取当前等待信号量为 0 的进程数。
    GETALL:获取信号量集中所有信号量的值。
    SETALL:设置信号量集中所有信号量的值。
    IPC_STAT:获取信号量集的属性。
    IPC_SET:设置信号量集的属性。
    IPC_RMID:删除信号量集。
    常用的有:
    semctl() 函数有多种用途,常用的命令有以下几种:
    GETVAL:获取信号量的值。
    SETVAL:设置信号量的值。
    IPC_RMID:删除信号量集。
    IPC_STAT:获取信号量集的属性。
    IPC_SET:设置信号量集的属性。
  • arg:可变参数,依赖于 cmd 的值而不同。如果 cmd 为 SETVAL 或 SETALL,则 arg 指向一个 int 类型的值,表示要设置的信号量的值。

例子1:

下面是一个使用 semctl() 函数获取信号量值的示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int main()
{
	key_t key = ftok("/tmp", 'a');
	int sem_id = semget(key, 1, 0666 | IPC_CREAT);
	int val = semctl(sem_id, 0, GETVAL);
	printf("Semaphore value: %d\n", val);
	return 0;
}

小问题:

其中 int sem_id = semget(key, 1, 0666 | IPC_CREAT); 参数为什么要在这样设置?

semget()函数用于创建或获取信号量集。
它的三个参数分别为:

  • key:信号量集的标识符。
  • nsems:信号量集中信号量的数量。
  • semflg:控制信号量集的创建或获取方式。
    1、在这里,第一个参数key是一个键值,用于指定信号量集的标识符。第二个参数nsems指定信号量集中信号量的数量。第三个参数semflg用于控制信号量集的创建或获取方式。
    2、0666表示信号量集的读写权限
    3、IPC_CREAT标志表示如果信号量集不存在,则创建它。
    综上,int sem_id = semget(key, 1, 0666 | IPC_CREAT);
    这行代码用于创建一个新的信号量集,其中包含一个信号量,并返回该信号量集的标识符。

例子2:

nt sem_id; // 信号量集的标识符
int sem_num = 3; // 信号量的编号
int sem_val = 5; // 信号量的值

union semun 
{
	int val;
	struct semid_ds *buf;
	unsigned short *array;
} sem_arg; // 定义信号量控制命令的参数

sem_arg.val = sem_val; // 设置信号量的值
semctl(sem_id, sem_num, SETVAL, sem_arg); // 设置信号量的值

这样就可以使用 semctl() 函数来设置信号量的值了。

小问题:

上面的代码中,设置信号量的值 那行代码 是什么作用?

在上面的代码中,设置信号量的值的那行代码是使用 semctl() 函数设置信号量的值。semctl() 函数是用来控制信号量集的函数,它提供了许多操作选项,如设置信号量的值,获取信号量的值,删除信号量等。在这个代码中,使用的是 SETVAL 操作选项,表示将信号量的值设置为指定的数值。这个函数的第三个参数就是要设置的信号量的值。


每天进步一点点 笔记仅供自学,用来回看复习,不一定适合你,如有错误请指出。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Linux】信号量操作函数 的相关文章

  • Ubuntu 上的 Docker 无法连接到本地主机,但可以连接到其 IP

    我运行的是 Ubuntu 18 04 uname r 5 3 0 46 generic 我已经安装了docker docker version Docker version 19 03 8 build afacb8b7f0 我有一个简单的
  • 为所有图像添加前缀(递归)

    我有一个包含 5000 多张图像的文件夹 全部带有 JPG 扩展名 我想要做的就是递归地向所有图像添加 thumb 前缀 我发现了一个类似的问题 重命名文件和目录 添加前缀 https stackoverflow com questions
  • 保护一个保存 MySQL 数据库的简单 Linux 服务器?

    这是一个初学者问题 但我浏览了该网站上的许多问题 但没有找到简单直接的答案 我正在设置一个运行 Ubuntu 的 Linux 服务器来存储 MySQL 数据库 该服务器尽可能安全非常重要 据我所知 我主要担心的是传入的 DoS DDoS 攻
  • 用于列出用户和组的 Python 脚本

    我正在尝试编写一个脚本 在自己的行上输出每个用户及其组 如下所示 user1 group1 user2 group1 user3 group2 user10 group6 etc 我正在为此用 python 编写一个脚本 但想知道如何做到这
  • 在 Ubuntu 上运行独立的 ASP.NET Core 应用程序

    我已经发布了一个 ASP NET Core 应用程序作为针对 Ubuntu 的独立应用程序 发布似乎工作正常 我已将这些文件复制到一台漂亮的 Ubuntu 机器上 现在 我如何运行我的应用程序 我的理解是 因为它是一个独立的 NET Cor
  • 如何在汇编语言中换行打印多个字符串

    我试图在汇编中的不同行上打印多个字符串 但使用我的代码 它只打印最后一个字符串 我对汇编语言非常陌生 所以请耐心等待 section text global start start mov edx len mov edx len1 mov
  • GCC 4.7 字符串文字的源字符编码和执行字符编码?

    Linux x86 64 上的 GCC 4 7 是否具有默认字符编码 用于验证和解码 C 源文件中字符串文字的内容 这是可配置的吗 此外 当将字符串数据从字符串文字链接到输出的数据部分时 它是否具有默认的执行字符编码 这是可配置的吗 在任何
  • 更改 Amazon RDS MYSQL Linux 服务器的 innodb_log_file_size 变量值

    我们正在使用 Amazon RDS linux 服务器作为 MYSQL 更改 my cnf 文件变量值的方法是什么 我正在尝试更改 innodb log file size 变量 您能告诉我哪一个是最好的改变方式吗 所以请帮我解决这个问题
  • 为什么分配大块内存会失败,而重新分配小块内存却不会失败

    这段代码的结果是x指向一块大小为 100GB 的内存 include
  • 使用请求和多处理时的奇怪问题

    请检查这个Python代码 usr bin env python import requests import multiprocessing from time import sleep time from requests import
  • 使用正在运行的进程的共享内存收集核心转储

    核心转储仅收集进程空间 而不收集为进程间通信创建的共享内存 如何使核心转储也包含正在运行的进程的共享内存 设置核心文件过滤器 proc PID coredump filter per http man7 org linux man page
  • 使用openssl从服务器获取证书

    我正在尝试获取远程服务器的证书 然后可以将其添加到我的密钥库中并在我的 Java 应用程序中使用 一位高级开发人员 正在度假 告诉我我可以运行这个 openssl s client connect host host 9999 获取转储的原
  • Web 本地应用程序 Apache:运行 shell 脚本

    我开发了一个 shell 脚本 我想用它创建一个 UI 我决定使用带有本地服务器的 Web 界面 因为我对 HTML PHP 的了解很少 比 QT 或 Java 的了解更多 我只是希望我的 html 可以在我的计算机上运行 shell 脚本
  • 在linux x86平台上学习ARM所需的工具[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有一个 x86 linux 机器 在阅读一些关于 ARM 的各种信息时 我很好奇 现在我想花一些时间学
  • bash 别名中允许使用哪些字符[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我最近添加了 alias cd alias cd alias cd 到我的 bash aliases 文件 玩弄这个 我注意到在别名时 被
  • C中的内存使用问题

    请帮忙 操作系统 Linux 其中 sleep 1000 中 此时 top 显示Linux任务 给我写了7 7 MEM使用 valgrind 未发现内存泄漏 我明白 写得正确 所有 malloc 结果都是 NULL 但是为什么这次 睡眠 我
  • 将一个文件写入.c中的另一个文件

    我有一个读取文件然后将其内容复制到另一个文件的代码 我需要使其仅复制每 20 个符号 然后跳过 10 个符号 然后再次跳过 20 个符号 依此类推 我必须使用 lseek 函数 但我不知道如何将所有这些放入循环中来执行此操作 main ar
  • 页面错误陷阱的成本

    我有一个应用程序 它定期 每 1 或 2 秒后 通过分叉自身来获取检查点 因此 检查点是原始进程的一个分支 它一直保持空闲状态 直到原始进程发生某些错误时被要求启动 现在我的问题是fork的写时复制机制的成本有多大 每当原始进程写入内存页面
  • 干净地销毁System V共享内存段

    我在用shmget shmat and shmctl分别获取和创建共享内存段 将其附加到进程地址空间中并删除它 我想知道进程是否仍然可以使用共享内存段 即使它已被分离并要求使用删除 shmctl id IPC RMID 在一个过程中 我无法
  • 类似 wget 的 BitTorrent 客户端或库? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 是否有任何

随机推荐

  • C/C++中关于struct和class类的区别

    struct和class的主要的区别在于两者默认的访问权限有所不同 在不设置类中的成员属性和成员方法的权限时 xff0c struct默认的访问权限是公共权限 xff0c class默认的访问权限是私有权限 补充 xff1a 成员属性和成员
  • C++中STL容器的主要使用及含义

    1 stack栈容器的使用 假如栈中存放的是字符串 xff0c 我们做如下定义 xff1a stack lt string gt ss 设该变量名为ss 其主要用法如下 xff1a ss push a 存入栈中元素a ss top 读取栈顶
  • 电赛备赛记录第一篇(控制部分)

    2022 5 25 九校联赛备赛阶段第一天 联赛小车系统沿用去年国赛使用的树莓派驱动底板与外设 整车情况良好 xff0c 摄像头通信 连接均正常 xff0c 现已拼装完整 复产复工的初步成果为 xff1a 小车可以实现开机自启动的程序运行
  • 数据结构——栈详解

    1 栈 Stack 是一种线性存储结构 xff0c 它具有如下特点 xff1a xff08 1 xff09 栈中的数据元素遵守 先进后出 34 First In Last Out 的原则 xff0c 简称FILO结构 xff08 后进先出的
  • 双目相机标定

    一 运行环境 opencv2 windows vs 二 图像获取 分割 保存 参考博客opencv打开双目摄像头 图像切割保存 scutqq的博客 CSDN博客 双目图像分割 include amp lt opencv2 core core
  • uart1接收不定长度数据和发送:STM32 HAL库串口+DMA+IDLE空闲中断

    DMA增加 xff1a usart1 gpio 默认即可 usart1中断必须打开 在 STM32 中 USART 发送接收有三种基本方式 xff0c 轮询 中断和 DMA 1 轮询方式为堵塞模式 xff0c 使用超时管理机制 它每次接收一
  • 串口、网口等自定义通信协议的问题

    自定义通信协议的问题 一 串口1 通信分为网络通信和串口通信2 协议格式3 协议设计4 代码实现 二 网口1 TCP粘包与拆包 包的划分 出现TCP粘包的原因 粘包与拆包的几种情况 常见的粘包与拆包解决方案 2 为什么UDP没有粘包 xff
  • 如何理解奇偶校验位?

    奇偶校验位提供对传输数据的简单错误 xff08 奇偶校验 xff09 检查 此表描述奇偶校验的类型 奇偶校验类型 xff1a Even 描述 xff1a 数据位加上奇偶校验位产生偶数个1 xfffc 奇偶校验类型 xff1a Mark 描述
  • C语言----隐藏代码文件

    在C语言中 xff0c 常用的文件主要是后缀为 c的源文件以及后缀名为 h的头文件 我们通常使用头文件对函数进行声明 xff0c 使用源文件对具体的函数进行实现 有些时候会由于各种原因需要将函数的功能交给别人使用 xff0c 但是又不想将具
  • c++入门系列(三)之头文件

    1 什么是头文件 xff1f 在C语言家族程序中 xff0c 头文件被大量使用 一般而言 xff0c 每个C 43 43 C程序通常由头文件和定义文件组成 头文件作为一种包含功能的函数 数据接口声明的载体文件 xff0c 主要用于保存程序的
  • std::atomic_thread_fence

    在原子变量的存取上应用不同的memory order可以实现不同的内存序来达到数据同步的目的 xff0c 而在C 43 43 11及之后的标准里 xff0c 除了利用原子操作指定内存序 xff0c 还定义了单独使用 内存栅栏 xff08 s
  • 【数据结构】【期末复习】知识点总结

    算法 线性表 概念明晰 xff1a 随机存取 顺序存取 随机存储和顺序存储 随机存取 顺序存取 随机存储和顺序存储这四个概念是完全不一样的 xff0c 切不可将之混淆 很多人包括我可能认为随机存取就是随机存储 xff0c 顺序存取就是顺序存
  • 【单片机学习】51单片机【定时/计数器】,详细介绍

    51单片机学习 一 先知先会1 CPU时序的有关知识1 1 周期换算2 在学习定时器之前需要明白的3 定时 计数器的工作原理4 51单片机定时器结构 二 定时 计数器的控制1 工作方式寄存器TMOD2 控制寄存器TCON3 定时 计数器的工
  • 【跟着江科大学Stm32】GPIO_LED_流水灯_蜂鸣器

    只要坚持下来了 xff0c 一定会有收获 xff01 一 LED闪烁 span class token macro property span class token directive hash span span class token
  • STM32F103C8T6 PWM驱动舵机(SG90)

    小知识 xff1a 同一个定时器 xff0c 不同通道输出不同输出PWM的特点 对于同一个定时器的不同通道输出PWM xff0c 因为它们是共用一个计数器的 xff0c 所以频率必须一样 xff0c 而占空比由各自的CCR决定 xff0c
  • STM32 PWM周期与频率的计算

    文章目录 STM32 PWM周期与频率的计算频率的计算占空比的计算笔记仅供自学 xff0c 用来回看复习 xff0c 不一定适合你 xff0c 如有错误请指出 STM32 PWM周期与频率的计算 TIM TimeBaseInitTypeDe
  • STM32F103C8T6 实现舵机与电机的控制 2个定时器输出不同频率的PWM

    智能小家居 舵机开门 xff0c 电机做风扇 or 拉窗帘 呼吸灯做提示 xff0c 小OLED屏幕显示当前状态 文章目录 直接上代码main cpwm hpwm cservo hservo cmotor hmotor c笔记仅供自学 xf
  • 【学习记录】Tpro遥控器_暂时取消Tpro的控制权(简易)

    文章目录 按照如下图示配置1 设置好 96 逻辑开关 96 2 选择执行该 96 逻辑开关指令 96 的 96 通道 96 3 配置成功附 xff1a 继电器与R88的接法 按照如下图示配置 1 设置好逻辑开关 2 选择执行该逻辑开关指令的
  • 【Linux】gcc编译工具,断点的设置,gdb调试

    文章目录 注意1 在gcc编译过程中一定要加入选项 96 g 96 xff1b 2 只有在代码处于 96 运行 96 中在 96 暂停 96 状态时才能查看变量值 xff1b 3 设置断点后 xff0c 程序在指定行之前停止 总结主要内容1
  • 【Linux】信号量操作函数

    文章目录 二 实验原理1 semget 函数函数作用 xff1a 参数意义 xff1a 例子 xff1a 2 semop 函数函数作用 xff1a 参数意义 xff1a struct sembuf 结构体定义如下例子 xff1a 再来个完整