大叶子 发表于 2025-4-27 08:42:55

TASK_Test.hex文件。文件时间显示,没有同时编译成功呢
这算问题吗?
是不能更改内容了吗?

Rebuild target 'Target 1'
User command #1: .\Auto_Keil.exe
compiling main.c...
compiling set_task.c...
compiling set_io.c...
compiling set_timer.c...
linking...
L251 LINKER/LOCATER V4.66.93.0 - SN: Eval Version
COPYRIGHT ARM Germany GmbH 1995 - 2018
@.\HEXFIL~1\TASK_T~1.LNP ".\Hex File\main.obj",
".\AI8051U_32_MDU32.LIB",
".\AI8051U_32_TFPU.LIB",
".\Hex File\set_task.obj",
".\Hex File\set_io.obj",
".\Hex File\set_timer.obj"
TO ".\Hex File\TASK_Test"
PRINT(".\Listings\TASK_Test.map") CASE DISABLEWARNING (16,57,30)
REMOVEUNUSED
CLASSES (EDATA (0x0-0x7FF),
HDATA (0x0-0x7FF))
******************************************************************************
* RESTRICTED VERSION WITH 0800H BYTE CODE SIZE LIMIT; USED: 122EH BYTE (227%) *
******************************************************************************
Program Size: data=8.0 edata+hdata=452 xdata=0 const=191 code=6811
*** ERROR L250: CODE SIZE LIMIT IN RESTRICTED VERSION EXCEEDED
    LIMIT:   0800H BYTES
Target not created.
Build Time Elapsed:00:00:01

angmall 发表于 2025-4-27 09:16:45

大叶子 发表于 2025-4-27 08:42
TASK_Test.hex文件。文件时间显示,没有同时编译成功呢
这算问题吗?
是不能更改内容了吗?

你的Keil C251 还没有注册。

Keil软件要注册才行。不注册只能编译小于2KByte。

和谐一下,找下注册机

大叶子 发表于 2025-4-28 08:55:07


我也奇怪,原先注册过了,一直用好好的,原来,
C251,过期了。
已经重新注册。
感谢,提醒!

明月清风 发表于 2025-5-6 14:37:39

例程是在C251下运行的8051U吗?

王昱顺 发表于 2025-5-6 14:58:58

明月清风 发表于 2025-5-6 14:37
例程是在C251下运行的8051U吗?

是的哩, 实际上只要是c语言环境都可以使用

Yang.Lian 发表于 2025-5-19 18:09:36

Protothreads

urada 发表于 2025-5-29 10:31:13

也可以看看这个: https://dunkels.com/adam/pt/, 原理是一样的, 都是无堆栈协程, 这个通用库功能多一点

dashuai 发表于 2025-5-30 15:55:03

可以的

fanxsp 发表于 2025-6-6 11:14:57

hhh402 发表于 2025-4-24 16:05
翻译了楼主首页的协程2:
_this_task=2;
if(task_num

这段代码确实没问题,有点令人意外,case 是可以放在 switch 中的代码块里面的。

Duff's device

The famous "Duff's device" in C makes use of the fact that a `case` statement is still legal within a sub-block of its matching `switch` statement. Tom Duff used this for an optimised output loop:

    switch (count % 8)
    {
      case 0:      do {*to = *from++;
      case 7:            *to = *from++;
      case 6:            *to = *from++;
      case 5:            *to = *from++;
      case 4:            *to = *from++;
      case 3:            *to = *from++;
      case 2:            *to = *from++;
      case 1:            *to = *from++;
                     } while ((count -= 8) > 0);
    }
```

We can put it to a slightly different use in the coroutine trick. Instead of using a `switch` statement to decide which `goto` statement to execute, we can use the `switch` statement to perform the jump itself:

int function(void)
{
    static int i, state = 0;
    switch (state)
    {
      case 0: /* start of function */
      for (i = 0; i < 10; i++)
      {
            state = 1; /* so we will come back to "case 1" */
            return i;
            case 1:; /* resume control straight after the return */
      }
    }
}

Now this is looking promising. All we have to do now is construct a few well chosen macros, and we can hide the gory details in something plausible-looking:

```
#define crBegin static int state=0; switch(state) { case 0:
#define crReturn(i,x) do { state=i; return x; case i:; } while (0)
#define crFinish }
int function(void)
{
    static int i;
    crBegin;
    for (i = 0; i < 10; i++)crReturn(1, i);
    crFinish;
}
```

(note the use of `do ... while(0)` to ensure that `crReturn` does not need braces around it when it comes directly between `if` and `else`)

This is almost exactly what we wanted. We can use `crReturn` to return from the function in such a way that control at the next call resumes just after the return. Of course we must obey some ground rules (surround the function body with `crBegin` and `crFinish`; declare all local variables `static` if they need to be preserved across a `crReturn`; *never* put a `crReturn` within an explicit `switch` statement); but those do not limit us very much.

The only snag remaining is the first parameter to `crReturn`. Just as when we invented a new label in the previous section we had to avoid it colliding with existing label names, now we must ensure all our state parameters to `crReturn` are different. The consequences will be fairly benign - the compiler will catch it and not let it do horrible things at run time - but we still need to avoid doing it.

Even this can be solved. ANSI C provides the special macro name `__LINE__`, which expands to the current source line number. So we can rewrite `crReturn` as

```
#define crReturn(x) do { state=__LINE__; return x; \
                         case __LINE__:; } while (0)
```

and then we no longer have to worry about those state parameters at all, provided we obey a fourth ground rule (never put two `crReturn` statements on the same line).
页: 1 2 3 [4]
查看完整版本: 【协程方式】实现【多任务调度 / 多线程】 仅需2byte的RAM 并带有详细视频讲解