- 博客(72)
- 收藏
- 关注
原创 【OCPP2.0】 1.1 简易的 websocket 交互服务器
本文介绍了一个基于Python的WebSocket服务器实现方案。该服务器具备两大核心功能:一是显示客户端发送的数据,二是通过命令行终端向已连接设备发送JSON数据。实现步骤包括安装Python3.7+环境、通过pip安装websockets库、运行服务器脚本以及配置客户端连接参数(协议类型、IP地址和端口)。该方案为设备间实时数据通信提供了一个简单有效的解决方案。
2026-01-28 09:15:18
222
原创 【rtos深入】1.1 创建任务的内部细节
本文介绍了任务PCB控制块的创建过程。在xTaskCreate()函数中,会动态/静态分配PCB结构体和任务栈空间,其中栈大小由参数1000决定(实际分配4000字节)。创建任务时需要传入函数地址、名称、优先级等参数,这些信息会被保存在PCB中。函数参数通过R0寄存器传递,而程序计数器PC和寄存器值都会被保存在任务栈中。当任务执行时,CPU会从栈中恢复这些值,实现任务切换和参数传递。
2025-12-07 16:59:05
229
原创 【debug】1.2 未赋值的函数指针
摘要:本文分析了嵌入式系统开发中常见的两种故障现象:1)程序进入HardFault异常,通常由非法内存访问或堆栈溢出引发;2)系统不断重启,可能与看门狗未被及时喂狗或异常恢复机制不当有关。文章还探讨了函数调用层次过深时可能出现的错误,特别是当跨模块调用最终访问特定内存地址时可能出现的问题。这些故障往往与内存管理不当、指针使用错误或中断配置问题相关。
2025-11-14 17:22:48
202
原创 【c语言】1.7 深入分析变量赋值
【摘要】本文分析了变量赋值的底层实现原理。对于小整数赋值(如a=1),CPU可直接通过MOV指令完成。但对于大整数(如b=0x12343578)或长字符串等大数据,因其超出指令容量限制,编译器会将数据存储在Flash中,运行时通过内存拷贝(如__aeabi_memcpy)完成赋值。该过程涉及目标地址、源地址和数据大小三个参数,说明大数据初始化本质上是通过内存拷贝函数实现的。这解释了不同规模数据赋值的底层差异。
2025-11-14 11:40:24
345
原创 【c语言】1.6 void 与null 本质
本文阐述了C语言中void和NULL的本质与应用。void表示未确定的类型,主要用于描述未绑定变量的内存(如malloc返回的void指针),最终需强制转换为具体类型使用。NULL本质是(void)0,代表指向内存0地址的指针,作用包括防止野指针误操作和作为特殊标记。文中还区分了'\0'、'0'、0和NULL的差异:'\0'是ASCII值为0的转义字符,'0'对应ASCII 48,0是数字,NULL则是被转换为指针类型的0值。这两个概念共同体现了C语言对内存和指针的精细控制机制。
2025-11-14 11:40:11
300
原创 【c语言】1.5 预处理 函数 函数库
客户拿到.a和.h文件后,通过.h头文件得知库中的库函数的原型,然后在自己的.c文件中直接调用这些库文件,在连接的时候链接器会去.a文件中拿出被调用的那个函数的编译后的.o二进制代码段链接进去形成最终的可执行程序。sqrt本来是库函数,在编译器库中是有.a和.so链接库的(函数体在链接库中的),因为是不常用库,加一个 -lm告诉链接器去libm中查找用到的函数 (gcc 6.10.math.c -lm 就不会报错了) ldd a.out 显示用到了那些函数库。函数运行完毕会释放占用的资源。
2025-11-14 11:39:41
586
原创 【c语言】1.4 字符串 struct union
/先用typeof得到member元素的类型定义成一个指针,然后用这个指针减去该元素相对于整个结构体变量的偏移量(偏移量用offsetof宏得到的)(注意转成char *),减去之后得到的就是整个结构体变量的首地址了,再把这个地址强制类型转换为type *即可!} ) //ptr 是指向结构体元素member的指针,作用:知道一个结构体中某个元素的指针,反推这个结构体变量的指针, 宏返回的是整个结构体变量的指针(由此可以得到其他结构体的指针)在这段代码中,p本质上是一个字符指针,占4字节;
2025-11-13 15:19:37
699
原创 【c语言】1.3 指针
本文摘要: 本文系统梳理了C语言中指针、数组和内存管理的核心概念。主要内容包括:1)指针作为间接访问的实现机制,数组名本质是首元素地址;2)变量本质是地址绑定类型信息,不同类型指针转换会出错;3)函数参数传递实质都是传值,数组形参退化为指针;4)详细分析三种内存来源(栈、堆、数据区)及其特性,强调栈变量的临时性和堆内存的分配释放机制;5)野指针的危害及NULL指针的本质;6)通过输出型参数实现函数多值返回的编程范式。全文深入剖析底层原理,强调指针操作才是访问数组的本质方式,为理解C语言内存模型提供了系统框架
2025-11-13 14:43:37
2176
原创 【c语言】1.3 位运算
本文摘要: 本文系统介绍了C语言中的位运算操作,包括逻辑运算(与、或、非)和位运算(移位、取反、异或)的规则与区别。重点阐述了嵌入式开发中常用的位操作方法:1)使用位运算对特定位进行置1(|)、清零(&~)和取反(^);2)通过移位操作构建特定二进制模式;3)寄存器位段的读写操作实践;4)使用宏定义简化位操作代码。文中提供了多个实用案例和宏定义模板,如SET_BIT_N、CLEAR_BIT_N和GETBITS宏,并详细解析了复杂宏的实现原理,为底层开发提供了实用的位操作解决方案。
2025-11-13 14:39:26
480
原创 【c语言】1.2 代码规范(华为c代码规范整理)
本文总结了C语言编程的规范化建议: 头文件应单一职责、自包含,使用防重复包含机制,避免循环依赖; 函数设计原则包括功能单一、参数合法检查、控制嵌套层级等; 变量命名采用小写下划线风格,全局/静态变量加前缀; 建议使用const常量代替宏,优先使用函数而非宏; 代码格式要求如文件头注释、程序块间隔、变量初始化位置等; 特别注意事项包括内存管理注释、字节序处理、I/O返回值处理等。
2025-11-13 14:35:48
680
原创 【c语言】1.1 变量(static restrict volatile)
本文摘要: 文章系统比较了静态(static)变量和自动(auto)变量的区别:存储位置(静态区/动态区)、初始化特性(static只赋值一次,默认0;auto每次调用都要初始化)和作用域。通过函数示例演示了局部变量与全局变量的作用域规则,指出C语言变量查找遵循"由小到大"原则。同时解析了const指针的不同用法(常量指针、指针常量及双const),并介绍了volatile(防止优化)和restrict(允许优化)关键字的用途。最后强调了变量定义与声明的差异,以及函数定义与声明的本质区别
2025-11-13 14:30:16
931
原创 【stm32】1.1 最底层点灯
本文介绍了STM32F103VE芯片的最底层GPIO操作步骤。首先创建工程并添加启动文件,然后通过直接操作寄存器实现LED控制:1)开启GPIOB时钟(0x40021018);2)配置PB0为输出模式(0x40010C00);3)设置输出低电平(0x40010C0C)。同时解释了开漏输出原理(不会导致VDD-GND短路)和推挽电路结构(需PMOS/NMOS配合)。最后提到外设地址映射方法,为后续封装寄存器操作打下基础。整个过程基于官方参考手册,实现了不使用库函数的底层硬件控制。
2025-11-11 17:22:58
153
原创 【keil调试】1.1 keil调试技巧
本文总结了嵌入式调试中的常见问题与技巧。基础调试时断点可能失效,建议直接使用地址指令。条件断点兼容性受处理器和调试器影响。变量异常修改可通过map文件定位地址。调试过程常出现断点停止位置异常现象,可能与流水线或Breakpoints设置有关。评论指出存在不影响程序执行的断点调试方法。这些现象有待进一步研究,涉及底层硬件特性与调试工具的交互问题。
2025-11-10 23:58:36
420
原创 【mqtt】1.1 网络基础/mqtt介绍
TCP/IP网络传输需要IP地址和端口区分应用程序,私网与公网IP需区别。手机访问开发板需通过服务器中转,因路由器无法直接转发私网请求。少量数据传输适合采用MQTT协议,可通过阿里云平台进行消息传递测试,Windows系统亦可体验该通信过程。服务器在消息路由中起关键作用,与路由器协同完成跨网络通信。
2025-11-09 16:02:13
223
原创 【esp32】2.3 smart_config一键配网
设备开启WiFi混杂模式监听所有网络报文,手机APP将SSID和密码编码到UDP数据包中通过广播/组播发送。设备收到UDP包后解码获取WiFi信息,并主动连接对应网络。协议虽加密,但可通过数据包长度推断信息。整个过程实现了通过广播方式自动传递WiFi认证信息的功能。
2025-11-09 15:53:28
144
原创 【esp32】2.2 ap/sta流程
摘要:本文介绍了ESP32 WiFi STA模式的初始化流程。主要步骤包括:1) 初始化TCP/IP协议栈(lwip_task);2)创建事件循环;3)初始化WiFi驱动;4)注册WiFi和IP事件处理器;5)配置STA模式参数;6)启动WiFi驱动。流程中使用了事件组(event group)实现任务同步,与AP模式类似但处理不同事件。开发者主要需关注事件处理函数wifi_event_handler()的实现。
2025-11-09 15:47:38
212
原创 【esp32】2.1 sta模式demo
摘要:本文展示了ESP32设备以STA模式连接WiFi的代码实现。通过初始化TCP/IP协议栈、创建默认事件循环和STA对象,配置WiFi参数(SSID为"烤红薯-2.4",密码为"15173788740"),并设置WPA2加密方式。代码实现了自动连接和断线重连功能,通过事件处理器处理不同WiFi连接状态(启动、连接成功、断开连接和获取IP地址)。最终调用esp_wifi_start()启动WiFi功能,完成STA模式初始化。
2025-11-09 15:45:03
206
1
原创 【蓝牙】1.5 GATT服务器流程
这段代码展示了ESP32蓝牙GATT服务器的初始化流程。首先初始化NVS存储,处理可能的错误情况;然后释放经典蓝牙内存,初始化并启用BLE控制器。接着初始化蓝牙协议栈,注册GATT和GAP事件回调函数,最后注册应用profile并设置最大传输单元(MTU)。整个流程还包括错误处理和日志记录,为后续的广播和处理连接事件做好准备。
2025-11-08 16:01:14
200
原创 【蓝牙】1.4 GAP GATT介绍
本文介绍了蓝牙GAP协议中的角色定义和设备交互方式,重点解析了GATT服务端的数据结构与实现。手环作为服务端提供心率等数据服务,手机作为客户端进行连接和数据读取。文章详细说明了UUID定义规则和服务嵌套关系,并通过代码示例展示了GATT数据库的实现结构,包括主服务、包含服务和特性值的定义。其中属性值的交互是核心,示例中的handle_read_by_type_request函数演示了如何根据请求类型返回对应的属性值。最后指出特征值通过UUID关联到所属服务,服务端通过这种结构向客户端提供数据访问能力。
2025-11-08 15:58:29
401
原创 【蓝牙ESP32】1.3 精简蓝牙demo(详细注释)
ESP32实现BLE外设的双服务通信 本文介绍了基于ESP32开发板实现BLE外设功能的实现方案,包含两个自定义服务构建过程。系统采用ESP-IDF开发框架,通过定义两个自定义服务(UUID 0x18FF和0x18F3),每个服务包含两个特征值(分别具有读写+通知、只读+通知权限)。 关键实现包括: 服务配置文件定义:建立两套GATT属性表(gatt1_db和gatt2_db) 事件处理机制:实现GATT事件回调(gatts_profile_event_handler)和GAP事件回调(gap_event_
2025-11-06 23:00:41
856
原创 【arm架构】1.5 重定位的纯C函数实现
要获取各个域的加载地址、链接地址和长度,可通过Keil MDK的armlink工具实现。在分散加载文件(scatter file)中定义域(region)时,使用LOAD_OFFSET指定加载地址,或在链接脚本中直接设置。链接完成后,查看生成的.map文件可获取详细的域地址和长度信息。也可参考ARMlink用户手册(armlink.pdf)中的"Scatter-loading Features"章节,了解域地址分配和映射的具体语法与实现方法。
2025-11-04 15:20:25
221
原创 【arm架构】2.4 代码段重定位
摘要:实验通过修改Keil默认生成的sct文件及Start.s文件,将main替换为mymain进行调试。初始代码崩溃无输出,原因在于未执行reset_handler。修正后代码正常输出,因数据段已重定位。测试未重定位代码段时发现,当调用RAM指令时程序崩溃;重定位后恢复正常。BL指令因使用相对跳转(位置无关码),在flash未重定位时仍可执行。关键发现是BL指令的offset固定,确保代码块间跳转不受位置影响。
2025-11-03 22:04:48
590
原创 【arm架构】2.3 如何清除BSS段?
Map文件记录了链接时确定的全局/静态变量和函数地址,局部变量在运行时动态确定。要清除BSS段(存放未初始化全局/静态变量),可通过汇编语言实现:在程序启动时,将BSS段对应内存区域清零,确保变量初始值为0。这种方法常用于嵌入式系统等无操作系统环境下的内存初始化。
2025-11-03 22:02:47
239
原创 【ram架构】2.2 散列文件使用与分析
摘要:本文解析了Keil工具链中的散列加载文件(.sct)结构,该文件由加载域和执行域组成,用于定义程序在存储器和内存中的布局。文章重点讨论了如何获取区域信息以实现重定位,指出重定位只需关注源地址、目的地址和长度三个关键参数。同时提到需在调用main函数前手动编写重定位代码,以及在解析过程中可能遇到的字符编码问题(如乱码)及其解决方案。最后建议查阅Keil帮助文档以获取更详细的技术支持。
2025-11-03 21:56:10
259
原创 【arm架构】2.1 为什么需要重定位?
本文介绍了重定位的概念及其作用。通过串口打印实验发现,存储在RAM中的字符A显示乱码,而存储在Flash中的字符B正确显示。分析表明,这是因为RAM中的字符A未被正确赋值。重定位的作用是在调用main函数前,将Flash中的数据复制到RAM中,确保程序正确执行。文章指出,重定位的核心在于保证目标地址存储的是有效信息而非无效数据,而非简单地讨论相对或绝对跳转指令。最后通过位置无关码的实例,直观展示了重定位的重要性。
2025-11-03 19:31:29
214
原创 【arm架构】1.5 keil背后的命令、gcc编译过程
本文摘要:Keil编译过程分析显示,编译LED项目时生成led_c.BAT文件,其中包含ARMCC编译器路径、环境变量设置及编译参数(如抑制警告9931)。关键编译命令涉及main.__i、start._ia和led_c.lnp三个配置文件,最终生成hex/bin/dis文件。GCC编译示例展示hello.c的完整编译流程(-v参数显示详细过程),涉及预处理、汇编和链接阶段,链接时需明确系统库与自定义OBJ文件的路径。两类编译均需关注环境配置(头文件/库路径)与中间文件的生成逻辑。
2025-11-03 00:00:29
742
原创 【arm架构】1.4 纯汇编点灯
这篇汇编代码展示了如何通过直接操作寄存器来控制LED灯的闪烁。首先设置栈并初始化向量表,然后启动复位处理程序。代码通过加载和操作特定内存地址的寄存器值(0x40021000和0x40010C00)来配置GPIOB0引脚为输出模式,并在循环中交替设置高电平和低电平,配合延时函数实现LED的闪烁效果。延时函数通过递减计数器实现简单的时间延迟。整个过程展现了底层硬件控制的基本原理,无需操作系统直接操作寄存器完成外设控制。
2025-11-02 13:00:02
183
原创 【arm架构】1.3 结合c语言深入分析汇编
摘要:本文介绍了汇编调用C函数的方法,重点讲解了ARM架构下的ATPCS调用规则,包括参数传递(r0-r3寄存器)、寄存器保存约定(r4-r11)和返回值处理。通过delay函数示例展示了参数传递和返回值获取的具体实现,并比较了使用volatile关键字时的性能差异。最后阐述了Cortex-M3/M4处理器的启动流程:从固定地址读取SP初始值和复位向量,通过Reset_Handler进入程序执行。特别指出Thumb模式下向量地址需要加1的特点。(147字)
2025-11-02 12:02:34
387
原创 【arm架构】1.2 反汇编与pc寄存器
摘要:本文探讨了汇编和反汇编文件在不同架构下的差异。dis文件在不同架构下生成的机器码不同,map文件用于定位程序内存布局和函数信息。对于ARM和Thumb指令集,三级流水线机制会在执行当前指令时并行处理下一条和后续指令。通过结合map文件和dis文件可以更方便地分析函数实现。
2025-11-01 23:23:47
234
原创 【arm架构】1.1 汇编基础
摘要:立即数是嵌入指令中的固定值,用作运算常量。汇编指令示例展示了STR指令的不同用法,包括基址偏移和后缀索引操作。LDR和STR分别用于数据加载和存储。栈操作指令STMIA可实现多寄存器存储,FD模式表示满减栈。数据处理指令会影响状态寄存器,而ADR指令可将标签地址加载到PC实现跳转。12行注释存在错误,应为"将R0地址值赋给R3并更新R0为R0+R1<<1"。
2025-11-01 23:13:30
163
原创 【蓝牙esp32】1.2 蓝牙堆栈
摘要:本文介绍了BLE(蓝牙低功耗)通信中的MTU(最大传输单元)概念。MTU指单次数据传输允许的最大字节数,在GATT协议中起着重要作用。通过合理设置MTU值,可以优化数据传输效率,影响蓝牙设备的通信性能。MTU大小决定了数据传输的分包处理方式,是BLE协议栈中的重要参数。
2025-11-01 23:05:06
146
原创 【esp32】1.7 SAR ADC
ESP32-S3内置两个12位SAR ADC,支持最多20个管脚的模拟信号采集。通过adc_oneshot.h和adc_continuous.h可分别实现单次和连续采样。单次采样通过状态机管理,包含初始化、配置、数据读取和校准等步骤;连续采样则利用中断回调实现数据采集。实际应用中需注意通道配置、衰减设置(如ADC_ATTEN_DB_12对应0-3.3V)和校准问题。常见问题包括采样值异常(如固定4095),可能由通道配置错误或电压超量程导致。
2025-11-01 20:30:47
696
原创 【esp32】1.6 ledc模块
LEDC模块支持通道与IO的灵活映射,通过ledc_timer_config()函数可自动配置定时器的分频系数、频率等参数,无需手动设置。当需要输出不同频率的PWM信号时,必须使用独立的定时器。使用ledc_stop()可停止PWM输出并释放通道,但该函数不能在初始化前调用。该API具有可重复调用特性,停止时默认输出低电平。
2025-11-01 20:21:35
317
原创 【esp32】1.5 BOD检测电源状态
本文介绍了ESP32芯片的BOD(欠压检测)中断功能实现。通过配置BOD检测阈值(如2.67V)并禁用自动重启功能,实现了欠压时触发中断而非系统复位。关键代码包括:1)初始化BOD并设置中断阈值;2)注册中断处理函数记录事件标志;3)提供状态查询接口。验证表明当电压低于设定阈值时能正确触发中断,同时避免了menuconfig中BOD配置导致的自动重启问题。该方案适用于需要欠压预警的场景,代码包含完整的BOD初始化、中断处理和状态检查功能。
2025-11-01 20:18:46
259
原创 【esp32】1.4 启动流程
摘要:系统启动日志显示,芯片固件加载过程中,FlashCache被固定设置为32KB,用于从Flash存储器将固件加载到内存。该32KB缓存空间作为Flash与内存间的数据缓冲通道,优化了固件加载效率,确保启动过程的稳定性和性能。这种固定配置方式体现了硬件设计中针对特定应用场景的优化策略。
2025-11-01 15:31:45
181
原创 【esp32】1.3 分区表介绍、RAM
摘要:本文介绍了ESP32-S3开发相关的三个关键技术点。1)分区表配置,详细说明了子分区名称、存储类型、子类型、偏移地址、大小和标志位的设置规则,特别强调4KB对齐要求。2)menuconfig配置机制,解析了Kconfig提供配置内容并生成sdkconfig文件的工作流程。3)数据存储方案,提到使用NVS存储复杂数据结构时可选用Blob格式,以及在RAM启动流程中的实现细节。这些内容为ESP32-S3开发提供了实用的配置参考和技术指导。
2025-11-01 15:05:43
288
原创 【esp32】1.2 芯片介绍/最小工程/启动log
ESP32-S3芯片启动过程分析 摘要:本文记录了ESP32-S3芯片的启动日志和内存分配情况。启动过程分为两阶段:ROM Bootloader初始化SPI Flash(DIO模式,80MHz),将代码和数据加载到IRAM(指令RAM)和DRAM(数据RAM)。第二阶段Bootloader验证安全启动签名后,加载应用程序分区(0x200000偏移)。系统各内存区域分工明确:IRAM存储关键代码(中断处理、RTOS调度器),DRAM存放数据段,Flash通过Cache映射执行大容量代码。日志还显示了16MB
2025-11-01 12:42:46
271
原创 【esp32】 1.1 ubuntu环境配置注意(idf)
本文介绍了在Ubuntu虚拟机环境下进行ESP-IDF开发的实用技巧。主要内容包括:1)推荐使用虚拟机开发环境,注意IDF与镜像版本匹配;2)通过SSH连接虚拟机的方法,建议使用MobaXterm或VSCode SSH插件;3)环境变量设置技巧,可将export.sh添加到.profile文件实现自动加载;4)开发实用技巧,如添加源码路径、调整VSCode设置、解决USB设备权限问题等;5)提醒在虚拟机拉取esp-idf前需先获取esp-tool工具。这些方法能有效提高开发效率,解决常见环境配置问题。
2025-11-01 12:38:01
286
原创 【蓝牙】1.1 蓝牙概述,音频数据流程
摘要:硬件部分分为controller(负责BLE和BT)和host(软件协议栈)。音频传输采用AdvancedAudioDistributionProfile协议,主要处理音频数据流。其过程是将模拟信号采样转换为数字信号进行传输。该方案实现了硬件与软件协同的无线音频传输系统。
2025-11-01 00:04:00
201
原创 【51单片机】1.12 stc51单片机总结
摘要:本文介绍了51单片机的中断原理和定时器工作机制,详细讲解了多种外设的应用方法。中断系统通过硬件自动保存现场、执行中断程序并恢复现场,定时器采用溢出中断和NOP指令实现精确延时。外设部分涵盖LED、数码管、按键、蜂鸣器等常见器件的驱动方法,以及I2C、UART、SPI等通信协议的实现要点,着重分析了时序控制和数据处理技巧。文章还涉及温度传感器、实时时钟等特殊器件的使用方法,为51单片机开发提供了全面的技术参考。
2025-11-01 00:03:34
526
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅