日常杂谈
文章平均质量分 89
strongercjd
资深嵌入式软件开发工程师,分享嵌入式软硬件方面知识。
展开
-
预编译#error的使用
说到预编译,大家立刻就能想到#define、#if、#ifdef和#ifndef等熟悉的预编译命令。其实#include,我们通常放在源文件用来包含头文件,它也是预编译命令。当然这不是这篇文章的重点。这篇文章主要讲解下#error预编译命令,对于什么是预编译,预编译的作用等基础知识点不再讲解,不懂的同学请自行百度。在MCU的开发中,我们经常需要用到Flash存储一些参数,且通常情况下有很多参数需要存储。原创 2022-12-17 10:57:18 · 1188 阅读 · 2 评论 -
关于共享资源保护的思考
先聊聊分享这篇文章的原因,在使用STM32时,我发现对于GPIO输出操作,可以使用GPIOx_ODR寄存器,也可以使用GPIOx_BSRR寄存器。对应的标准外设库API接口有对于我来说,我一直在用GPIO_SetBits和GPIO_ResetBits接口,一直对GPIO_ToggleBits无感。最近注意的这个问题,经过查资料和FAE确认,这样做的,目的是防止同一个port的其他GPIO被篡改。看下GPIO_ToggleBits的具体实现。原创 2022-12-17 10:40:53 · 359 阅读 · 0 评论 -
表驱动法在STM32中的应用
所谓表驱动法(Table-Driven Approach)简而言之就是用查表的方法获取数据。此处的“表”通常为数组,但可视为数据库的一种体现。根据字典中的部首检字表查找读音未知的汉字就是典型的表驱动法,即以每个字的字形为依据,计算出一个索引值,并映射到对应的页数。相比一页一页地顺序翻字典查字,部首检字法效率极高。具体到编程方面,在数据不多时可用逻辑判断语句(if…else或switch…case)来获取值;但随着数据的增多,逻辑语句会越来越长,此时表驱动法的优势就开始显现。原创 2022-11-05 23:48:32 · 3389 阅读 · 2 评论 -
关于软件定时器的一些讨论
这里先介绍下软件定时器和硬件定时器的区别:CPU内部自带的定时器模块,通过初始化、配置可以实现定时,定时时间到以后就会执行相应的定时器中断处理函数。硬件定时器一般都带有其它功能,比如PWM输出、输入捕获等等功能。但是缺点是硬件定时器数量少!!:软件定时器允许设置一段时间,当设置的时间到达之后就执行指定的功能函数,被定时器调用的这个功能函数叫做定时器的回调函数。回调函数的两次执行间隔叫做定时器的定时周期,简而言之,当定时器的定时周期到了以后就会执行回调函数。原创 2022-09-26 21:35:28 · 1720 阅读 · 2 评论 -
聊聊数据溢出的事
聊聊数据溢出的事情原创 2022-07-09 11:38:07 · 640 阅读 · 0 评论 -
C语言为什么不检查数组下标
1、引言最近在查一个bug,查到最后发现是数组越界导致的。数组只有30个字节,代码却向这个数组填充了35个数据,这个bug还是偶现的,查到它确实废了一番功夫。我就突然想到:C语言为什么不检查数组下标呢???先来个demo验证下#include<stdio.h>#include<stdlib.h>int main(){ int data[5]={0}; for(int i=0;i<8;++i) { printf("%d "原创 2022-05-25 22:08:30 · 433 阅读 · 1 评论 -
回调函数
1、函数指针学习回调函数,其实就是函数指针的应用,关于函数指针在之前的文章《指针与函数》中有详细的讲解,这里不再展开详解,重新贴一下之前文章中函数指针的示例代码#include <stdio.h>void MyFun1(int x);void MyFun2(int x);void MyFun3(int x);typedef void (*FunType)(int); /* ②. 定义一个函数指针类型FunType,与①函数类型一致 */void CallMyFun(FunTy原创 2022-04-16 16:55:55 · 1312 阅读 · 1 评论 -
VS Code调试C代码
1、前言首先说明的是vscode是代码编辑器,并不是编译器,它本身并不能编译C语言。在这里我们使用的是MinGW-w64作为C语言的编译器。MinGW-w64的前身是MinGW的全称是:Minimalist GNU on Windows。它实际上是将经典的开源 C语言 编译器 GCC 移植到了 Windows 平台下,并且包含了 Win32API ,因此可以将源代码编译为可在 Windows 中运行的可执行程序。而且还可以使用一些 Windows 不具备的,Linux平台下的开发工具。一句话来概原创 2022-03-13 17:38:24 · 4250 阅读 · 0 评论 -
C语言中static关键字详解
C语言中staic关键字很简单,简单到你的任何一个项目中可以不写一个staic关键字也是没有问题的。写这篇章主要是一下自己的staic的理解和应用,当然在章开头依旧要照本宣科简述一下static关键字。1、简述static关键字在嵌入式C语言当中很简单,它有三个作用:作用一:在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。void test1(void){ unsigned char a; static unsigned char b;…...原创 2022-02-16 21:52:12 · 3617 阅读 · 0 评论 -
深入聊一下const关键字
const是一个C语言的关键字,它限定一个变量不允许被改变。使用const在一定程序上可以提高程序的健壮性,另外,在观看别人代码的时候,清晰理解const所起的作用,对理解别人的程序有所帮助。1、const简介下面简单描述一下const,基本都是教科书的知识。const修饰的变量,其值存放在只读数据段中,其值不能被改变。称为只读变量。关于什么是数据段,什么是代码段,请看我之前的文章《C语言的内存分配》。int const a;const int a;上面两条语句都可以将a声明为一个整数,原创 2022-02-08 21:27:18 · 1564 阅读 · 0 评论 -
联合体在单片机编程中的应用
1、联合体之前的文章《枚举和结构体的结合》文中提到,结构体就像是打包封装,把一些有共同特征的变量封装在内部。结构体是一种构造类型或复杂类型,它可以包含多个类型不同的成员。在C语言中,还有另外一种和结构体非常类似的语法,叫做联合体(Union)(有些地方也叫做共用体)。联合体举例如下union data{ char n; char ch; char f;};union data a, b, c;结构体和联合体的区别在于:结构体的各个成员会占用不同的内存,互相之间没原创 2022-01-27 22:07:46 · 2711 阅读 · 0 评论 -
关于结构体中指针的一些探讨
1、起因在上篇文章《STM32编程中枚举和结构体的结合》中,有读者对下列代码有疑问typedef struct{ char *name; //姓名 int num; //学号 int age; //年龄 float score; //成绩}stuff_s;stuff_s xiaoming;void xiaoming_inf_init(){ xiaoming.name = "xiaoming"; xiaoming.num = 1; xiaoming.age原创 2022-01-25 22:59:46 · 637 阅读 · 0 评论 -
STM32编程中枚举和结构体的结合
01、结构体定义基本定义:结构体,通俗讲就像是打包封装,把一些有共同特征(比如同属于某一类事物的属性,往往是某种业务相关属性的聚合)的变量封装在内部,通过一定方法访问修改内部变量。结构体的定义:第一种:只有结构体定义struct stuff{ char *name; //姓名 int num; //学号 int age; //年龄 float score; //成绩};第二种:附加该结构体类型的“结构体变量”的初始化的结构体定义,如下代码也就是定义结构体时原创 2022-01-08 14:37:55 · 779 阅读 · 0 评论 -
C语言的内存分配
01、ANSI C在ANSI C中数据类型包括:整形,浮点型,指针和聚合型(如数组和结构等)整形:字符,短整型,整型和长整型,他们都分别有有符号(singed)和无符号(unsingned)取值范围:没有带signed或者unsigned,默认signed长整型至少应该和整型一样长,而整型至少应该和短整型一样长在32位环境中,各种数据类型的长度一般如下:02、ARM C具体我们以IAR为编译器,版本7.2注意:在32位ARM中,字是32位,半字是16位原创 2021-12-17 23:46:04 · 2129 阅读 · 0 评论 -
深入探讨一下如何打断点
对于程序员来说,debug的时间往往比写程序的时间还要长。尤其对我这种专写bug为主的程序员来说,正确使用断点调试是提高效率的有效方法。今天我们聊聊如何高效率的断点调试,由于工作中IAR为主力IDE,本篇文章主要以IAR为主。01、普通断点打开IDE,如下图,我们想在程序运行到第104行时停止运行,我们在下图中104行号前单击,这时该语句上将出现红色的断点标记。如下图:或者点击要设置断点的语句,按鼠标右键,选择Toggle Breakpoint (Code)。02、条件断点除了上述最原创 2021-12-07 21:40:54 · 4373 阅读 · 0 评论 -
C语言访问存储器的方法
在单片机中我们经常需要访问某个指定的寄存器或者到指定的RAM地址,在本文为简单描述,下文所说的存储器可指:寄存器,RAM等。01、宏定义:定义一个宏,将地址值转化为C指针,然后取这个指针指向的内容,这样就可以访问存储了,代码如下:#define SDA_DIR_REG *(__IO uint32_t *)SDA_MOD_OFFSET分析:(__IOuint32_t *)SDA_MOD_OFFSE 是强制类型转换强制转换为指针*(__IOuint32_t *)SDA_MOD_..原创 2021-10-22 21:03:17 · 2168 阅读 · 0 评论 -
Jlink之J-Scope虚拟示波器
01、虚拟示波器说到虚拟示波器,大家应该都不陌生。在学校时开发智能车,调节PID时虚拟示波器是必须的工具。虚拟示波器软件有很多,之前我也分享过一篇文章《一个超赞的开源串口虚拟示波器项目》,基于QT的开源软件,大家有兴趣可以看一下。一般情况下虚拟示波器软件都是通过串口接收数据的,所以要求MCU通过串口把数据打包成软件支持的协议发给虚拟示波器软件。02、J-Scope是什么J-Scope是J-link的功能之一,J-Link是SEGGER公司为支持仿真ARM内核芯片推出的JTAG仿真器。简单地说原创 2021-09-23 21:57:19 · 2957 阅读 · 1 评论 -
STM32“隐藏的定时器”-DWT
01、前言在之前的文章在《STM32延时函数的四种方法》使用定时器延时,在《如何测量代码运行时间》中提到使用定时器外设计算代码运行时间。文中提到这种方法的明显缺点就是需要占用一个定时器,一些MCU在特定应用场景下定时器外设资源是十分稀缺的。在留言区有位大佬提到可以使用DWT,我就研究了一番。02、DWT在Cortex-M里面有一个外设叫DWT(DataWatchpoint andTrace),是用于系统调试及跟踪,DWT的中文名字应该是:数据观察点触发。在STM32用户手册的第32章节Deb原创 2021-08-31 00:03:48 · 3224 阅读 · 1 评论 -
如何测量代码运行时间
01、示波器测量一段代码运行时间第一时间想到的当然是示波器了,在测量开始的代码前面拉高某个GPIO,在结束测量的位置拉低这个GPIO,直接使用示波器查看这个GPIO的高电平时间长度即可,就是我们要测量的这段代码的运行时间。那么直接上示例,为了模拟代码运行一段时间,这里我直接采用之前文章《STM32的四种延时方法》直接延时。 while (1) { GPIO_SetBits(GPIOE,GPIO_Pin_4); //熄灭LED灯原创 2021-08-25 21:56:24 · 1851 阅读 · 0 评论 -
数字地和模拟地都是地,为什么要分开?
数字地、模拟地互相会影响不是因为一个叫数字,一个叫模拟,而是他们用了同一部电梯:地,而这部电梯所用的井道就是我们在PCB上布得地线。模拟回路的电流走这条线,数字回路的电流也走这条线,本来无可厚非,线布着就是用来导通电流的,可问题出在这根线上有电阻!而且最根本的问题是走这条线的电流要去2个不同的回路。假设一下:有2股电流,数流,模流同时从地出发。有2个器件:数字件和模拟件。若2个回路不分开,数流模流走到数字件的接地端前的时候,损耗的电压为V=(数流+模流)X走线电阻,相当于数字器件的接地端相对于地原创 2021-08-17 21:41:23 · 2348 阅读 · 0 评论 -
填坑-关于IIC通讯
01、概述在之前的文章中《STM32IIC详解》中详细讲解了IIC协议,并且使用是NXP的官方手册,demo示例使用IIC读取RTC芯片,运行正常,没有任何问题。并且更新了《IIC踩过的坑》,讲述了在使用IIC读取RTC芯片时遇到的问题,并成功解决。我以为我已经完全学会了IIC,但现实却打了脸,我在使用《STM32IIC详解》文中的IIC驱动,去驱动MPU6050时,总是读取失败。这个驱动明明是验证过的,为什么会有问题。让我一度很是郁闷。02、问题所在不卖关子,直接说问题,是我之前的IIC驱原创 2021-08-04 00:07:39 · 1044 阅读 · 0 评论 -
用Excel教会你PID算法
01、引入PID电机控制这样是没有反馈的,也就是说我们完全相信输入的数字,且是理想化的模型,比如输入占空比为50%的25Kz的PWM,车轮速度为1m/s,实际产品中会受到各种这样的影响,比如地面阻力,风阻等等,同样输入占空比为50%的25Kz的PWM,车轮的速度并不是1m/s。这时候我们就引入测量单元,也就是反馈系统。这个时候,最常见的反馈就是:直接使用反馈值。简单的例子,属于数值X和输出数值y的数学公式是:y=2x,这是这最见的关系。假设我们输入7,测量结果是5,那么我们就直接将输原创 2021-07-21 22:31:42 · 2513 阅读 · 3 评论 -
STM32属于哈佛结构还是冯诺依曼结构?
目录01、冯·诺依曼体系02、哈佛体系03、arm和哈佛、冯·诺依曼的关系04、实际芯片制造现代的CPU基本上归为冯诺伊曼结构(也成普林斯顿结构)和哈佛结构。冯洛伊曼结构就是我们所说的X86架构,而哈佛结构就是ARM架构。一个广泛用于桌面端(台式/笔记本/服务器/工作站等),一个雄踞移动领域,我们的手持设备(平板\手机用的大多就是他了)。01、冯·诺依曼体系冯·诺依曼体系结构图如下冯·诺依曼体系的特点:A、数据与指令都存储在同一存储区中,取指令与取数据利用同一数据原创 2021-04-22 22:07:55 · 6625 阅读 · 2 评论 -
填坑-关于SysTick定时器
目录01、坑的由来02、填坑03、修改代码验证04、总结本文主要来填坑,更正之前文章的错误。也进一步加深了我对SysTick定时器的理解,希望对你有帮助。01、坑的由来在之前的推文中《STM32延时的四种方法》介绍了使用查询定时器精确延时,使用的就是systick定时器,具体代码如下void delay_us(uint32_t nus){ uint32_t temp; SysTick->LOAD = RCC_Clocks.HCLK_Frequency/100原创 2021-03-31 12:17:50 · 3504 阅读 · 2 评论 -
我是如何查找RFC官方资料的
目录01、关于TCP协议头中保留位02、Wireshark工具03、RFC官方协议下载01、关于TCP协议头中保留位读者疑问:部分读者对上一篇《TCP协议详解》中的保留字节和标志位有疑问。关于这一点,详细说下,大部分同学看过1999年译的《TCP/IP详解卷1:协议》,这本书中TCP部分保留位为6位,如下:TCP/IP详解卷-第一版-此书里面明确讲解了,TCP协议头有6个保留字节。这本书讲的没有错,因为在TCP标准文档(RFC793)中也是这样原创 2021-01-05 10:41:19 · 4164 阅读 · 0 评论