- 博客(182)
- 资源 (1)
- 收藏
- 关注
原创 GD32F407开发环境搭建
笔者近期做一个嵌入式项目,要使用国产芯片,根据需求,选用了GD32F407VG芯片。STM32系列开发板,有正点原子,野火等配置了详细的例程。遗憾的是,只有野火仅支持了一款GD32H759芯片(M7内核),并没有GD32F407芯片。继续查找相关厂家,有一些小厂家有做GD系列的开发板,并配备了相应的例程,但大多数都是基于标准库,hal库并不完备(甚至GD32的厂家兆易创新本身也只有F3xx系列以下提供了hal库例程,F4xx都是一些标准库)。
2025-04-07 17:01:28
458
原创 上位机和下位机差异(1):上位机是高配板的下位机,下位机是低配版的上位机,二者本质是一样的
上位机和下位机这个概念其实是一个比较形象的说法,我们一般把运行在电脑上的软件称为上位机软件,把运行在嵌入式芯片的软件称为下位机软件。
2025-03-20 11:32:53
351
原创 51芯片内存分配详解(data,xdata,bit,code)和address space overflow问题
如果读写要了解51单片机的详细内容,建议读51芯片手册。本文结合笔者使用51单片机的情况,谈一下51单片机的存储和内存分配。以及当空间超出时的,代码优化问题。
2025-03-11 11:44:49
641
原创 STM32启动文件解析【建议收藏】
启动文件,即复位后,首先执行的文件。我们可以想象一下,程序如何去执行?首先,得有编译后的二进制文件。其次,得有执行指令的硬件,对嵌入式来说就是处理器MCU 最后,我们知道程序执行需要堆栈,而且是从程序计数器PC中取得将要执行的下一条指令的地址的。因此,在程序执行前,应当初始化栈顶指针,初始化程序计数器。还需要哪些东西呢?时钟是需要的吧,因此需要初始化时钟。中断向量表是不是也要初始化呢?需要的,如果没有初始化中断向量表,就进入了main函数中执行,那一旦产生中断就没有进入相应的中断处理函数中执行。
2025-03-04 13:41:36
834
原创 电脑不用的时候,网络自动掉线。打开后,又重新联网。关闭网卡休眠,解决此问题!
选择电源管理,把“允许计算机关闭此设备以节约电源”的勾选去掉!打开网络适配器,右键属性。
2025-02-21 10:55:36
140
原创 C Primer Plus 读书笔记,精简实用,建议收藏!
思考下,为什么要有函数?函数的声明有什么作用?在一个大型项目中,源文件的编译是有顺序的。当在编译一个文件时,遇到函数fun1调用fun2。此时编译器如何对调用fun2做检查呢?比如检查参数个数和类型是否正确。但是当此时编译器可能还未遇到fun2的定义,因此不知道如何检查fun2函数调用的是否正确。此时,就需要提前告诉编译器该函数的原型。这就是声明的作用。函数调用:函数调用过程,需要开辟栈帧空间,把参数和返回地址进行压栈。调用结束后,再返回调用处。
2025-02-07 18:50:11
764
2
原创 C++面经之const用法:常变量,常量指针,指向常量的指针,const 函数
const可以用来修饰普通变量、指针、函数等,const用来修饰的符号,除了赋初值的情况下,其余情况不可修改,也就是说只支持读不支持写。因const修改的不可变,因此const在大型项目开发中广泛用于修改函数参数,来保证外部接口传来的参数不被修改。非const变量不能赋值给const变量(初始化除外),反之可以。非const函数可以调用const函数,反之也可以。const常变量在编译期期间,就会检查错误。const函数中,任何变量不可修改。
2024-12-18 09:41:23
258
原创 深入理解计算机系统之汇编与链接,建议收藏!
程序员需要了解一个程序如何从源文件变成可执行程序的过程。概括请参考深入理解计算机系统,源码到可执行文件翻译过程:预处理、编译,汇编和链接。本文主要将分析一下源程序生成的汇编文件和链接器链接过程。
2024-12-16 16:29:39
440
原创 深入理解计算机系统:缓冲区溢出、内存越界访问和栈破坏检测
基于栈存在缓冲区溢出和内存访问越界的特点(其实就是我们常说的“踩内存”),编译器一般都会带有基本的栈破坏检测功能,原理就是在变量或返回的地址周围插入一段特殊的区域redzones,当这段区域被访问时,就可以知道一定是发生了踩内存。举例说明,函数调用时,需要把压栈和出栈。如fun1调用fun2,那么需要把传入fun2的参数和当前fun1执行所在的地址进行压栈,以便函数返回时,能够返回fun1原本的位置,使得fun1得以继续执行。如果这段内存是只读属性的,别处的缓冲区再溢出,也无法覆盖我此处内存的数据。
2024-12-11 10:19:52
414
2
原创 一个函数无法打断点,可能的原因:该函数没有被链接
问题描述:问个技术问题:keil C51在之前的老程序上增加了一个xx.c文件,里面有个方法fun(),然后原来的main.c中会调用xx.c文件的fun()函数。现在有个问题是:如果按照这个写法,fun()调用不到。但那fun()的定义移到main.c是可以的。不知道为什么?同时,按照最初的方法,断点调试时,fun()里面也无法打上断点。给我的感觉是这个函数就没有被链接到可执行文件。但编译也没有报错,不知道问题出在哪了。和群友讨论了一下:怀疑在编译main.c文件时,有一些告警被忽略了。
2024-12-02 16:41:24
288
原创 DB9接口定义和接线
在单片机和DB9的公头连线时,单片机的芯片的TX输出引脚最终要接到DB9公头的TX引脚上。另外,对于同一根,假如有两个DB9口,一个公头和一个母头,其内部连线,DB9公头的TX线是和DB9母头的哪个引脚是相通的,即是同一根线?逻辑电平不同:电脑COM口是RS232电平,UART是TTL电平,电平标准不同,不能直接相连,需要电平转换芯片(MAX3232等)。对单片机来说,往外发出信号的线我们叫发端,TX。对计算机来说,收信号的线,我们叫收端,RX.对单片机来说,收信号的线,我们叫收端,RX.
2024-11-28 16:08:33
3168
2
原创 深入理解计算机系统,源码到可执行文件翻译过程:预处理、编译,汇编和链接
从一个高级语言到可执行程序,要经过预处理、编译,汇编和链接四个过程。大家可以思考下,为什么要有这样的过程?我们学习计算机之处,就应该了解到,计算机能够识别的只有二进制语言(这是本身硬件特点决定的)。计算机刚诞生时,程序员写的就是二进制语言(机器语言),也就是0101的代码串。但机器语言的缺点也是非常明显的(和人类自然语言相差过大,难以理解,难以编写,难以维护)。
2024-11-28 11:23:44
1363
3
原创 C51程序优化,减少data空间占用
这两天搞了一下51单片机。开发工具使用的keil,踩了一些坑,记录一下。产品选型,用的C8051F120,片上RAM是256字节,但只有低128字节可用于直接寻址。
2024-11-27 14:08:29
358
原创 strtok_s详解,实现使用strtok_s分割字符串,并返回包含分割符的子串
strtok_s 是一个线程安全的字符串分割函数,它是 strtok 的一个变体,用于将字符串分割成一系列的标记(tokens)。与 strtok 不同,strtok_s 需要一个额外的参数来保存上下文信息,这样它就可以在不同的调用之间保持状态,而不需要使用静态变量。在第一次调用时,strtok_s 会在 str 中查找第一个不属于 delim 中的字符,并将其视为标记的开始。delim 中的字符或字符串的末尾,此时它会将找到的标记的末尾设置为空字符(\0),并返回指向标记的指针。str:要分割的字符串。
2024-11-12 12:54:49
1387
原创 嵌入式调试手段:使用串口工具(二)
这是嵌入式调试手段之使用串口工具的第二篇,第一篇参见嵌入式调试手段(一):使用串口工具嵌入式调试中,我们常常需要通过串口抓取发送或接收的数据和时序,以便对问题进行分析。更进一步,我们可能需要在不破坏原有系统正常工作的前提下,抓取到下位机发送或接收的数据和时序。常见的嵌入式系统(包含上位机和下位机)一是由用于工业控制的计算机、单片机以及感知或动作单元组成。位于计算机上的上位机负责监控和控制整个系统的运行,通过友好的可视化界面与用户进行交互,传递用户操作命令或者把结果呈现给用户。
2024-11-12 10:54:16
406
原创 嵌入式调试手段(一):使用串口工具
嵌入式开发和纯软件开发一大不同在于调试工具和方法,因嵌入式开发本身特点,其相对传软件开发的调试手段和调试技巧要求得更高一些。比如,如何看这个信号通不通,可能就需要使用示波器等工具。如何看通信发的命令对不对,可能需要串口工具把命令接收打印出来。一般,常规得嵌入式项目,首先要把通信调通,在此基础上再调试业务逻辑代码。本文讲一下,如何借助串口工具来调试嵌入式程序。来看下面这个例子。
2024-11-04 10:17:56
506
1
原创 c语言实现一个日志系统,记录程序运行状态,提供可维可测手段!
在一个正式的项目中,设计一个日志系统是很有必要的。当程序执行不符合预期,一个日志有助于我们分析程序运行的状态,进而定位到异常点。设计一个日志系统,应该从下面几点进行考虑:1.日志函数是对外提供接口供调用?会不会有多处调用,同时写文件?如何解决IO一致问题2.通过一个单独的线程来处理写日志?3.日志中,应该保存哪些信息?4.运行过程中,日志文件会不断增大。日志文件大小如何设置?5.如何兼顾性能?日志文件要有相应的宏开关
2024-10-30 10:28:56
433
原创 一文搞懂指令周期,机器周期和时钟周期
指令周期:一个指令,从取值到执行的全部周期。一个指令执行过程包括取值,译码和执行阶段。时钟周期:时钟频率的倒数,一般为系统最小的时间刻度。机器周期:,取指、间址、执行和中断等。
2024-10-26 14:41:16
451
原创 一文看懂,为何需要时钟?以及时钟树的基本结构
本文主要介绍时钟的作用以及STM32时钟数的结构。嵌入式常见的时钟源:高速外部时钟(HSE)、低速外部时钟(LSE)、高速内部时钟(HSI)和低速内部时钟(LSI)。LSE为低速外部时钟,HSE为高速外部时钟,它们的时钟源可以是晶振。再往PLL时钟看去,可以看到PLL时钟的时钟源是高速内部时钟HSI和高速外部时钟HSE。往系统时钟看去,PLL时钟,高速内部时钟HSI,高速外部时钟HSE都可以作为系统时钟SYSCLK的时钟源。
2024-10-26 14:15:22
944
原创 STM32之基本定时器TIM6和TIM7
基本定时器有两个,分别是TIM6和TIM7。它们的计数器都是16位的,也就是意味着取值范围对无符号数来说是0到65535。基本定时器工作时,主要涉及三个寄存器,分别是计数器寄存器(TIMx_CNT)、预分频器寄存器(TIMx_PSC)、自动重载寄存器(TIMx_ARR)。顾名思义,计数器寄存器(TIMx_CNT)是用来计数的,它的值是从0开始递增。而当计数寄存器的值等于自动重载寄存器(TIMx_ARR)中的值时,就会生 成事件,将相关事件标志位置位,生成中断输出。
2024-10-24 18:15:45
1138
1
原创 存储器层次:寄存器,L1 Cache,主存 Main Memory,磁盘 Local Disk
关于存储器领域,有一个非常经典的图。图中,越往顶,访问速度越快,价格也越贵。L0: 寄存器。L1~L3: Cache,是高速缓存器。L4:主存,DRAM。L5: 本地磁盘。L6: 远端存储器。
2024-10-23 14:05:58
510
原创 射频系统:下行通路,开关,低噪放,AGC,DSDS
射频芯片或射频组件在生活中处处可见,如手机中,如卫星信号收发。所谓射频芯片起作用是把无线电磁波信号接收下来转化为数字信号或者把数字信号转化为无线电磁波信号发送出去。因此,只要涉及到无线通信,几乎都有射频组件。对于射频芯片老说,发送要保证,发的远,且尽可能少的对接收造成干扰。对接收来说,就要在嘈杂环境下还要“听得清”。因此,射频系统设计时就要考虑到上述问题。
2024-10-23 11:41:43
1192
原创 注册函数和回调函数使用讲解
分层模型中,常规的逻辑是,上层调用下层的方法。但也会存在下层调用上层方法的情况,这时如果直接调用调用的话,会使得下层的软件特定于一个上层的软件,降低复用性。而使用注册和回调机制的话,调用者不需要关心具体的实现细节,只需要知道存在一个具有特定原型的函数即可。在回调机制中,一个函数(回调函数)的地址被传递给另一个函数(注册函数),以便在某个事件发生时能够调用这个回调函数。
2024-10-18 14:33:26
1199
原创 程序负载优化,持续更新,建议收藏!
对一个程序来说,内存和负载是两个重点指标。特别是对嵌入式程序来说,本身单片机的主频小,内存少,这就要求 开发工作者必须考虑如何在有限的内存和负载下开展工作。本文主要侧重负载优化。首先介绍负载的概念,其次接收负载优化的理论和思想,最后介绍一些可行的方法。
2024-10-16 17:53:01
467
1
原创 STM32 程序卡着不动,可能是发生了硬件错误,进入了HardFault_Handler处理程序中
STM32 程序卡着不动,可能是发生了硬件错误,进入了HardFault_Handler处理程序中。
2024-10-15 14:16:45
696
原创 MODBUS协议介绍,通过MODBUS协议控制伺服电机工作
modbus协议本身的介绍,请大家自行查阅资料。本文简单介绍一下如何通过MODBUS协议组装控制指令。最近搞了一个项目,要驱动伺服电机工作。通过下位机STM32 407 100封脚 给伺服电机发控制指令。电机和下位机之前的通信采用RS485串口通信,发送和接收数据的格式使用是MODBUS协议。分为读寄存器,即从电机的寄存器里面读值,来获得一些电机的运行状态信息等。读寄存器的格式 地址:功能码:寄存器地址:读寄存器个数:CRC校验。
2024-10-12 09:57:37
1199
原创 STM32 407 RS485通信实现数据收发【我的创作纪念日】
最近搞嵌入式程序,踩了不少坑,这里统一记录一下。串口通信,数据是一个字节一个字节的发送,对方收到的数据是放在了寄存器中(这个是由硬件控制的),软件在接收数据时,中断处理函数中再把寄存器中的数据取出来,一般是放在一个缓冲区里。因为写入的数据量 和写入时间不确定性 ,会导致软件在读取串口的时候读取的数据不完整 或者一次读取"一条半"这样的问题..这时候软件上就要解决一个问题,如何保证收到的数据是完整的。一般有下面几种方式: 1. 发送的数据长度是知道的,那么当接收到相应长度的数据时,认为接收完成了。
2024-10-11 18:25:44
1688
原创 程序执行过程中,报错debug errror damage :after normal block at
Visual C++ 6.0运行一段程序,报错:debug errror damage :after normal block at(堆损坏了)。网上查了一下,说是内存访问越界。Debug模式下,点击忽略还能继续执行。下面,我将通过断点调试找到出错的语句,并定位出原因。
2024-09-26 11:03:05
483
原创 .text .data .bss .stack 和 heap
ELF头:包含ELF头的大小、目标文件的类型、.text .data .bss 等文件的位置和大小等信息。.data:已经初始化的全局变量和静态变量(static修饰)放在flash上,断电不失。
2024-03-09 17:12:31
631
1
原创 Windows11的浏览器出现ERR_PROXY_CONNECTION_FAILED,无法使用网络
笔者的电脑是windows11系统,Edge,Google等浏览器访问网页网页时,都出现以下错误:ERR_PROXY_CONNECTION_FAILED。同时,cmd测试网络,可以ping通。浏览器无法访问网页的原因,很有可能就是代理服务器的问题。找到“网络和Intenet”,关掉代理服务器即可。...
2022-07-07 10:52:11
13849
6
原创 C++解析字符串获取参数
一些软件在运行时,需要一些命令。这里使用通过字符串的方式,来获取软件启动需要的一些参数。比如:-name1 aaa -name2 bbb有这样一个字符串,通过解析-name1对应的aaa,-name2对应的bbb;
2022-06-21 10:33:28
1336
原创 PyTorch框架中使用早停止Early Stopping(含详细代码)
文章目录1.什么是早停止?为什么使用早停止?2.如何使用早停止?3. Refferences1.什么是早停止?为什么使用早停止?早停止(Early Stopping)是 当达到某种或某些条件时,认为模型已经收敛,结束模型训练,保存现有模型的一种手段。机器学习或深度学习中,有很大一批算法是依靠梯度下降,求来优化模型的。是通过更新参数,让Loss往小的方向走,来优化模型的。可参考BP神经网络推导过程详解关于模型何时收敛(模型训练好了,性能达到要求了或不能再优化了),此时我们可以采取一些判断标准:1.验
2022-03-21 21:46:49
45605
16
原创 分类问题模型性能评价指标(含代码)
文章目录1. 分类问题模型性能评价指标2. 混淆矩阵(confusion matrix)3. 准确率(accucary)、精确率(precision)、召回率(recall)4. 灵敏度(sensitive)、特效度(sensitive)5. F-Score / F-Measure6. Macro-F1 和 Micro-F17. P-R曲线、ROC曲线和AUC8. 代码实现(python)References
2022-03-20 22:37:27
2927
4
原创 TensorFlow和PyTorch框架绘制loss和accuracy曲线
文章目录1.前言2.TensorFlow框架绘制loss和accuracy曲线3.PyTorch框架绘制loss和accuracy曲线4.pytorch中使用tensorboard绘制Accuracy/Loss曲线1.前言搞深度学习时,我们一般会遇到一个问题,评估模型的性能:这时,一般会绘制模型在训练集 & 验证集上的准确率值和损失值曲线。在这一点上TensorFlow框架比PyTorch框架方便,因为TensorFlow框架在训练模型时,把模型、训练集和验证集上的accuracy和loss都
2022-03-17 23:16:36
22184
10
原创 神经网络模型训练时,性能不高?原因总结(神经网络模型性能优化方法汇总)
文章目录 前言1. 改模型框架2.数据处理3.超参数对模型训练的影响3.1 学习率对模型训练时的影响3.2 批处理大小对模型训练时的影响3.3 epoch对模型训练时的影响3.4 如何判断模型收敛3.5模型过拟合时怎么办?
2022-03-15 21:58:40
9235
2
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人