自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 ADXL345 SPI加速度传感器Linux驱动开发笔记

本驱动实现了基于SPI接口的ADXL345三轴加速度传感器在Linux系统中的访问,通过miscdevice设备框架向用户空间提供数据读取接口。

2025-10-29 21:46:35 797

原创 i.MAX6ULL Linux LED 字符设备驱动代码分析

define MAJOR_NUM 248 // 主设备号#define MINOR_NUM 0 // 次设备号#define DEV_NAME "led" // 设备名称#define CLASS_NAME "led_class" // 设备类名称// GPIO寄存器物理地址#define GPIO1_SW_MUX_CTL 0x20e0068 // 复用控制寄存器。

2025-10-21 21:42:44 503

原创 i.MX6ULL Linux内核启动流程深度解析

1. "Boot ROM依赖":ARM SoC特有的芯片固化启动代码2. "DCD配置关键性":DDR初始化在Bootloader运行前完成3. "设备树核心地位":完全替代x86的BIOS信息传递机制4. "渐进式MMU启用":需要在汇编阶段手动创建初始页表5. "驱动初始化层级化":通过initcall机制确保正确的初始化顺序理解i.MX6ULL的完整启动流程,对于嵌入式Linux开发、系统调试和性能优化都具有重要意义。

2025-10-21 20:41:30 527

原创 嵌入式ADC应用详解:工作原理、参数计算与选型

基准电压 = ADC 用来量化模拟输入的“标尺”。数字输出 = (Vin / Vref) × (2^N − 1) ,其中 N 为分辨率。要求:低噪声、低温度漂移通常用专用电压基准芯片(如 TL431、REF3030、ADR440)或高精度 LDO。常见值:1.024 V、2.048 V、2.5 V、3.0 V、3.3 V、5.0 V。注意:Vin 不得超过 Vref(多数器件 Vin ≤ Vref)。

2025-09-29 19:10:16 590

原创 I2C总线通信实战:线与特性应用与时序控制要点

START (S)SDA 从高到低的跳变,且 SCL 保持高电平。作用:复位所有从机移位器,准备接收 7 位地址 + R/W̅。STOP (P)SDA 从低到高的跳变,且 SCL 保持高电平。作用:结束当前传输,释放总线,从机返回空闲。

2025-09-28 19:31:48 431

原创 嵌入式通信核心概念:同步异步、串行并行与工作模式

嵌入式系统中的通信是指两个或两个以上的主机之间的数据互交。

2025-09-28 09:22:12 921

原创 从轮询到中断:i.MX6ULL GPIO按键处理机制深度解析

1. 初始化 4 大步① 复用 IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B代码:IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);② 电气 IOMUXC_SW_PAD_CTL_PAD_UART1_CTS_BHYS=0 PUS=11b(22 kΩ上拉) PUE=1 PKE=1 ODE=0 SPEED=10b(100 MHz) DSE=000(输出禁用) SRE=0。

2025-09-24 20:30:12 885

原创 ARM裸机编程核心:编译工具链与GPIO控制原理

①找到引脚MUX寄存器地址(IOMUXC_SW_MUX_CTL_PAD_GPIO3_IO03=0x020E_0068)②找到PAD寄存器地址(IOMUXC_SW_PAD_CTL_PAD_GPIO3_IO03=0x020E_02F4)配置驱动强度、上下拉、压摆率(DSE、PUS、SRE),保证电流够用且EMI达标。源码->汇编器->目标文件->链接器->ELF->格式转换->BIN/HEX。确认LED挂在哪个GPIO(例如GPIO3_IO03→引脚名GPIO_3)。记下 DR、GDIR、PSR 偏移。

2025-09-23 20:02:01 499

原创 冯·诺伊曼与哈佛架构深度对比:ARM体系结构特点

--是一种集成和设计的理念,像一个蓝图,将市政府(MPU)警察局(MCU)研究所(DSP)机场(调制解调器)放在同一片土地(芯片)上,组成了一个功能完善的芯片。DSP(Digital Signal Processing):数字信号处理器 ---是为了高强度数学运算而设计的一种专用芯片。(3)CPU(Center Processing Unit):中央处理单元 ---是一种强大通用型处理器。MPU(Mirco Processing Unit):微处理器 ---通用型,偏向处理。

2025-09-19 19:28:56 1893

原创 HTML网页设计基础:标签使用与表单创建指南

<title>中文测试</title>

2025-09-09 20:47:22 791

原创 SQLite3核心操作:数据库维护命令与标准SQL语句

select *from user order by id(从小到大根据id排序,逆序后加desc) limit 2(只用前2条)///删除id=1 的数据;create table 表名 (表字段 类型,表字段 类型,。///删除表中所有数据。create table 表名(表字段1,表字段2,...);注意:以上表的表字段,支持如下数据类型。.help 出现所有相关的系统维护命令,都是以 "."开头。.dump user(示例) 导出数据库。

2025-09-08 19:16:02 1525

原创 IO多路复用核心技术:fcntl、select、epoll实战

单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力。

2025-09-06 09:09:07 505

原创 协议头部格式详解:IP、TCP、UDP与MAC帧结构

封包 是指在发送数据时,将数据从高层协议封装到低层协议的过程。每经过一层协议,数据都会被加上相应的协议头(有时也会加上协议尾),形成一个新的数据单元,直到数据被封装成可以在物理介质上传输的帧。每经过一层协议,数据都会被去掉相应的协议头(有时也会去掉协议尾),直到数据被还原为应用层数据。传输层协议(如TCP或UDP)将应用层数据封装成传输层数据段(Segment)。数据链路层协议(如以太网)将网络层数据包封装成数据链路层帧(Frame)。网络层协议(如IP)将传输层数据段封装成网络层数据包(Packet)。

2025-09-04 19:10:07 997

原创 从连接到关闭:TCP网络编程完整流程与实现细节

在connect()和accept()之间,内核自动完成了 TCP 的三次握手,确保双方都准备好收发数据。:你无需在代码中手动实现握手,但必须理解connect()会阻塞直到握手成功或失败。

2025-09-03 19:12:08 850

原创 网络编程基础:OSI模型、TCP/IP与UDP协议详解

数据链路层,负责物理相邻(通过网络介质相连)的主机间的数据传输,主要作用包括物理地址寻址、数据帧封装、差错控制等。物理层,负责把主机中的数据转换成电信号,再通过网络介质(双绞线、光纤、无线信道等)来传输。src_addr 可选,表示对方的地址信息结构体,如果为NULL,表示不关心对方地址。注意:socket()的参数需要调整,bind()客户端是可选的,服务器端是必选的。len 要获取的数据长度,一般是buff的大小。buff 本地的数据存储,一般是要发送的数据。

2025-09-03 19:03:10 618

原创 共享内存核心操作:shmget、shmat、shmdt与shmctl

proj_id 整形的数字,一般用ASCIl码的单字符。表示与参数1的运算。shmaddr 本地可用的地址,如果不确定则用NULL,表示由系统自动分配。通过该函数可以将pathname指定的路径用来以projid生成唯一的临时键值。(1)IPC_PRIVATE固定的私有键值,其值等于 0x0。key ==》申请对象==》映射对象==》读写对象==》撤销映射"==》删除对象。修改共享内存属性,也可以删除指定的共享内存对象。将指定shmid对应的共享内存映射到本地内存。

2025-09-01 20:38:28 435

原创 IPC通信实战:管道创建、信号发送与捕获处理

①匿名存在:没有文件名,只在内存中存在。 ②亲缘要求:只能用于父子进程或兄弟进程间通信。 ③临时性:管道随进程的结束而自动销毁。#include <unistd.h>#include <stdio.h>#include <stdlib.h>int main() { int pipefd[2]; // pipefd[0]用于读,pipefd[1]用于写 pid_t pid; char buf[256]; // 1. 创建管道

2025-09-01 20:27:57 640

原创 线程同步核心技术:互斥锁实现与信号量操作

pthread_mutex_t mutex;int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *attr);功能: 将已经定义好的互斥锁初始化。参数: mutex要初始化的互斥锁 atr 初始化的值,一般是NULL表示默认锁返回值: 成功 0 失败 非0Int pthread_mutex_lock(pthread_mu

2025-09-01 20:00:36 2430

原创 Linux线程编程完全解析:创建、属性设置与清理函数

通过该函数可以将指定的线程资源回收,该函数具有阻塞等待功能,如果指定的线程没有结束,则回收线程会阻塞。4、proc(大任务),thread(大任务中的小任务)。1、创建的开销,proc 3G,thread 8M。attr 线程属性,,一般是NULL,表示默认属性。3、稳定性,proc稳定,thread(不稳定)。注:进程是系统中最小的资源分配单位,线程是系统中最小的执行单位。retval 线程退出时候的返回状态,临死遗言。线程是轻量级进程,一般是一个进程中的多个任务。1、线程和进程相比,稳定性,稍微差些。

2025-08-27 19:54:54 685

原创 Linux进程管理进阶:状态回收、非阻塞等待与exec原理

后,进程ID(PID)、父进程ID(PPID)、文件描述符、信号处理方式等大部分属性保持不变,但进程的代码段、数据段、堆栈段被新程序完全替换。它们用于将当前进程的映像替换为一个新的程序。它是在当前进程的上下文中,停止执行原有的程序代码,转而加载并执行一个新的程序。该函数可以阻塞等待任意子进程退出并回收该进程的状态。2)如果一个子进程终止,正在等待的父进程则获得终止状态,获得子进程的状态后,立刻返回。子进程退出时候的状态,如果不关注退出状态用NULL。如果要回收进程退出状态,则用WEXITSTATUS回收。

2025-08-27 19:41:05 780

原创 Linux进程生命周期:创建、运行、终止与僵尸进程

退出状态,终止的进程会通知父进程,自己使如何终止的。任何情况下,负进程都能使用wait,waitpid获得这个状态,以及资源的回收。子进程是进程的副本。2)exit,c库函数,会执行io库的清理工作,关闭所有 的流,以及所有打开的文件。④子进程复制父进程的0到3g空间和父进程内核中的PCB,但id号不同。进程是一个程序执行的过程,会去分配内存资源,cpu的调度。Linux中的状态,运行态,睡眠态,僵尸,暂停态。0-3G,是进程的空间,3G-4G是内核的空间。①克隆的进程称为子进程,原有的进程称为父进程。

2025-08-25 19:48:58 813

原创 字符串转数字函数对比:atoi、strtol与sscanf选择指南

函数优点缺点推荐使用场景atoi简单易用无错误检查,溢出行为未定义快速转换,确定输入肯定有效strtol有错误检查,支持多种进制稍复杂需要验证输入的有效性sscanf灵活,可一次转换多个值性能较差需要复杂格式解析。

2025-08-21 10:16:07 601

原创 数据结构链式存储:单链表实现与核心算法

为了表示每个数据元素,ai与其直接后继数据元素ai+1之间的逻辑关系,对ai来说,除了存储其本身的信息外,还需要存一个指示器直接后续的信息。把存储元素信息的域叫数据域,把存储直接后继位置的域叫指针域。这两部分信息组成数据元素ai的存储映像,叫结点(Node);线性表链式存储结构的特点是一组任意的存储单位存储线性表的数据元素,存储单元可以是连续的,也可以不连续。可以被存储在任意内存未被占用的位置上。在链式结构中还需要一个元素存储下一个元素的地址。--- 解决顺序存储的缺点,插入和删除,动态存储问题。

2025-08-19 20:05:45 180

原创 数据结构核心概念:逻辑结构、算法特性与线性表ADT

当线性表元素的个数n(n>=0)定义为线性表的长度,当n=0时,为空表。在非空的表中每个元素都有一个确定的位置,如果a1是第一个元素,那么an就是第n个元素。链式,数据存放的存储单位是随机或任意的,可以连续也可以不连续。注:O(1)<O(logn)<O(N)<O(nlogn)<O(n^2)<O(n^3)<O(2^n)<O(n!如果存在多个元素,第一个元素无前驱,最有一个没有后继,其他的元素只有一个前驱和一个后继。②有穷性,执行的步骤会自动结束,不能是死循环,并且每一步是在可以接受的时间内完成。

2025-08-18 17:58:55 898

原创 Linux目录操作详解:opendir、readdir与stat函数

失败 NULL并且且errno会被设置。成功 读到的某一个目录下的结构体指针。@pathname 要打开的文件。从dirp中读取目录项,返回对应一个结构体。失败 NULL&&errno。失败 -1&&errno。失败 -1&&errno。@name 要打开的目录文件的文件名。打开一个目录文件关联一个目录流。成功 目录流指针。@dir 要操作的目录流指针。@dirp 目录流指针。成功 0。

2025-08-16 14:30:32 288

原创 C语言文件缓冲与系统调用详解:缓冲类型与文件IO

注:文件往后的偏移量如果大于文件本身是可以的,如果想占有存储空间,必须要有写操作,多出来的空间 --- 空洞 -- 用'\0'填充。1k,terminal,主要用于人机交互stdout,缓存区满或者遇到\n刷新,行缓存多是关于终端的一些操作。文件IO,文件由编号(文件描述符)体现,文件描述符就是一个编号--代表打开文件,数值---是一个非负整型值。4k,主要用于文件的读写,缓存区满刷新缓存区,对普通文件进行标准IO操作,建立的缓存一般为全缓存。表示创建文件的权限,只有前面有O_CREAT时,才需要指定。

2025-08-13 20:31:39 748

原创 C语言文件编程完全指南:标准I/O函数与文件流操作

2.fgets读取遇到EOF会结束,遇到'\n'//'\n'会被读取到buffer中,读满size-1也会结束。从指定的文件中stream读取nmemb个元素,每个元素size大小的这么多个数据,存放到ptr指定的一块空间。fgets 和fputs 实现拷贝文件,对于二进制文件--问题很大,二进制文件中存储大量的\0。将ptr所在空间的nmemb个大小为size的元素,写到stream对应的文件中。关闭流指针,并且刷新流中的数据到指定位置 //关闭底层的文件描述符。⑥a+ 追加的读写。

2025-08-13 10:33:40 695

原创 Shell脚本编程核心:环境变量、条件判断与循环语句

Eg:var=10 //shell中不需要类型,直接给变量名就行注意:自定义变量书写时等号左右两边不能有空格。

2025-08-13 10:17:00 605

原创 C语言typedef与位运算详解:类型别名与二进制操作

/a就是int的别名,代表int类型。---区别在于移动的数据是否有符号。②算术右移//有符号,最后高位补符号位。--- 二进制位的运算。①逻辑右移//默认最高位 补0。控制二进制进而控制硬件。注:不使用第三方变量实现数据交换。(1)嵌入式通过位运算控制硬件。加密、不使用第三方变量实现交换。(1)作用:给已有类型起别名。(3)逻辑右移和算术右移。

2025-08-13 09:40:11 211

原创 掌握C语言自定义类型:结构体、共用体与枚举应用

在实际使用中,我特别注意到了结构体初始化的顺序要求,以及通过成员运算符(.和->)访问成员变量的方式差异。这些特性的学习让我认识到,C语言虽然接近底层,但通过结构体等复合数据类型,仍然可以构建出高度抽象的数据模型。结构体与qsort函数的配合使用让我印象深刻。提供给用户可以自定义一种数据类型 --- 程序员根据问题的需要,自己组织的数据类型,可以描述现实生活中一些基本数据类型不好描述的场景,结构体可以把不同类型的数据集合在一起。所谓"枚举"是指将变量的值一一列举出来,变量的值只限于列举出来的值的范围内。

2025-08-08 20:24:24 312

原创 C语言多级指针解析:指针数组、二级指针与内存管理

/ s本身是数组,数组传参只需要传递首元素地址即可,此时首元素是s[0]//s[0]的数据类型是char*。指针是 C 语言中最为强大也最为复杂的特性之一,它提供了对内存地址的直接操作能力,是理解 C 语言核心机制的关键。①函数可以返回地址,但是,不能是局部变量(auto--栈上)的地址,auto的局部变量的生命周期随着函数调用开始存在,函数调用结束销毁。//ps是个形参变量,放的是传过来的数组名(数组名代表的地址)---首元素地址。//这元素--- 打印的是首元素的值,是hello的地址。

2025-08-07 18:40:35 382

原创 C语言指针进阶:const修饰、数组操作与快速排序实现

通过const关键字,我可以在函数参数中明确指出哪些数据是不应该被修改的,这不仅提高了代码的可读性,还有助于避免潜在的错误。//const 用来修饰基类型 --- 限定基类型为只读 --- 不能通过*p修改,相当于限定了*p为只读。//"hello"本身是字符串常量,存放字符串常区//"hello"字符串都是按字符数组的方式存储的。//本身的空间在栈上,s是char*的指针变量,用来存放一个char*的地址。//s本身的空间在栈上,"hello"本身是字符串常量,存放字符串常量区。

2025-08-06 17:51:54 391

原创 掌握C语言指针:地址传递、间接修改与指针运算详解

一、指针---c语言重点,是可以直接使用硬件的方式1.认识指针(1)指针就是地址,地址就是内存单元编号。(2)地址本身是特殊的数据--- 是具有指向含义的整数,c语言为了能够表示这种特殊的数据专门设计一种数据类型。--- 指针类型2.定义指针(1)语法:基类型 * 指针变量名;(2)基类型基类型说明了通过指针找到的空间多大,怎么用。是指针找到的空间上的所储存的数据类型。(3)*修饰符,用来说明现在定义的变量不是普通变量而是指针变量。(4)指针变量名是个标识符,符合标识符命名规则。

2025-08-05 20:10:19 295

原创 GCC编译全过程解析:从预处理到链接的完整流程

预处理、编译、汇编、链接四阶段 toolchain 的拆解,让我第一次把“写下的.c”与“跑起来的 ELF”之间的黑盒打开:宏在预处理期做纯文本替换,因此必须加括号避免副作用;链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体。<> ---表示找包含的文件,到系统默认的路径寻找,系统默认的头文件一般用<>。这个文件的含义同没有经过预处理的源文件是相同的,但内容有所不同。

2025-08-04 17:32:51 775

原创 C语言数组作为函数参数:传递规则与内存原理分析

/a空间被开在了静态区 --- 静态变量//这个a的生命周期成为了全程序的生命周期。4.如果是不同的作用域,但是作用域之间存在嵌套关系,则内层的作用域的同名标识符会屏蔽外层的作用域的同名标识符(就近原则)。7.局部变量 --- 从代码执行到对应的定义,开始存在,到所在作用域结束。8.全局变量/静态变量 ---从程序开始到程序结束(全程序的生命周期)6.时间概念 --- 变量的生命周期(变量,开始存在到销毁)(5)局部变量 --- 定义在局部作用域的变量。形参 二维数组形式 行数形参。

2025-08-01 20:55:34 257

原创 C语言函数核心知识:设计原则、嵌套调用与递归实现

尤其把数组名当指针传递后,我真正理解了“地址 + 长度”这对黄金搭档:数组连续存放的本质让 int *a 与 int a[] 等价,而长度参数则补足了指针丢失的维度信息。c语言中所有标识符--先定义,后使用,main的数是整个程序的入口函数,定义的位置在main之前,如果在main之后,在使用前在做一下函数声明(将函数头复制加上分号)。若改为动态二维数组,则需 malloc 到堆,再手动释放,避免内存泄漏。//从值的角度 --- 数组名代表首元素的地址,因为数组的特点:连续性,有序性,单一性。

2025-07-31 19:37:07 726

原创 C语言字符串操作与二维数组详解:常用函数与多维结构

注:字符串比较的规则与其他语言中的规则相同,即:对两个字符串"自左至右"逐个字符相比(按ASCII码值大小比较),直到出现不同的字符或遇到'\0'为止。时,突然理解了“数组名退化”与“指针等价”的真实含义:语法上的维度消失了,内存里依然是连续的一片字节。int[4] a[3] ---定义了一个可以包含3个int[4]的一维数组。二维数组的本质还是一维数组,是数组的数组,符合数组的特点,按行优先存储。s[5] --- 相当于是内部的 一维数组的数组名。@s ---可以传字符串数组名。

2025-07-30 20:24:42 329

原创 C语言三大排序算法解析:选择、冒泡、插入排序实现

将数组第一个数插入另一个数组的第一个数,将第一个数组的第二个数与另一个数组的第一个数进行比较,若大于则插入另一个数组的第二个数,否则另一个数组的第一个数后移,第一个数组的第二个数插入另一个数组的第一个数,后续依次类推完成排序。将数组第一个数与后面的数依次比较且交换,然后继续将第二个数与后面的数依次比较且交换,重复该过程直到排序成功。@s --- 需要的是一个字符串的首地址//传字符型数组的数组名即可或字符串。//数组类型 ---表示这是一个能够存放10个int类型数据的数组;

2025-07-29 19:36:38 408

原创 C语言循环结构与数组详解:从流程控制到数据集合

循环语句中,while与do-while的区别让我明白“先判断”与“先执行”的微妙差异,而for循环的紧凑语法则将初始条件、判断、更新操作优雅地整合在一行,极大提升了代码的可读性。Step4:求解表达式3,表达式求解完,继续step2-3-4,直到step2表达式为假,假表示for循环语句结束,程序继续往下。---数组长度省略的情况下,必须要有初始化的值。②部分初始化 ---值依次给前面的元素,后面的没给值的元素,默认为0。常量表达式 ---用来说明---数组中相同类型变量的个数。

2025-07-28 19:54:05 290

原创 C语言条件判断核心:关系运算、逻辑运算与if/switch语句

逻辑运算“与或”能短路,省运算。求解表达式,得到结果与下面case后的值进行匹配,如果匹配上则执行对应case后的语句,知道遇到braek或switch的}则执行结束。判断表达式,为真执行if下的语句,语句执行完,if语句结束,程序继续往下;3.没有单独的else语句,如果出现else一定有其对应if,else和if是成对出现的。都是程序与现实的对话,而调试时的每一次“为什么没进这个分支”,都是对逻辑思维的一次锤炼。c语言中表示真和假:用int类型1的数据1(真)和0(假)表示,c语言中没有布尔类型。

2025-07-26 19:58:39 393

空空如也

空空如也

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

TA关注的人

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