有啥不一样
仅两行核心代码就实现了来回循环的流水灯,代码如下:
// P_10 --> P_17 依次点亮
#define UP 0
// P_17 --> P_10 依次点亮
#define DOWN !UP
void led_flow(void)
{
static direct = UP;
// 上下流水,注意初始化 0xFF 和 0x8F 的位移操作
P1 = (direct == UP) ? (P1 << 1 | (P1 == 0xFF ? 0x00 : 0x01)) : (P1 >> 1 | (P1 == 0x8F ? 0x00 : 0x80));
// 流水灯掉头
direct = ((P1 == 0x7F && direct == UP) || (P1 == 0xFE && direct == DOWN)) ? !direct : direct;
}
就这?
当然了,上面的流水灯代码并没有什么出奇的地方,真正有意思的地方来咯
void main(void)
{
// 初始化调度器
hsch_init_timmer2();
// 追加任务,流水灯
hsch_add_task(led_flow, 0, 1000, SCH_COO_TYPE);
// 启动调度器
hsch_start();
while (true)
{
// 派遣任务
hsch_dispatch_tasks();
}
}
上述几行代码才是整个精华,可以看到 led_flow
方法并没被直接调用,而是通过 hsch_add_task
加到了一个任务池子里面,然后被系统所调用
原理
c51 一般不带系统的,所以没有相关的线程调度机制,这里手工实现了一个简单的调度器,hsch 是 hybird scheduler(混合调度器)的缩写,含抢占式调度器和协作式调度器,相关的介绍可以《调度器》相关的书籍和博客,其原理大概长下面这个样子
可以看到,通过调度器将一个中断等事件转换成任务句柄提交到任务池,然后定时器不断去轮询任务池提取可执行的任务交由 mcu 去执行,同时在整个调度流程中可以输出相关日志方便做一个链路监控
扩展
上述调度器仅用到了一个 MCU,可以更大胆一点实现一个调度器集群(几百块 MCU),实现也不复杂接入通讯芯片,外加一个共享的存储单元即可
- 源码
https://github.com/ychost/HybSCH