自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(37)
  • 问答 (1)
  • 收藏
  • 关注

原创 基于MQTT的智能家居系统的学习

sprintf()是一个用于将格式化数据写入字符串的函数。

2025-10-31 16:40:33 742

原创 基于STM32的智能天气时钟

定义一个名为的结构体变量,用于存储GPIO的配置参数。是库中定义的结构体类型,包含GPIO的所有可配置项。

2025-10-31 16:40:23 1019

原创 FreeRTOS---进阶知识4---通用链表

上面的代码本身是改进过链表的定义内容,但是如果需要将其他类型的结构体添加进链表时,就会出现代码冗余的问题。比如,需要重新定义结构体 struct bird{ },将 struct bird{ }也添加进链表,那么就需要重新写个代码这显然是有问题的。下面,将介绍通用链表操作,也就是说不管结构体的类型如何,只需要一个函数即可。

2025-10-26 16:52:19 354

原创 FreeRTOS---进阶知识3---改进的链表操作

在进阶知识1和进阶知识2中进行的链表操作实际上还有很大的提升空间,下面将仔细进行介绍。只是一个地址,指向某个person节点这个指针本身不存储任何人员信息是一个实实在在的person结构体它就"住"在list结构体内部注意:改进后的链表的操作涉及到下面简单回顾一下结构体的操作:根据结构体的定义可以知道,改进后的链表中:struct person head;,其中是类型,是结构体List的一个成员下面简单写一个结构体嵌套的代码:可以看到输入结果如下:从上面的例子看出,定义。

2025-10-26 16:51:46 953

原创 FreeRTOS---进阶知识1---列表的创建

在 FreeRTOS 中,列表(List) 是一种核心数据结构,用于高效管理任务、事件和其他内核对象。它本质上是一个 双向链表(Doubly Linked List)。每个列表()由多个 列表项() 组成,列表项之间通过 前驱() 和 后继() 指针连接。包含一个 尾节点() 作为哨兵节点(Sentinel Node),使遍历和插入操作更高效。FreeRTOS 列表通常用于任务调度(如就绪列表 ),因此其操作(插入、删除、遍历)必须保证 线程安全。在 SMP(多核)版本 的 FreeRTOS 中,列表可能涉

2025-08-20 16:12:48 1003

原创 FreeRTOS---进阶知识2---列表的删除

在之前的内容中我们提到,在中,本质上是一个每个列表(List_t)由多个ListItem_t组成,列表项之间通过pxPrevious和pxNext指针连接。包含一个xListEnd作为哨兵节点(Sentinel Node),使遍历和插入操作更高效。为了更好的理解列表的删除操作,下面先试用单向链表进行操作。这里要介绍指的是当前节点的。在双向链表中,但在单向链表中,我们需要手动维护前驱节点的信息。

2025-08-20 16:11:45 1023

原创 FreeRTOS---基础知识9---中断

在任务函数中,我们可以调用各类API()函数,比如队列操作函数:xQueueSendToBack。但是在中使用这个函数会导致问题,应该使用另一个函数:xQueueSendToBackFromISR,它的函数名含有后 缀"FromISR",表示"从ISR中给队列发送数据"。FreeRTOS中很多API函数都有两套:一套在任务中使用,另一套在ISR中使用。后者的函数名含 有"FromISR"后缀。为什么要引入两套API函数?

2025-08-18 10:49:25 1191

原创 FreeRTOS---基础知识8---软件定时器(Timer)

软件定时器是一种基于系统节拍(Tick)的计时机制,由操作系统(如 FreeRTOS)提供,用于在指定时间后执行回调函数或周期性任务。与硬件定时器不同,软件定时器完全由软件实现,不依赖特定的硬件资源,适用于任务调度、超时检测、周期性事件触发等场景。:依赖操作系统的 Tick 中断,精度取决于系统节拍周期(如 1ms/10ms)。:可在运行时创建、启动、停止或删除定时器。:触发一次后自动停止。:按固定间隔重复触发。默认在守护任务中执行(如 FreeRTOS 的 Timer Task也可配置为在。

2025-08-18 10:49:14 737

原创 FreeRTOS---基础知识7---任务通知

所谓"任务通知",你可以反过来读"通知任务"。我们使用队列、信号量、事件组等等方法时,并不知道对方是谁。使用任务通知时,可以:通知哪个任务。使用队列、信号量、事件组时,我们都要事先创建对应的结构体,双方通过中间的结构体通信:使用任务通知时,任务结构体TCB中就包含了内部对象,可以直接接收别人发过来的"通知":也就是说,// 任务通知特有字段// 通知值(32位数据)// 通知状态:任务不在等待通知:任务在等待通知:通知已收到但尚未处理。

2025-08-13 09:39:03 1031

原创 FreeRTOS---基础知识6---事件组

是 FreeRTOS 中用于和的高效机制,允许任务等待多个事件中的任意组合(按位操作)。

2025-08-12 17:39:12 461

原创 FreeRTOS---基础知识5---信号量

在二进制信号量基础上增加所有权和优先级继承。

2025-08-08 20:36:36 629

原创 FreeRTOS---基础知识4---队列

它是 FreeRTOS 内部用于管理队列状态的核心数据结构,包含。

2025-08-07 17:21:47 1129

原创 FreeRTOS---基础知识3---链表(列表)

例如在pxReadyTasksLists[4]中有高优先级任务Task1,pxReadyTasksLists[1]有低优先级任务Task2,Task3和Task4.那么系统将首先执行并且一直执行Task1,理解这些链表的结构和操作逻辑,是掌握调度机制的关键。例如如果Task1,Task2和Task3的优先级相同,那么Task1,Task2,Task3将依次执行。通过操作链表节点(插入、删除、遍历),实现任务状态的动态管理。:按优先级分组,调度器直接选取最高优先级的链表头部任务。,决定了任务的执行顺序。

2025-08-06 15:42:12 1058

原创 FreeRTOS---基础知识2---调度机制与Tick中断

FreeRTOS 是一个实时操作系统(RTOS),其核心功能是通过。

2025-08-02 17:44:58 1243

原创 FreeRTOS---基础知识1---寄存器、堆和栈、任务

POP{R3,PC},找到SP指向的地址,将当前SP地址的内容读入R3,此时SP=SP+4,再将当前地址的内容(也就是上面存入的LR寄存器的内容)读入PC寄存器中,然后SP=SP+4.PUSH{R3,LR}(大括号内寄存器不分先后顺序,也可写成PUSH{LR,R3}),找到SP指向的地址,先将LR的内容写入,然后是。在异常(如中断)发生时,R14 会保存异常的返回地址(但需注意模式切换时的特殊行为)。中断发生时,硬件自动使用当前任务的栈保存上下文(部分架构可能使用独立的中断栈)。

2025-08-01 15:35:15 880

原创 操作符习题练习

这是一个典型的斐波那契数列问题。可以使用递归或动态规划来解决。方法一:递归方法二:动态规划。

2024-10-28 09:55:13 826

原创 隐式类型转换

整数提升:当一个较低的整数类型(如char、short)与一个较高的整数类型(如int、long)进行运算时,较低的整数类型会被提升为较高的整数类型。扩展类型转换:当一个较短的整数类型与一个较长的整数类型进行运算时,较短的整数类型会被自动转换为较长的整数类型。截断类型转换:当一个较长的整数类型与一个较短的整数类型进行运算时,较长的整数类型会被截断为较短的整数类型。这样可能会导致运算结果的精度损失或溢出。在C语言中,隐式类型转换是指在表达式中自动将一个类型的值转换为另一个类型的值,而无需显式的类型转换操作。

2024-10-23 20:53:16 599

原创 C语言操作符详解

C语言中的算术操作运算符包括:(1)加法运算符(+):用于求两个数的和,如a + b。(2)减法运算符(-):用于求两个数的差,如a - b。(3)乘法运算符(*):用于求两个数的积,如a * b。(4)除法运算符(/):用于求两个数的商,如a / b。(5)取余运算符(%):用于求两个数的余数,如a % b。加、减、乘运算符没什么需要注意的地方,但是/和%需要注意一下。除法运算符(/):分为整数除法和浮点型除法:整数除法:1/2=0。

2024-10-22 20:45:58 1167 1

原创 扫雷小游戏

FindMine函数是游戏的核心逻辑,它在一个循环中接受玩家的输入,然后根据输入的坐标来判断该格子是否是雷,如果是雷则游戏结束,如果不是,则显示该格子周围的雷的数量,并判断是否已经排查完所有的雷。注:这里我们定义扫雷范围是9*9,但是在后续判断周边雷的数量时,对于边上的格子四周的访问时会出现数组越界的问题,所以要在9*9的基础上。如果一个方格周围的数字为2,则表示该方格周围有两个地雷,可以推断出其他未揭示的周围方格中有地雷。如果揭示的方格周围没有地雷,则该方格周围的8个方向的方格也会被自动揭示。

2024-10-12 21:15:36 713

原创 数组的练习

方法一:首先不采用递归的方法,如何完成上述要求运行结果如下所示:运行结果如下:函数的实现思路是利用递归,将字符串中的第一个和最后一个字符进行交换,然后不断缩小字符串的范围,直到字符串长度小于2。tmp\0上面的代码思路上可能有些复杂,也可以用下面一种方法运行结果与上面的一致。

2024-09-28 19:40:15 419

原创 三子棋小游戏

这里创建1个game.h文件,用来声明函数、宏的文件,一个game.c文件用来实现函数game(),一个play.h文件用来作为该游戏的源文件。使用C语言编写代码,实现一个简单小游戏---三子棋。3.play.c文件。1.game.h文件。2.game.c文件。

2024-09-24 19:42:19 824 1

原创 数组的学习

在C语言中,数组的声明格式为:类型名 数组名[数组长度];例如:int numbers[5];表示声明了一个包含5个整数的数组。数组的元素可以通过索引来访问,索引从0开始计数。例如,要访问数组numbers中的第一个元素,可以使用numbers[0]。这里定义了4个字符型数组,打开监视功能可获取这些数组的初始化内容,如下所示:观察数组ch1和ch2初始化内容一致,但数组ch3和ch4存放的内容不同,这是因为字符串是以字符“\0”为结束字符存放的,这里初始化时需要注意。

2024-09-05 20:28:50 1042

原创 函数的练习

这里我们可以看到,从主函数传递过去的arr变了,不再是数组,而是一个地址,类型由int变成int*,变成了指针,而指针的大小只有4(32位)或8(64位),这里我使用的是64位,所以。sizeof(arr)= 8,而sizeof(arr[0])= 4为一个int类型变量的大小,所以这里sz根本就不是数组的大小,所以运行结果错误。数组名就是数组首元素的地址,所以数组传参时,并没有把整个数组传递给形参,实际上只是传递的数组地址,所以函数里的arr实际上是一个指针变量。函数,用于求解两个数的最大公约数。

2024-08-08 21:32:55 1130

原创 函数的学习(三)

但是如果将加法函数看作是一个模块的话,就可以将函数声明放入头文件add.h中,将函数定义放入源文件add.c中,在主函数需要用到加法模块时,需要引入加法的头文件#include"add.h"即可。但需要注意的是,在使用递归函数时,必须确保递归能够终止,并且递归的层数不能太大,否则可能会导致栈溢出的问题。在上面的示例中,函数的定义中包含了函数体的具体实现,在函数体中定义了一个局部变量sum,计算a和b的和,并将结果返回。需要注意的是,函数的声明和定义必须一致,即参数类型、返回值类型和参数个数必须相同。

2024-08-07 20:28:17 1354

原创 函数的学习(二)

在C语言中,函数的嵌套是指在一个函数内部调用另一个函数。通过函数的嵌套,可以将程序的功能细化,提高代码的可读性和可维护性。函数的嵌套可以是直接嵌套,也可以是间接嵌套。直接嵌套是指一个函数直接在另一个函数内部调用的情况。上述代码中,calculate函数内部先调用add函数计算两个数的和,然后再调用subtract函数计算结果与第二个数的差,并返回最终结果。main函数通过调用calculate函数来获取计算结果。运行结果如下所示:通过函数的嵌套,可以实现程序的模块化和复用,提高代码的可读性和可维护性。

2024-07-31 20:50:19 1221

原创 函数的学习(一)

C语言中的用户自定义函数是指用户根据自己的需求定义的函数。通过自定义函数,用户可以将一些常用的代码封装在函数内部,方便重复使用。用户自定义函数的定义与声明分为两部分:函数声明和函数定义。函数声明用于告诉编译器该函数的存在和函数的参数类型和返回值类型。函数声明一般放在程序的开头,通常在头文件中进行声明。函数定义是函数的具体实现,包括函数的参数列表、函数体和返回值。函数定义一般放在程序的其他函数之后。// 函数声明// 函数定义return 0;

2024-07-27 20:13:39 2052

原创 关于使用VS 2022版本中strcpy()函数报错问题

函数的作用是将源字符串的指定个数字符复制到目标字符串中,同时可以指定目标字符串和源字符串的大小。如果不修改大小,就只能减少目标缓冲区的大小,如下所示,运行不会报错,但缺点是字符串复制不全。学习函数时,学到了strcpy()函数,本来打算练习一番,没想到出现了一系列的错误。函数是C语言中的一个字符串函数,用于将一个字符串复制到另一个字符串中。需要注意的是,函数的返回值是一个指向目标字符串的指针。函数可以指定要复制的最大字符数,以避免目标缓冲区溢出的问题。应该是一个足够大的字符数组,以容纳复制的字符串,而。

2024-07-25 20:43:16 4125

原创 关于循环语句练习二

需要注意的是,rand()函数生成的是伪随机数,它们是通过数学算法计算得到的一系列数字,而不是真正的完全随机数。(1)rand()函数: rand()函数用于生成一个0到RAND_MAX之间的随机整数。(2)srand()函数: srand()函数用于设置随机数生成器的种子值。要在C语言中生成1到100之间的随机数,需要使用rand()函数和srand()函数。要使用rand()函数,首先需要调用srand()函数来设置随机数的种子。在C语言中,rand()和srand()是用来生成伪随机数的函数。

2024-07-24 19:48:08 628

原创 关于循环语句的练习一

它的基本思想是:首先将数组(或列表)按照升序(或降序)排列,然后取数组中间位置的元素与目标元素进行比较,如果相等则返回该位置的索引,如果目标元素小于中间元素,则在数组的前半部分继续查找,如果目标元素大于中间元素,则在数组的后半部分继续查找。在C语言中,字符串的长度是根据空字符来确定的。在上面的示例中,字符串"Hello"和字符数组{'H', 'e', 'l', 'l', 'o', '\0'}的长度都是6字节,因为空字符也会占用一个字节的空间。空字符是一个特殊的字符,ASCII码为0,用来表示字符串的结束。

2024-07-22 21:35:54 909

原创 初识循环语句

使用循环语句可以方便地重复执行一段代码,节省编写重复代码的时间和精力。同时,需要注意循环条件的设置,以免导致死循环。

2024-07-19 19:14:09 2506

原创 初识分支语句

在C语言中,语句是一组按照特定规则编写的代码,它们被用于执行特定的任务。每个语句通常以分号 (;) 结束。C语言中有多种类型的语句,包括以下几种最常见的:表达式语句:最简单的语句类型之一,用于执行一个表达式,并丢弃其结果。x = 5;代码会执行一个赋值操作,将5赋值给变量x。控制流语句:用于控制程序的执行流程。常见的控制流语句包括条件语句(如if语句和switch语句)和循环语句(如for循环和while循环)。跳转语句:用于在程序中跳转到指定的代码位置。

2024-07-16 20:09:21 982

原创 初始结构体

在C语言中,结构体是一种用户定义的数据类型,用于将不同类型的数据组合在一起,以便更有效地操作和管理这些数据。结构体可以包含不同类型的成员,如整数、字符、浮点数、数组等,甚至是其他结构体。

2024-07-13 20:48:34 646

原创 冒泡排序---qsort函数

在C语言中,qsort函数是标准库中的一个函数,用于对数组进行快速排序。需要特别指出的是,该函数可以比较任意类型的数据。这个函数接受四个参数: 1.‘base’:指向要排序的数组的指针。2. ‘nitems’:数组中的元素个数。3. ‘size’:每个元素的大小(以字节为单位)。4. ‘compar’:指向比较函数的指针,该函数用于确定元素的顺序。比较函数‘compar’需要接受两个指向元素的指针,并返回一个整数值,表示这两个元素的大小关系。

2024-07-10 20:20:53 986

原创 指针参数和函数指针

在C语言中,函数指针是指向函数的指针变量。它允许你在程序运行时动态地选择要调用的函数。函数指针可以像普通函数一样被调用,这使得它们非常灵活和强大。函数指针在C语言中有许多应用,例如在回调函数、事件处理和动态函数调用等方面。它们允许程序在运行时根据需要选择要执行的函数,从而增加了程序的灵活性和可扩展性。

2024-07-06 21:21:06 1475

原创 初始数组指针

学习数组指针首先要与指针数组区分开,前面提到,指针数组是用来存放指针的数组,其本质上还是一个数组;而数组指针是用来存放数组地址的指针,其本质上是指针。

2024-07-01 20:35:51 725

原创 初始数组名

这里定义的数组是int(整型)类型,一个整型占4个字节大小,sizeof(arr)是计算整个数组的大小,所以显示的40个字节。从上面的结果可知,arr+1和&arr[0]+1的地址只增加了4个字节,说明这两个操作只是取出该数组的第二个元素的地址;arr和&arr[0]以及&arr,这三种取地址的操作,虽然取出的地址是一样的,但是&arr取出的地址是整个数组的地址,前两种的含义是一样,均代表数组首元素的地址。2.&数组名,这里的数组名表示是整个数组,所以“&数组名”取出的是整个数组的地址。

2024-06-29 21:35:53 332 1

原创 初识指针数组

运行结果与上面一致,从这里可以看出,指针数组就是存放指针的数组。如果还是不太理解指针数组存放的内容,可以看下面这个写法。指针数组是数组,是用来存放指针的数组。

2024-06-29 17:03:46 334

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除