Protothread 一个非常巧妙的轮询式多线程模型,也是 contiki 系统的内核,uip 和 lwip 作者 adam 的杰作
http://dunkels.com/adam/
proteus8.12.SP0 居然都支持 STC 51 单片机和 STM32 模拟了。。
https://www.52pojie.cn/thread-1432924-1-1.html  
链接:https://pan.xunlei.com/s/VMZq3HdA1_aoTPXmaYi4SkLsA1
提取码:p9qc
常见问题:
一、proteus 8.12_sp0和proteus_8.9sp2存在相同的问题,如果安装在非C盘目录下,打开后则会显示密钥错误和未注册的灰色字体;点击帮助后也是未注册。
这是因为破解器默认是你安装在C盘。
解决方法如下:
[1]、卸载后重装在C盘
[2]、1.先在C盘安装,破解.
        2.打开软件,发现有注册信息,则注册成功
        3.此时软件复制根目录的bin文件夹。
        4.卸载刚才安装的proteus
        注意:不要用第三方的卸载软件,在控制面版里卸载就行,更不要用everything之类的把残余文件删的干干净净
        5.重新安装,选择D盘。破解
        6.把刚才复制bin文件夹覆盖到D盘软件的根目录下,选择全部替换
        7.再打开proteus就显示注册成功了
-- 虽然有点脱裤子放屁的感觉,但能用就行
Protesu 仿真测试,两个线程控制 LED 闪烁,另外还有 mutex timer 等,可以参考 contiki 的内核实现。
仿真截图:
示例工程:
STCxx_Projects.rar
测试代码:
/**
  ******************************************************************************
  * @file    main.c
  * @author  Iron
  * @date    2021-01-01
  * @version v1.0
  * @brief   main c file
  */
/* Private includes ----------------------------------------------------------*/
#include "board.h"
#include "pt.h"
#include "delay.h"
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Two flags that the two protothread functions use. */
static int protothread1_flag, protothread2_flag;
/* Private function prototypes -----------------------------------------------*/
/**
 * The first protothread function. A protothread function must always
 * return an integer, but must never explicitly return - returning is
 * performed inside the protothread statements.
 *
 * The protothread function is driven by the main loop further down in
 * the code.
 */
static int protothread1(struct pt *pt)
{
    /* A protothread function must begin with PT_BEGIN() which takes a
       pointer to a struct pt. */
    PT_BEGIN(pt);
    /* We loop forever here. */
    while (1)
    {
        /* Wait until the other protothread has set its flag. */
        PT_WAIT_UNTIL(pt, protothread2_flag != 0);
        /* thread code... */
        led_togger(LED0);
        delay_ms(100);
        /* We then reset the other protothread's flag, and set our own
           flag so that the other protothread can run. */
        protothread2_flag = 0;
        protothread1_flag = 1;
        /* And we loop. */
    }
    /* All protothread functions must end with PT_END() which takes a
       pointer to a struct pt. */
    PT_END(pt);
}
/**
 * The second protothread function. This is almost the same as the
 * first one.
 */
static int protothread2(struct pt *pt)
{
    PT_BEGIN(pt);
    while (1)
    {
        /* Let the other protothread run. */
        protothread2_flag = 1;
        /* Wait until the other protothread has set its flag. */
        PT_WAIT_UNTIL(pt, protothread1_flag != 0);
        /* thread code... */
        led_togger(LED1);
        delay_ms(100);
        /* We then reset the other protothread's flag. */
        protothread1_flag = 0;
        /* And we loop. */
    }
    PT_END(pt);
}
/**
 * Finally, we have the main loop. Here is where the protothreads are
 * initialized and scheduled. First, however, we define the
 * protothread state variables pt1 and pt2, which hold the state of
 * the two protothreads.
 */
static struct pt pt1, pt2;
int main(void)
{
    board_init();
    /* Initialize the protothread state variables with PT_INIT(). */
    PT_INIT(&pt1);
    PT_INIT(&pt2);
    /*
     * Then we schedule the two protothreads by repeatedly calling their
     * protothread functions and passing a pointer to the protothread
     * state variables as arguments.
     */
    while (1)
    {
        protothread1(&pt1);
        protothread2(&pt2);
    }
}
/**
  * @}
  */
/******************* (C)COPYRIGHT 2021 ***** END OF FILE *********************/离线
准确的说,这个不是真正的多线程,就是一个超级大状态机。
有人用这个库编译出来的代码,会比不用这个库的代码大很多。
离线
用协程不是体积更小一些
离线
感谢作者分享,但是感觉示例给的有问题,delay_ms 中没有进行任何调度,如果一个线程中 delay_ms(1000),另一个 线程中 delay_ms(100),个人分析两个LED只能以1.1s左右闪烁,而不是一个1s,另一个0.1s闪烁。
这个库很小巧,但是不能在线程中使用死循环方式进行延时。
离线
协程非常时候那种小资源的单片机使用。
离线
@llinjupt 
我深表赞同!
离线