事先说明,在下也是一个小白,纯萌新(认真脸.JPG),所以难免有错误的地方,所以恳请各位大大指出来,小的立马改~(Orz)。
好,进入正题,非阻塞系统是啥,与之相对的阻塞系统又是个啥,我个人理解的话就是:非阻塞系统就相当于高速公路,车辆一旦上路,就别想停下来。阻塞系统就类似于在郊区闹市行车,时不时就来一个红绿灯。
上面例子里面,阻塞系统的红绿灯就好比是我们单片机常用的delay函数,就是让cpu跑循环,来达到延时的作用。这样的话虽然很好,但有个小问题,如果,需要处理的任务特别多的话,你cpu大部分时间都在等红绿灯了(划去)跑循环去了。举个例子,如果你就是出租车司机的话,前面有个人想上车,还很急,这时候你一直在等红绿灯,过一会这个乘客不耐烦了,就走了。这就是阻塞系统的弊端。
关于非阻塞系统的话,cpu几乎不会跑空循环函数,cpu几乎随时随地都在处理命令。
在举个栗子:
以后各位单身狗独立出来(快到情人节了,但这和我单身狗有什么关系呢?T^T),不想出去,就居家做饭。
做饭先蒸一锅米饭,然后炒菜(先举这两件事)。
这时候阻塞系统处理的话,就是蒸米饭需要30分钟,得勒,我就米饭倒锅,开煮,然后我就正襟危坐看着这锅米饭,(30 minute later~)饭熟了,这时候站起身来:“啊~该炒菜了,又是充实的一个中午呢~”(看到这,你觉得充实吗?你大部分的时间都在空置着,换到cpu这可是极大的浪费啊!)。
非阻塞系统会怎么办?非阻塞系统开始步骤都一样,米放锅,插电 。然后就跑去炒菜了,要是不放心,过个十分钟抽空看一眼,直到饭熟了。这时候菜也炒好了,用时30分钟。
这个例子我觉得就能很好的,讲明白阻塞系统和非阻塞系统的区别了。
阻塞系统就按下不表了。
主要讲一讲非阻塞系统。
再再再举个例子:x战警看过没,里面有个人物叫快银,他可以自己和自己打乒乓球,他会分身吗?并不会,他只是很快,宏观看上去就是自己和自己打乒乓球(虽然一直想吐槽,这么快速度打乒乓球应该没啥乐趣吧)。极端一点,他甚至可以同时干好多事情,虽然在他自己来看是按顺序做的。
类比到单片机就拿stm32单片机来讲,f1主频达到72M,处理能力应该和快银,闪电侠之流差不多。所以这时候我们就试着模仿一下快银来处理事情。
所以就有了非阻塞系统框架。
(首先说一下,这是我自己搭的一个框架,基本原理是用定时器中断来的。虽然我看到有的大佬用结构体,联合体什么的,但在下才疏学浅,未能参悟,所以就按我自己的版本讲一下)
首先就是,设置一个基准的脉冲,每隔1ms就进入一次定时器中断,这直接就在cubemx里面配置就好了。


这样就开启了定时器中断,主分频器设置成719;预分频器设置为99
也就是1ms进一次中断。
有中断,就必有中断服务函数
uint32_t CNTSTEP = 0;//这个变量的作用是作为进入一次中断就+1;标志着第几个毫秒
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
CNTSTEP++;//进入一次中断就加一
if(CNTSTEP==1000)
{
CNTSTEP = 0;//加到1000ms 也就是1s就清零;
}
}
}
然后嘛就很简单,开始写任务函数~
void mission_A_2ms()
{
if(CNTSTEP == 2){
//任务A内容(比如蒸米饭);
}
}
任务函数就是这样子,第几个中断,大致代表着第几个毫秒,然后用if告诉cpu:”皇上~您该下命令煮饭了(花费了几个us)”,cpu(皇帝):"好,那就做饭吧(过去了几个us)"然后皇帝继续批折子,到了30ms,饭熟了。if就颠颠的报告说:“皇上~饭熟了,能呈上来了。(几us)”,cpu(皇帝):“啊~麦芽的香气,开饭开饭(几us)”。
这就是一个非阻塞系统的编写需要的步骤。
很简单吧,但是有一条禁忌千万不能碰,不要在非阻塞系统里面加阻塞系统的东西,削微的几us的延时可以考虑,但是你一旦想延时个几毫秒,那还是算了,这边建议出门找状态机编程。用阻塞式延时的话,就好比在高速路上猛刹车。容易上热搜,整个项目也容易一脸懵逼不知道该干嘛(就成了车祸现场了~)。
另外,提前祝各位看官情人节快乐(单身狗就和我一块儿汪起来~嗷~~~~)。