首页 » 智能家居 » 本周作者推荐:鱼鹰单片机

本周作者推荐:鱼鹰单片机

深圳市名雕装饰股份通讯 2025-01-08 0

扫一扫用手机浏览

文章目录 [+]

xxx.htm

xxx.map事实上这个文件天生也是由默认参数 --map 管理的,不同的是增加 --info=stack 参数后,文件中还会增加如下信息:

本周作者推荐:鱼鹰单片机 本周作者推荐:鱼鹰单片机 智能家居

它描述了每一个函数调用情形,并且把最大调用链和最大利用栈给你找出来了(这个文件打开有一个小技巧,双击 Target 1,即可打开这个文件,方便快捷)。

本周作者推荐:鱼鹰单片机 本周作者推荐:鱼鹰单片机 智能家居
(图片来自网络侵删)

事实上,这些信息只能用于参考,而不能作为终极的栈大小,打算实际栈大小远比这个繁芜,这个原文进行了深入阐述。
事实上,一样平常设置栈大小都不会采取如此繁芜的打算,而是通过永劫光运行来大略确定栈大小(一样平常 RTOS 都有栈检讨功能函数),并且会在永劫光运行获取栈大小的条件下预留一定大小的栈空间,这样一样平常来说都能担保有足够的栈空间。
IAR 平台这个平台鱼鹰不是很熟习,原文是这样写的:IAR Embedded Workbench for Arm (EWARM) provides stack size report in the linker map file. To enable this, the following project settings are required:

Enable linker map file generation in Linker settings (List tap)Enable stack usage analysis (Advanced tap).

谷歌浏览器自动翻译结果是:

用这个开拓平台的道友可以试试。
GCC利用参数: -fstack-usage并且 gcc上供应了堆栈保护功能,利用以下选项

-fstack-protector:在堆栈帧上为每个易受攻击的函数插入一个保护变量。
-fstack-protector-all:在堆栈帧上为所有函数插入一个保护变量。

然后在看看文中的几个故意思的点:

01 栈布局

一样平常情形下的栈布局有如下两种:

KEIL 平台下的属于第一种,这便是为什么栈空间小了会很大可能影响用户变量的缘故原由(栈往低地址成长)。
而 gcc 采取第二种情形,这种情形可以完备利用 RAM 空间,如果说这种布局还会导致栈空间不足,那么你怎么设置栈大小都没用了。

02 函数调用

须要特殊理解来自开拓工具的堆栈利用报告仅涵盖每个函数或调用树的堆栈利用情形。
它们不包括非常处理程序所需的额外堆栈空间。

假设运用程序仅对外设中断利用两个中断优先级,由于可能发生HardFault非常和NMI非常(如果运用程序利用),可能存在4级嵌套非常,如图所示。

(原作者为Joseph Yi)这便是为什么栈打算繁芜的缘故原由了。
栈打算可用以下流程图:

(原作者为Joseph Yi)

03 栈大小难以打算缘故原由

软件开拓职员可能会创造,在许多情形下,报告无法供应有关运用程序某些部分的堆栈哀求的信息。
堆栈利用情形报告天生对某些代码不起浸染的缘故原由有很多:

在运用程序中利用函数指针可能意味着该工具无法天生调用树。
在许多工具中,C运行时库中函数的堆栈利用是未知的。
该运用程序包含递归函数调用或自修正代码。

在这些情形下,您可能必须手动打算这些函数的最大堆栈利用量,或者通过试验来估计这些函数。
例如,您可以在运行程序之前利用调试器以某种数据模式添补堆栈内存空间,然后实行代码,并检讨堆栈内存空间以查见地式实行已修正了多少堆栈空间。

也可以通过在项目中添加检测代码来处理堆栈估算。
例如,附录I显示了gcc Arm Embedded(利用NewLib)的堆栈检讨实用程序代码。

末了再说一点,鱼鹰知道 PID 系列文章很多道友都不是很感兴趣(从阅读量可以看出),但是鱼鹰还是会连续更新下去的,由于鱼鹰写这部分条记的初衷本来便是给自己看的,以是不会由于你们不感兴趣而停滞更新。

其余鱼鹰还想说的便是,一旦 PID 系列文章更新完毕,鱼鹰可能将停滞更新。

为什么呢,从去年 11 月份开始到,由于做公众年夜众号而花费了很大精力,但收成很小,而且最近的状态是总想着怎么写出一篇好的文章,而不是说怎么研究技能问题。
而本"大众年夜众号的文章里面,只有 KEIL 调试系列和少数几篇文章还算满意,其他文章的代价很少。
在鱼鹰看来,先有好的技能积累,才会有好的文章涌现。
最近一段韶光一贯在输出,而输入很少,以是鱼鹰准备停息更新,直到认为有足够的技能积累再连续更新。

那什么时候规复更新呢?鱼鹰无法确定,以是说如果你以为本"大众号没有代价了,那么可以取消关注。
但是鱼鹰想说的是,当公众年夜众号规复更新时,将呈现三大系列文章:

1、USB (包括如何低廉甜头一个调试器,将以它作为这个系列的终极目标)

2、FAT32FS 文件系统(源码理解,图解文件系统)

3、uCOS II (鱼鹰已全部看完并理解源码,只是须要点韶光写出相应的条记)

最近鱼鹰也算处于一种转型状态了,从单片机开拓转向 linux 开拓,不懂的知识点太多了,祝我好运咯!

查看原文:https://www.dianyuan.com/eestar/article-7724.html

固件升级履历总结

上面理论+实践当初花了3天韶光弄完的,但是,当你真正做项目的时候,你会创造,只有上面的这些知识还不足,还有更多的细节要去处理:

1. APP程序怎么跳转到BootLoader程序?

2. APP程序和BootLoader之间是否会相互影响

3. APP和BootLoader之间如何通报参数?

4. 固件更新一到一半,由于某种缘故原由失落败了(通信缺点、掉电),该如何处理?

5. 如何确保更新的APP是你须要的APP,而不是别的一个APP?

经由一个项目的固件升级功能洗礼,以上问题都得到了较好的办理,为了避免往后忘却,在此记录一下。
芯片为:STM32F103ZET6

第一个问题,APP程序怎么跳转到BootLoader程序?看似很大略,由于这是基本的功能,但是实际情形并不大略。

由前面的小节理解到,从BootLoader跳转到APP可以通过指针进行跳转,但是当你从APP通过指针跳转到BootLoader时,创造会涌现问题(详细缘故原由不明,有机会的话去研究一下)。
那么又该怎么办?

可以通过复位的办法,让程序重新从开始地址运行,有以下几种办法复位:

1、 内核复位

2、 系统复位

3、 上电复位

第一、第二种办法都是通过设置干系寄存器使单片机发生复位的,两者的差异便是,内核复位只复位芯片的内核,但对单片机的片上外设并不进行复位,比如USART、SPI、USB等外设是不会进行复位的。

系统复位的话,就会对全体芯片进行复位,不管是外设还是内核,都会回到最初始的状态,就如按下复位按键一样。

末了一种上电复位,实在和系统复位、按键复位的效果差不多,都是会进行全部复位的,不过这个须要外部硬件掌握单片机的电源的开启与关闭,增加了额外的硬件。

一开始鱼鹰准备采取系统复位的,直接设置寄存器触发导致复位,由于这样更彻底,测试创造项目中的单片机根本无法复位,而我自己的开拓板是能进行复位的,后来经由硬件工程师的查找,创造是看门狗电路导致无法复位,这样一来,系统复位这条路堵去世了(由于项目的硬件已经确定,无法再变动了)。

那么是否有其它方法,前面提到的指针跳转的办法创造会涌现问题,由于项目比较急,就没怎么花心思办理。
后来在调试过程中,溘然创造KEIL中的复位按钮是能进行复位的,那么问题就大略了,既然调试器能进行复位,那我该当也能进行复位才对,之前说了系统复位不好使,那么按下复位按钮时该当是采取的内核复位(实际上CMSIS-DAP调试器是有单独的一条复位线的,但是当时没考虑它可能采取了这种办法,只考虑可能采取了内核复位,阴差阳错)。

那么就试试内核复位吧,一试创造果真有效,但是由于内核复位不彻底,导致涌现了问题。

这就到了第二个问题,两个程序之间是否会有影响?

第一,首先从BootLoader对APP的影响考虑,我们知道,BootLoader程序也是须要一些资源的,比如串口之类的用于固件的传输,如果说BootLoader的寄存器和APP的寄存器配置哀求不一样,那么就可能涌现问题(鱼鹰的项目中还用了一个定时器喂狗,创造一进入APP程序就挂了,后来才找到这个缘故原由)。

比如BootLoader采取串口查询的办法吸收数据,而APP为了提高效率,利用DMA+空闲中断的办法处理,那么两者的寄存器配置肯定不同,那么该怎么肃清BootLoader程序对APP的影响呢?

有人说,让BootLoader程序用完串口之后自动复位串口外设即可,确实,这是一种方法,但是你是否考虑过两个程序是独立的,万一后面的人在BootLoader程序中忘却了复位串口呢?以是说,靠别人不如靠自己,与其担心害怕别人不靠谱,不如APP自己去复位串口,即APP在配置串口之前,可以先复位串口,再进行配置(从这里可以知道,为什么有些代码会利用XXX_DeInit()之类的函数在配置前复位片上外设,一开始以为是多余的,毕竟一样平常程序开始运行的时候一样平常都是上电之后才运行的,这个时候已经复位外设了,为什么还要多此一举,直到现在才明白这才是安全的做法)。

第二,从APP对BootLoader的影响考虑,APP程序利用的资源一样平常比BootLoader的资源多,如果两者之间利用了相同的资源,比如串口,那么肯定得考虑两者的差异性,以是根据上面的考虑,也可以让BootLoader程序在利用串口之前前辈行复位,然后再进行配置,这是比较安全的做法。
但是仅仅如此就足够了吗?

在项目里的APP程序中,有一个加热过程,如果说APP跳转到BootLoader之前没有考虑这一点就盲目的运行到BootLoader,那么很可能涌现APP正在加热,但是由于跳转到了BootLoader中运行,导致无法对温度进行掌握,那么结果将是灾害性的,轻点的只是设备烧毁,重的可能就引发失火了。

以是说,两者之间的影响一定要慎重考虑。

事实上,如果采取系统复位或者上电复位的办法,第二点关于APP对BootLoader的影响是可以不考虑的,由于系统复位或者上电复位自动将外设进行初始化了,但是你不能肯定你现在采取这些办法,往后就不会采取内核复位的办法,所以为了安全,还是要考虑进去。

现在说说第三个问题,APP和BootLoader之间如何通报参数?

首先思考为什么要通报参数?

在前面的小节中,选择让BootLoader程序在开始复位时等待一段韶光再进入APP运行,在等待的过程中,就可以判断是否须要固件升级,比如等待时,由上位机发送一条分外的命令确定是否升级,或者通过引脚电平等办法,反正便是要让BootLoader程序知道,下面我要开始升级了,别急着进入APP运行。

但这里有一个问题便是,这里须要一个冷启动的过程,即先上电后再吸收命令,而且韶光短暂,有一个好处便是,纵然单片机中暂时没有APP程序,也能够实现固件升级过程,这样担保了由BootLoader吸收升级命令而不是由APP吸收,以是当初在无法办理升级到一半时如何规复时有考虑利用这种逼迫升级的办法。

那么有没有更好一点办法,不须要冷启动过程,而是由APP决定是否升级?有的。

既然是APP决定是否升级,那么肯定须要在进入BootLoader之前给它通报一个参数,见告它,这次复位须要升级,不能直接跳到APP中运行,那么BootLoader就会乖乖地等着升级了。

那么怎么通报呢?有人说往FLASH中写入参数,这样复位的时候就可以判断是否须要升级了,这确实是一个方法,但是我们知道,如果我们要往FLASH写入参数,那么必须前辈行擦除事情才行,而擦除的每每是一个扇区,为了写入几个字节的参数,擦除几K的数据,鱼鹰觉得实在是太摧残浪费蹂躏了;还有这个参数保存地址也是须要好好考虑的,放在APP区还是BootLoader区?那么有没有更好的办法?

有的。
还不但一种。

一开始鱼鹰想到的是利用后备域保存参数,由于如果有电池存在的话,它的数据是不会丢失的,但不巧的是,这个项目没有这个功能。

还有可以利用外部的FLASH空间,有些FLASH芯片是可以进行字节编程的,不须要整片擦除,挺得当的。
但是缺陷便是,你的项目要有这种芯片,而你的BootLoader须要写相应的代码驱动这个芯片,显然很麻烦。

末了鱼鹰采取的是RAM传参。
鱼鹰在之前的小节说过,APP和BootLoader共用RAM,如果说能用RAM通报参数的话,只是操作一个变量,相称方便。

但是怎么担保两者之间顺利通报参数呢?

我们知道,C措辞申请的变量空间是由编译器自动分配的,也便是说,同样申明一个同名变量,APP和BootLoader申请的变量地址不一定是一样的,而且还有一点便是,纵然你申请的变量通过某些方法让它地址固定,也会有问题,由于申请的变量会在进入main函数之前会被初始化掉,当然你可以说通过某种办法让它不被初始化,但是鱼鹰想到了更好的方法。

通过指针直接操作RAM空间末了几个字节用于参数通报(之前有看到说STM32单片机中有个寄存器可以直接掉电不丢失,但详细不知道是哪一个)。

由于采取指针操作,以是编译器并不会对你指向的地址进行初始化,这样可以很方便的绕过编译器的处理。
其次,通过操作末了几个字节,担保了这个空间不会被程序的其他变量占用(实在占用了也关系不大,只要你通报的参数足够特殊,比如0x05055555,就问题不大)。

这样,BootLoader在复位后只要检讨这个地址的值,就可以轻松知道是否该升级了。

但是还有一个隐患便是,在上电那一刻,如果这个地址的值刚好是你设置的分外值(由于上电后,RAM的值是随机的),那么一定会涌现问题,但这种可能性微乎其微,由于要让四个字节在复位哪一刻刚好都变成你设置的分外值,切实其实比中彩票还要困难。

不过纵然你真的中彩票了,重新上电复位一下就好了,如果说第一次中彩票还能接管,第二次还如此,那就须要烧烧喷鼻香、拜拜佛了。

须要把稳的是,一旦利用完这个参数,必须清零,防止下次内核复位又进入升级了(比如在线调试时可能会利用KEIL中的复位按钮)。

第四个问题,固件更新一到一半,由于某种缘故原由失落败了(通信缺点,掉电),该如何处理?

我们知道,升级过程中很大可能是会失落败的,但是单片机升级不像电脑升级,这次升级不堪利,规复本钱来的系统便是了。
单片机空间有限,没办法同时保存两份APP程序的,那么又该如何处理呢?

现在换个角度思考,你如何确定你升级失落败了?如果能做到这一点,那么你的BootLoader程序就可以在升级失落败后连续运行BootLoader的程序,而不进入APP运行那只升级到一半的程序(运行这种半残程序,鬼知道会发生什么怪异事宜呢)。

如果从这个角度来看,实在就大略了,只要上位机把bin文件的大小发下来,然后由BootLoader程序判断是否升级完造诣可以了,而Ymodem刚好可以有这个功能。

但是这样一来,就涌现了一个问题,须要一个掉电不丢失的参数来保存是否升级成功,否则下次上电又会连续运行APP。
但是鱼鹰对全体扇区擦除的办法很反感,便是不愿利用这种办法,怎么办?

苦思冥想之下,终于找到了一个奥妙的办法去处理。

我们知道,运行APP之前,一样平常会对APP的前面8个字节的栈顶指针、复位地址的合法性进行判断,判断是否是有效的APP程序,毕竟随便拿一个程序去升级,还不乱套了。

不管若何,APP程序都是要往FLASH更新程序的,那么我们是否能利用这个过程呢?

APP更新之前,必定把该擦除的扇区进行擦除了,如果说我们一开始,就对写入的事情进行分外处理,那么是否可以达到我们想要的效果呢?

比如说,前面8个字节,本来是在一开始的时候就会被写入的,如果我们在一开始写入数据的时候,跳过这8个字节的写入,然后把剩余的代码全部写入,当判断已全部吸收到(大于即是bin文件大小,由于Ymodem协议轻微有点分外,末了一帧数据可能添补0)固件之后,末了再对前面8个字节写入,这样一来,就担保了程序的完全性,如果说你中途数据中断了(掉电或上位机中断),那么前面那8个字节肯定不会写入,也就无法正常进入APP中运行了。

第五个问题,如何确保更新的APP是你须要的APP,而不是别的一个APP?

前面的问题担保了更新的程序是完全的,但是完全的程序不一定便是你须要的程序,那么怎么确定是你须要的APP呢

通过bin文件名来确定吗?这是一个方法,但是bin文件名可以被用户轻易变动,那就只能从bin文件内容本身入手了。

常规方法是,通过某些工具,在bin文件中加几个字节标着文件的分外性,但是众所周知的是,鱼鹰比较

那么有什么办法呢?就从代码本身入手好了。

方案确定下来了,但是怎么处理呢,标志位放在哪里,怎么放?又是一番苦思冥想。

一开始想到的是想将标志位放在bin文件末了,但是bin文件的大小是不固定的,虽然说上位机可以把bin文件大小传下来,但是怎么放是个问题,开始打算通过修正链接文件实现,但是创造自己对链接过程不熟,对汇编措辞(汇编可以指定地址)也不熟,怎么办?

终极鱼鹰选择把程序标志放在向量表的后面,即通过指定变量地址的办法担保地址唯一性(须要把稳一点的便是,通过指定地址的办法,不一定就确保终极的地址便是你设定的地址,如果和其它地址冲突了的话,可能不一致,须要看map文件确定)。
而且在设置APP程序的时候,一样平常都会重新定义向量表的位置,那么可以在定义标志地址时利用这个地址进行偏移。

当BootLoader在写前面8个字节前,只要再判断这个地址的标志位是否精确即可。

到此,固件升级方面的知识该当比较完善了,但还有一个问题,如何对bin文件加密与解密呢?

这个问题只有下次项目须要的时候再研究了。

查看原文:https://www.dianyuan.com/eestar/article-7725.html

PID 调节之 P(proportion)调节

首先看 P 调节的公式:

PWM 为输出电压,Kp 为放大系数,e(K)当前偏差,

即设定速率值和当前测得的速率 n 的偏差。

现在开始进行剖析。
先假定一些情形,便于理解(只用于定性理解,不能定量剖析):

速率最大为 1000(即单位韶光的测得的脉冲数);输出 PWM 的值最大为 8000,即 8000 时占空比为百分百。
Kp 为 10

现在假定速率设定值为 700(目标),电机还没有启动,即速率为零,那么偏差 e(K)为 700,此时输出 PWM =700Kp=7000,占空比为 7000/8000,此时的掌握电压很大,但是速率为零,根据之前的知识可知此时电机电流(启动电流)很大,大于负载所需电流,即电磁转矩大于负载转矩,电机开始加速,转速上升,并且电流开始低落。

截取个中一个韶光点,如果转速上升至 300,偏差 e(K)=700-300=400,此时 PWM=40010=4000,这个 PWM 比上一次的 7000 更小,即掌握电机的电压小,使电流更小,这时如果电流大于负载电流,速率还是会连续上升的,直到达到一个平衡:转速上升时,电流低落至刚好和负载电流相等,即转速不再上升了,既然转速不再上升,那么电流就不再低落,即达到一个平衡情形。
现在速率到达平衡速率:转速上升至 400,e(K)=700-400=300,PWM=30010=3000。
这便是利用 P=10 后终极的调节速率。

即在 P=10,负载不变的情形下,终极 P 调节后的速率是 400。
明显和 700 的目标速率相差较大,但是在 P=10 的情形下只能调节到这种程度。
那有没有办法再提高呢?不说提高到刚好 700,600 也行啊,这样就知道该怎么减小偏差了。

还是看公式理解:

PWM=Kpe(K)

从刚才的剖析可以创造终极的输出 PWM=10300=3000,以是导致偏差太大,如果终极把 PWM 升高至 6000 而不是 3000,速率一定是不会只达到 400 的程度,肯定有更高的速率,也就更靠近 700 了,以是现在把 Kp 设置为 20,我们可以重新剖析一下,可以知道在速率再次达到 400 时,PWM 已经到了 20300=6000,之前在 PWM 为 10300=4000 时达到平衡,这次是 6000,由于负载不变,一定电流大于负载电流,速率还是要连续上升的。
终极我们假定平衡时速率为 600(实在这些数据只是一个方向,终极是若何的须要精确打算,比如终极是 600 这种情形下是经不起剖析的,由于 e(K)=100,PWM=2000,这是不对的,以是终极的偏差不可能是 100,肯定大于该数的,终极的 PWM 比 3000 大,不可能小,不然速率不可能提高的),这样的速率离设定目标 700 又更近了。

从这里我们可以创造 P 调节的实质便是将偏差放大,利用非常小的偏差通过 Kp 进行放大得到我们的所须要的 PWM(即对应的掌握电压)。
如果我们要想使偏差为零,我们必须把 Kp 设置为无穷大才可能,事实上这是不可能的(书上 P25)。

事实上 P 调节系统便是依赖被调量的偏差进行掌握,如果没有偏差,那么根据 PWM=Kpe(K) PWM 输出便是零了,也就没有掌握电压了。
以是这样的调速系统是有静差调速系统。
这是 P 调节的实质导致不能肃清静差。

但是如果为了得到最小的偏差,是不是 Kp 越大越好呢,理论上是这样,但是它有一个放大倍数 Kcr 限定(书上 P33),如果放大倍数 Kp≥Kcr,系统不稳定。
对付一个自动掌握系统来说,稳定性是它能否事情的紧张条件,是必须担保的。

以是在 Kp<Kcr 的条件下,Kp 一样平常比较大,还是上面的例子,若 Kp=30,在设定值为 700 的条件下,初始 PWM=30700=21000,而 PWM 最大为 8000,以是必须限幅,把它限定在 8000 以下。
而 PWM 为 21000 的情形下,实在便是饱和的情形,此时由于限幅的浸染,使它对速率的变革是没有反应的,只有在速率上上升至 8000/30 才会有调节浸染。
实在这种饱和对调节没有多大关系,由于它是只要在到达设定速率前开始调节就行,由于它只和当前偏差有关,和之前的偏差没有关系。

之前剖析的是负载不变的情形下,P 的浸染。
现在剖析负载变革的情形。
我们在之前的剖析知道,P 便是将小的偏差放大,得到我们所需的掌握 PWM,以是 P 是一定须要的。
如果须要比之前更小的偏差,在同样的掌握 PWM 下,我们须要更大的 P 值。

但是 P 值不能大于 Kcr,否则系统不稳定。
同样的,在负载变革的时候,也是根据偏差放大来得到掌握电压的。
负载增加时,速率一定低落(暂时),即反馈后的偏差 e(K)增加,而 P 值在正常情形下设定之后是不能变的,导致得到更大的 PWM 来抵抗负载的滋扰,这样掌握电压就会增加,此时的电机运行曲线就不是刚才的那一条,而是向上移动,进入另一条运行曲线,这样就能抵抗刚才的负载扰动。

看下图:

这是开环曲线和闭环曲线。
假设原始事情点为 A,负载电流为 Id1,当负载增加到 Id2 时,开环系统的转速一定降到 A’点所对应的数值,闭环后,由于偏差增加,电压可升到 Ud02,使事情点变成 B,稳态速降比开环系统小的多。
这样,在闭环系统中,每增加(或减少)一点负载,就相应地提高(或降落)一点电枢电压,因而就调换一条机器特性。
闭环系统的静特性便是这样在许多开环机器特性上各取一个相应的事情点,如图的 A、B、C、D、……,再由这些事情点连接而成。

由此看来,闭环调节系统能过减小稳态速降的本色在它的自动调节浸染,能过随着负载的变革而相应的改变电枢电压,以补偿电枢回路电阻压降的变革。

但是只用比例放大器的反馈掌握系统,其被调量仍是有静差的。
从静特性剖析中可以知道,闭环系统的放大系数 K(不是 Kp,但和 Kp 有关)越大,系统的稳态性能越好。
还有一点须要解释的是在同样的闭环条件下,随着负载的增加,偏差会越来越大。
可以看闭环系统的稳态速降:

△ncl 为闭环系统的稳态速降,K 为闭环系统的开环放大系数。
从这里我们可以看到,随着负载增加,Id 增加,稳态速降也增加,也便是和目标值的偏差越来越大。

查看原文:https://www.dianyuan.com/eestar/article-7721.html

延时功能进化论之概述

在这篇长达万字的长文中,鱼鹰将通过延时这种刚需功能聊聊溢出、可重入、编程思想、共享变量保护等方面内容,以延时功能为载体,能更好的理解这些缥缈的知识点。

本篇长文将分成五篇陆续发布:概述、V1.0~V1.5、V1.7、V2.0~V2.4、V2.5~V2.7。

在生活中,韶光与我们的生活息息相关,日出而作,日落而息,说的便是利用太阳来大概判断韶光,从而方案自己的作息。
而在单片机领域,同样须要一个韶光去掌握你的代码运行情形。

玩单片机的该当都理解过晶振,很多初学者可能会从前辈那里得到这样一个比喻:单片机的心脏。
从功能的角度来说确实如此,由于单片机代码确实是依赖晶振实行的,比如说晶振输出一个脉冲,CPU实行一条指令,就像心脏跳动一次,你做一个抬手动作。
只不过你的心脏可能1秒只能跳动几十次,而晶振1秒输出脉冲几十兆赫兹(1 MHz = 1,000 KHz = 1000,000 Hz),而一样平常单片机还会将晶振输出的频率进行倍频,倍频后的频率才终极用于驱动CPU的运行。

如果说现实生活中,韶光的最小单位是秒(该当没人在生活和事情中去精确到毫秒吧,更多可能是分钟),而在单片机领域,常用的韶光单位该当是毫秒、微秒、纳秒,而决定韶光精度的便是晶振(更准确的说是经由晶振分频、倍频后的系统时钟,比如说 STM32 的 8 M 晶振分频成 1 M,然后倍频成 72 M 作为系统时钟驱动 CPU,进而实行存储器中的代码)。

对付运用开拓来说,可能他不会去理解晶振频率多少,系统频率多少,一条指令运行韶光又是多少?他们更多的需求是,在多少毫秒、多少秒(微秒很少用)之后这段代码实行一遍,这个界面刷新一遍,然后以这个韶光为周期,循环实行。
这是利用延时功能去达到特定代码周期实行的目的。

延时可分为相对延时和绝对延时,相对延时与绝对延时的差别可看下图理解:

(在后面先容的几种延时演进版本中,可自行思考采取何种办法延时)

本篇条记将根据鱼鹰多年编程履历先容自己如何实现延时功能。
说是进化论,不如说是鱼鹰个人延时功能的利用演进过程。

说到延时函数,51单片机过来的道友脑中该当会想起郭天祥老师视频中的延时函数,而利用原子例程的道友会想起例程中利用systick定时器实现的延时功能,只管他们的实现办法有所不同,但他们都是采取去世等的办法达到延时功能(所谓去世等,有个比喻鱼鹰以为挺恰当的:驴拉磨,让CPU一贯在一个地方打转,韶光到了就离开这个地方)。

去世等办法确实很随意马虎理解,也很随意马虎实现,但是它的弊病也很明显,不说它极大的摧残浪费蹂躏了CPU的资源(在延时过程中,除了能处理中断,后面的代码无法处理),更主要的是影响的代码的实行效果,比如说你有一个功能时须要20毫秒实行一次,而你的另一个功能却须要30毫秒实行,那你如何采取去世等办法处理个中的抵牾呢?既然是进化论,为了条记的完全性,鱼鹰将根据自己利用过的延时函数进行逐一解释。

查看原文:https://www.dianyuan.com/eestar/article-7719.html

更多精彩内容,尽在电子星球 APP(https://www.eestar.com/)

六篇技能文章,让你秒懂电容的脾气秉性

七篇DIY技能文章献给你,让你脑洞全开

五篇文章帮你开启DSP的学习思路

汇总篇:关于PID知识,重点在此

标签:

相关文章

五金模具设计制造完整的流程和办法方法

一套模具能不能顺利交样和生产以下几点是要模具干系职员关注模具一样平常设计是头(模具的灵魂),加工是模具的身体(模具的身体布局),调...

智能家居 2025-01-10 阅读0 评论0