自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(52)
  • 收藏
  • 关注

原创 数据类型讲解

E:阶码(无符号 8 位,范围 0~255,但 0 和 255 有特殊用途)把它当成二进制小数来算:从左到右分别是2的-1、-2、-3。注:那比如11100010....0(隐含前导 1 之外的部分)IEEE-754 规范里实际尾数是 1.M1.M1.M,所以。转换规则:保留数值,转换为 IEEE-754 表示。的 1 出现在第 1、2、3、4、7 位,所以。在内存里它的 IEEE-754 表示是。,没有小数部分,所以转换后就是。,用来表示有效数字的小数部分。M:尾数的小数部分(23 位)

2025-09-05 09:45:45 1078

原创 RT-Thread(三)

就是预先分配一大块连续内存,然后划分成固定大小的小块,用链表管理,后续申请和释放时直接操作链表。指向下一个空闲块的指针(典型实现是单链表,每个空闲块的前几个字节存放“下一块地址”)。每次申请/释放只是在链表里拿/还一个块,几乎是常数时间,毫秒级保证。每次分配/释放都要操作堆,可能产生碎片,速度慢,不可预测。如果 = 0,说明内存池耗尽,申请内存的线程可能会被挂起。等待,则唤醒其中一个线程,把刚释放的块分给它。这块内存会被切分成固定大小的块,用于分配。当释放一个内存块时,会唤醒链表里的线程。

2025-08-28 16:38:56 1181

原创 RT-Thread(二)

STM32/很多 MCU 的 GPIO 数量固定,而且系统中一般只有一个“GPIO 控制器”。MCU 上可能有多个串口(USART1、USART2…),每个串口是独立的实例。来保存 pin 的操作函数和状态即可,不需要动态分配。,整个系统只会有一套 GPIO/Pin 设备接口。需要为每个实例保存不同的配置、缓冲区、回调函数。在驱动文件里对多实例进行注册。等操作接口来访问这套全局。通过传入指针的方式,可以在。),注册时传入指针即可。

2025-08-26 16:33:56 879

原创 设计模式(2)

观察者模式 : 定义了 对象之间 一对多 的 依赖 , 令 多个 观察者 对象 同时 监听 某一个 主题对象 , 当 主题对象 发生改变时 , 所有的 观察者 都会 收到通知 并更新;抽象耦合 : 在 观察者 和 被观察者 之间 , 建立了一个 抽象的 耦合;循环调用 : 避免 循环调用 , 观察者 与 被观察者 之间 绝对不允许循环依赖 , 否则会触发 二者 之间的循环调用 , 导致系统崩溃;如 : 在购物网站 , 多个用户关注某商品后 , 当商品降价时 , 就会自动通知关注该商品的用户;

2025-08-14 16:33:08 348

原创 设计模式(1)

策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。第一个优点的表现就是在object的对象管理中,用数组与链表来维护,根据对象的type和name进行索引,而不是if else。把具体硬件的实现(不同厂商的驱动)封装成不同的“策略”,在运行时通过函数指针调用,不需要上层关心底层具体实现。

2025-08-14 09:58:43 393

原创 C语言属性讲解

*malloc 内部有一个头部(header)**存储块大小等信息,占 6 字节(只是示例,真实实现可能不同):底层 NAND/NOR Flash、SD 卡、SSD 块设备,通常要求访问按扇区对齐(512B、4KB)。:网络协议头(TCP/UDP/IP)有时会对齐到 4 字节或 8 字节边界,方便 CPU 快速解析。:DMA(直接内存访问)传输要求源/目的地址对齐到总线宽度(常见 4、8、16 字节)。:DMA 硬件一次搬一整个对齐宽度的块,不对齐会浪费带宽甚至出错。

2025-08-08 09:31:04 900

原创 RT-Thread(一)

RT-Thread记录(二、RT-Thread内核启动流程 — 启动文件和源码分析)_RTT_矜辰所致_InfoQ写作社区Yaochenger/RT-Thread-Source-Notes: RT-Thread内核源码中文注释源码解读·RT-Thread操作系统的任务(上)_51CTO博客_rt-thread操作系统的特点【万字长文慎点】RT-Thread 内核要点,一网打尽_RT-Thread_嵌入式操作系统论坛_MCU智学网 - Powered by Discuz! RT-Thread记录(十一、I/O

2025-08-04 09:16:16 1111

原创 C语言模块化编程

项目宏定义 (#define内联函数 (inline参数副作用风险高,可能多次求值低,参数只求值一次类型安全性无类型检查有完整类型检查调试友好性不可调试可调试编译器优化不一定优化优化空间更大(函数内联、死代码消除等)推荐使用场景非函数用途(如条件编译、常量等)函数行为替代宏①参数副作用风险int a = 3;// 展开为 ((a++) * (a++)) => a 被递增了两次!这个宏展开后变成,产生未定义行为(顺序不确定,副作用多次)。int a = 3;

2025-07-28 11:26:57 469

原创 C语言面向对象编程

list_head每一个list_head实际就是两个指针:指向下一个节点和上一个节点。宏 / 函数作用定义并初始化链表头初始化某个节点(通常用于结构体内嵌)添加到链表头部添加到链表尾部删除节点判断链表是否为空遍历链表(不获取结构体)遍历链表(获取结构体指针)安全遍历(可删除)

2025-07-22 16:23:31 414

原创 C语言数据存储与指针

在 C 语言中, 是 C99 标准引入的一个 类型限定符(type qualifier),用于指针,表示该指针是访问其所指向对象的 唯一方式。 的基本作用:告诉编译器:这样,编译器可以放心地进行优化,比如更激进地重排指令、消除冗余加载等。 上面函数表示:、、 指向的内存 不重叠。编译器可以假设:修改 不会影响 或 ,从而生成更高效的代码。若违反 的承诺:违反 的前提会导致 未定义行为(undefined behavior)。例如: 是一种承诺:“只有我会访问这块内存”,它能让编译器

2025-07-16 16:18:31 277

原创 如何避免使用布尔状态变量

①、主从状态机(使用枚举来标识状态)(消息地图/switch case)③尽量不要使用全局状态变量,尤其多核CPU时。⑤、使用函数返回值携带状态信息。​:将相关状态封装在结构体中。⑥、位域结构体管理相关标志。​:使用状态机隔离状态转换。​:每个函数只处理一种情况。​:用枚举类型明确状态含义。非常局部、临时的控制流标记。②、Linux的事件驱动。③、函数指针与策略模式。二、何时使用状态变量?

2025-07-03 16:02:38 295

原创 内存堆栈管理

在操作系统中,​​每个进程都有自己独立的虚拟地址空间,其中包括自己独占的堆空间。堆空间是进程私有的,不与其他进程共享。进程之间的内存在默认情况下不是共享的。但是可以有一种例外情况:共享内存。若需要多个进程共享内存,必须通过​。​,是专门申请的区域。

2025-07-02 11:31:01 252

原创 程序的编译、链接、安装与运行

​​链接地址(Link Address)​​是程序编译链接过程中使用的一个​​核心概念​​,指的是​​编译器(Compiler)和链接器(Linker)在生成可执行文件时,假定该程序未来将在内存中的某个特定地址运行​​。这个地址是程序内部所有​​绝对地址引用(如变量地址、函数入口地址、常量地址)的“基址”​​。就是在链接阶段,链接器 (ld) 并不知道程序最终会被加载到物理内存的哪个地址运行(可能是0x8000,也可能是0x87F00000,取决于硬件和启动方式)。所以需要​。

2025-06-26 14:09:02 713

原创 MCU堆栈问题

Flash (0x08000000): [代码(.text) | 只读数据(.rodata) | 初始化数据(.data的初始值)]RAM (0x20000000): [栈(Stack) | 堆(Heap) | .data段 | .bss段]Flash (ROM) 占用: [ Code ] + [ RO Data ] + [ RW Data的初始值 ]未初始化全局/静态变量​​在编译后的二进制文件中​。将.bss段对应的RAM区域全部初始化为0​​。但是在执行时占用RAM的地址空间​​。

2025-06-19 09:40:16 986

原创 CAN协议详解

粘包:CAN不会发生粘包。而232/485会发生粘包,所以需要每个帧之间有界定符或者帧之间的超时时间来划分。通讯对象:多点通讯(与485一样/232只能单点通讯)。双线通信,RX/TX。

2025-06-18 16:07:55 933

原创 libmodbus库讲解

modbus.c 并不直接定义 Modbus 的寄存器地址或寄存器数据。寄存器的定义与数据结构,实际上是由用户在自己的程序中自行定义的。而libmodbus提供的 API(如)是用来访问这些用户定义的数据的。下面边讲解如何定义边分析库中的结构体与函数。

2025-04-25 17:07:01 884

原创 Linux的时间函数

ucos中有systick这个系统时间滴答,那linux中有没有这种系统时间滴答呢?有,jiffies,但是用户空间不可以使用。那么在linux中除了使用timer定时器进行定时,可以通过时间滴答的方式来进行粗略的计时吗?下面介绍一下几个linux中使用的时间函数。

2025-04-24 16:02:46 776

原创 USART讲解

对于 RS-485 半双工通信,通常要控制一个 GPIO 用来切换收发方向(比如控制 MAX485 的 DE/RE 引脚(高电平发送,低电平接收))。TTL 串口:使用的是 TTL 电平(比如 3.3V 或 5V),直接连接到 MCU 的 USART 引脚。RS232 串口:使用的是 RS232 电平(±12V 或 ±5V),不能直接接到 MCU,需要芯片转换。常见的 USB 转串口芯片(如 CH340、CP2102、FT232)很多都是 TTL 电平输出。,要匹配 MCU 的供电;

2025-04-17 17:01:27 490

原创 ADS1118

主要参考ADS1118文档。以及部分转载自。

2025-04-17 15:39:42 1034

原创 看门狗WDG(待整理)

(如独立芯片型 WDG,比如 TI TPS3813、MAX706 等),那就不再依赖 STM32 内部的看门狗(如 IWDG 或 WWDG),但 MCU 软件仍然需要。,通常以 GPIO 引脚输出一个周期性脉冲或翻转电平的方式。如果一段时间没有检测到电平变化,它就触发复位(一般通过。此处我使用的是SGM706-SYS8G/TR这个外部芯片作为看门狗。的芯片,适用于系统稳健性设计。是看门狗输入口,MCU 必须。使用PA2作为输出引脚。

2025-04-10 11:19:22 698

原创 TIM定时器

其实重点在Flag和IT,前者是外设的状态标志,而后者是外设的中断标志。状态标志就是一个外设它有自身的一些标志位(Flag),来表明它处于什么状态。中断标志就是使能外设的中断后,每次发生一次中断,它会表明发生了什么样的中断,同样中断也有相应的标记。如果不清除该标志位,下一次进入中断时,标志位仍然为1,会导致反复进入中断,造成“死循环”现象。因此,需要在中断服务函数中调用此函数清除中断标志位。:指定的中断标志已经被置位,即中断已经触发。(如更新中断、捕获比较中断、触发中断等)。:状态寄存器,包含中断标志位。

2025-04-08 14:49:57 883

原创 ucos-ii使用讲解

让出 CPU,任务从。(等待时间到期后回到。

2025-04-03 09:38:53 564

原创 时钟RCC讲解

当CPU从Flash读取数据时,预取缓冲区会提前加载相邻的连续数据块(例如64位或128位),减少后续访问的延迟。如果外部晶振损坏,或者电路板设计不合理,可能导致 HSE 启动失败,此时需要回退到 HSI 作为系统时钟。(如 48MHz),推荐开启预取缓冲区,以减少 Flash 访问延迟,提高 CPU 执行效率。HSE 启动需要时间,因此不能直接切换到 HSE,而是需要等待 HSE 稳定。,即使关闭预取缓冲区,Flash 访问也不会有太大延迟,是否开启影响不大。

2025-04-01 08:40:45 754

原创 EXTI讲解

当你需要配置外部中断时,首先必须用该函数将 EXTI 线路与正确的 GPIO 端口/引脚映射起来,然后再配置 EXTI 中断线的触发方式(上升沿、下降沿或双边沿)和 NVIC 中断优先级等。将指定的 GPIO 端口和引脚映射到相应的 EXTI 线路上,从而使得该引脚的外部事件(如电平变化)能触发对应的中断。特指由 GPIO 引脚电平/边沿触发的中断,两者在触发机制和配置方式上有本质区别。等),用于指定 GPIO 端口中的哪个引脚映射到 EXTI 线路上。,由 SPI 模块内部事件触发,与外部引脚无关。

2025-03-28 17:14:43 633

原创 NVIC讲解

比如组2来说:2位配置抢占式优先级(00 01 10 11)换成十进制不就是0~3嘛,2位配置响应式优先级0 ~3,数字越小优先级越高其他分组以此类推。注意:组1抢占式优先级0位,那就没有抢占式优先级,配置分组在系统代码执行的过程只进行一次中断优先级分组,设置分组之后一般不会进行变动,不然中断执行会混乱,如:假设你分成组2,抢占式优先级有2位,后面改成组3的话,就会变成3位抢占式优先级,则之前的一位响应优先级变成了抢占式优先级,则之前配置的抢占式和响应优先级的值就不确定了乱套了。

2025-03-28 16:33:26 770

原创 SystemTick

SystemTick 是 ARM Cortex-M 系列中一个 ​可选的硬件定时器,主要用于提供周期性中断(如 RTOS 的系统节拍)。对于CM3、CM4内核芯片,都有Systick定时器。Systick定时器常用来做延时,或者实时系统的心跳时钟。这样可以节省MCU资源,不用浪费一个定时器。比如UCOS中,分时复用,需要一个最小的时间戳,一般在STM32+UCOS系统中,都采用Systick做UCOS心跳时钟。

2025-03-28 09:21:19 615

原创 SPI协议

SPI是常用的通信手段之一,经常使用,但也经常踩坑;网上资料很多,但对于CS/NSS使用的讲解比较少,正好最近使用SPI也遇到了一些问题,记录一下。SPI中NSS作用和用法简单来说,NSS和CS是一个东西,主要用于片选从机的。SPI控制器上连接的内部NSS引脚。NSS硬件模式和软件模式:可以通过寄存器配置,选择将内部NSS引脚连接到SSI寄存器,使用寄存器控制NSS电平,也可以选择内部NSS引脚和外部真正的NSS GPIO相连,由外部引脚电平来控制NSS。我画了一个关系图,可以清晰的看明白NSS的控制流

2025-03-26 11:16:16 966

原创 GPIO详解

*!/*!/*!/*!/*!/*!/*!/*!/*!/*!成员变量地址偏移描述MODER0x00GPIO 端口模式寄存器(输入/输出/复用/模拟)OTYPER0x04GPIO 端口输出类型寄存器(推挽/开漏)OSPEEDR0x08GPIO 端口速度寄存器(低速/中速/高速)PUPDR0x0CGPIO 端口上拉/下拉寄存器IDR0x10GPIO 输入数据寄存器(读取引脚电平)ODR0x14GPIO 输出数据寄存器(控制引脚输出)BSRR0x18。

2025-03-25 16:06:16 753

原创 attribute属性

简单来说,map文件就是通过编译器编译之后,生成的程序、数据及IO空间信息的一种映射文件,里面包含函数大小,入口地址等一些重要信息。程序各区段的寻址是否正确程序各区段的size,即目前存储器的使用量程序中各个symbol的地址各个symbol在存储器中的顺序关系(这在调试时很有用)各个程序文件的存储用量。

2025-03-14 15:45:36 765

原创 linux设备树

reg = <0x10000000 0x02000000 0x10000>这种情况我们64位的地址就是高32位是0x10000000,低32位是0x02000000的64位地址所以他代表的地址空间就是:0x1000000002000000 + 0x10000的地址空间。off2=这里((1<<32)|(0))就是我们ranges=<1 0 0x0a000000 0x02000000>的前两个数字组成的64位地址,(即0x1代表高32位,0x0代表低32位)对于#address-cells = <1>;

2025-03-09 17:17:39 1108

原创 NFS服务开启、配置、ubuntu(18.04)、PC、开发板互ping

若局域网是其它网段,请参考此处的配置,不能直接用星号表示,如欲配 置192.168.1.* 的局域网下所有机器都可以访问,则配置为 192.168.1.0/24。anongid=998: 将客户机上的用户映射成属于指定的本地用户 组ID,此处998是开发主机embedfire用户组gid,此处请根据具体的主机用户组gid进行配置。anonuid=998:将客户机上的用户映射成指定的本地用户ID的用户,此处998是开 发主机embedfire用户的uid,此处请根据具体的主机用户uid进行配置。

2025-02-26 13:48:05 358

原创 timerfd事件驱动

如果不读取它,它会一直存在,直到你处理它。未处理的定时器事件就会累积,因此你会看到它一直触发。如果你希望定时器只触发一次并停止,或者在每次触发后清空计数值,你必须在程序中通过。假设我们创建了一个定期触发的定时器,每10秒触发一次。来读取定时器的计数值,从而让内核清除已触发的计数并停止继续触发。时,它会定期触发并将计数值写入文件描述符。,触发的计数值不会被清除,内核会一直写入新触发的次数。触发时,内核会向文件描述符写入一个 64 位的值(这个值表示定时器已经触发的次数。并不断积累触发次数,直到你读取它。

2025-02-21 11:09:03 471

原创 linux基礎(一)

每一行的内容由 7 个字段组成,字段之间用冒号(

2025-02-06 19:24:23 149

原创 事件驱动机制

即使你一次性读取了所有数据,也需要确保文件描述符是非阻塞的,以避免循环读取时出现阻塞情况。在这种情况下,哪怕你已经读取了所有数据,仍会收到冗余的事件触发(性能浪费)。在高性能场景中,尤其是数据到达分批或者延迟的情况下,依然更具优势。都会返回文件描述符的事件,直到缓冲区被清空(即数据被完全读取)。操作中读取了所有数据,ET 模式下就不会再收到事件触发。检测到缓冲区有数据后都会通知你,直到数据被完全读取。如果你每次只读取 512 字节,就会触发多次事件。模式一次性读取所有数据,减少了多次触发的开销。

2025-01-16 16:13:22 865

原创 mosquito库函数

来启动一个后台线程,该线程会负责处理消息队列中的事件(包括接收和发送消息)。中的处理逻辑时间较长(比如循环处理),会阻塞主线程,无法立即处理新的消息。不被调用,所有的事件(包括消息接收和发送)都在主线程中处理。函数会在接收到消息时被调用,但如果。可以被异步调用,而不会阻塞主线程。

2024-12-31 16:39:32 454

原创 POSIX消息队列

mq_close只是关闭进程对队列的访问,不会删除队列本身。mq_unlink需要显式调用,以确保删除队列并释放系统资源。如果不调用mq_unlink,可能导致消息队列在文件系统中残留,造成资源泄漏。所以,在使用完消息队列后,建议总是调用mq_unlink来显式删除队列,确保系统资源得到释放。

2024-12-30 16:05:47 703

原创 信号量处理

此函数若被多个进程调用的话,其结果可能是未知的,因为当(**)语句刚执行完后,另外一个使用本函数的进程可能正好被激活,那么当新激活的进程执行到此函数时,将使 Exam 赋与另一个不同的 para 值,所以当控制重新回到 “temp = Square_Exam( )” 后,计算出的temp很可能不是预想中的结果。一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误;那么如下函数不具有可重入性。

2024-09-25 09:52:21 959

原创 Makefile编译脚本

操作符可以定义一个条件变量,即如果该变量尚未定义,则将其设置为指定的值。述代码中,.c文件列表SOURCES的每个元素将被转换为对应的.o文件,并将结果赋值给变量OBJECTS。,即将变量的值在赋值时进行解析,并将解析结果作为变量的值。这意味着,在赋值时不会发生变量的延迟展开,而是立即获取变量的值。上述代码的意思是,如果变量CFLAGS尚未定义,则将其设置为"-O2",否则不对其进行重新赋值。上述代码将会立即获取当前目录下所有以".c"结尾的文件,并将其赋值给变量SOURCES。在Makefile中,?

2024-04-20 15:28:14 1019

原创 Linux编译内核步骤

进入 Linux 内核官网下载 Linux 内核 , 点击右侧 黄色的 " Latest Release "在这里插入图片描述按钮 , 下载最新的 Linux 内核发布版本;最新版的 Linux 内核有 122MB;

2023-11-15 09:00:48 560 1

原创 GCC编译与链接

源文件中明明包含了头文件,为啥编译时还是会出现未定义的引用?_引用了头文件但是还是未定义-CSDN博客Linux下undefined reference to ‘pthread_create’问题解决_undefined reference to `pthread_detach-CSDN博客库依赖错误导致main.c:(.text+0x7): undefined reference问题_undefined reference to `atan-CSDN博客ubuntu下 libevent库安装和简单测试_u

2023-10-30 14:38:17 64

空空如也

空空如也

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

TA关注的人

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