7

由于没有操作系统,如何在编程PIC18时创建并行运行的线程?

4

13 回答 13

12

不要使用线程,使用事件循环。

PIC18 是一个小型处理器,基于事件循环的风格意味着您不必保留许多深堆栈。您需要根据事件循环编写代码,但这可能是合理的。

如果你确实有一些长时间运行的任务,使用定时器是不同的中断优先级,以允许较高优先级的事件循环抢占较低优先级的事件循环,并将适当类型的工作放入适当的事件队列中。

于 2009-10-26T11:31:40.827 回答
9

您可以尝试协作式多任务处理

对于 PIC 解决的问题类型,如果您尝试使用中断或轮询而不是多线程的不同设计,您可能会更好。

于 2009-10-26T11:21:56.720 回答
6

你可以在那里安装一个 RTOS(有一个非官方的 ucOS 端口,或者你可以查看FreeRTOS 的 PIC18 端口)。

否则,您可以尝试使用and来实现C 中的协程setjmplongjmp

于 2009-10-26T11:21:45.310 回答
5

如果根本没有操作系统,您(显然)必须自己重新创建必要的功能。

最简单的方法可能是安装一个以某个合适频率运行的定时器中断(可能取决于您的实际时钟速度,但可能在 100-1000 Hz 范围内)。在中断处理程序中,您需要检查当前线程的状态,并决定是否应该发生切换。

诀窍是在必要时进行切换,并从中断处理程序返回到不同的线程

当然,当线程本身可能使用中断时,让它工作并不一定容易。

您还可以考虑安装一些内核,也许是Contiki

是 PIC18 的“protothreads”示例,看起来是相当数量的代码。不过,不确定语义。

更新:这可能需要您在汇编程序中执行一些最低级别的代码(我不确定,没有在 PIC 上使用 C 语言,所以我不知道您获得了多少控制权)。您将需要控制程序计数器的寄存器,而这些不是 C 概念。

于 2009-10-26T11:24:28.420 回答
2

请注意,在微控制器上,某些“线程”也可以仅由某些特定的中断处理程序处理,因此无论如何都与您的主事件循环“并行”运行。

例如,如果您有一个外部事件触发 ADC 转换,您的 ADC-conversion-done 处理程序可以获取该值,进行一些计算,然后设置一些输出位以根据 ADC 值调整控制输出。所有这一切都可能发生在中断处理程序中,因此与其他一切并行。

根据您需要并行执行的操作,您可以选择多种技术的组合,以使工作按预期并行工作。

于 2009-10-26T11:45:56.843 回答
2

您可能想从嵌入式系统编程中阅读这篇文章: 构建一个超级简单的任务器

于 2009-10-26T13:49:42.453 回答
1

CCS 编译器包括一个 RTOS。我没有使用它,但是来自编译器手册

CCS 实时操作系统 (RTOS) 允许 PIC 微控制器运行定期调度的任务,而无需中断。这是通过充当调度程序的函数 (RTOS_RUN()) 完成的。当一个任务被调度运行时,分派函数将处理器的控制权交给该任务。当任务完成执行或不再需要处理器时,处理器的控制权返回给调度函数,然后调度函数将处理器的控制权交给安排在适当时间执行的下一个任务。这个过程称为协作多任务。

只是一个警告-查看他们的论坛以获取有关您正在寻找的特定功能的信息。显然 CCS 习惯于在新功能经过全面测试之前发布它们。这就是我仍在使用旧版本 (v3.249) 的原因之一。

于 2009-10-26T18:31:12.557 回答
1

我想分享我用 C 编程语言编写的微型内核来管理微控制器上的任务。您可以随时创建带周期的任务、暂停、恢复和更改任务周期。该内核可以根据需要删除所有任务以创建另一个音序器。内核提供了一个 TickGet 函数来根据需要管理所有计时器。您只需创建一个中断函数并替换函数 Timer() 即可为您自己的应用程序获取微型内核。恢复这个内核是基于循环链表,在任务上切换任务。它愿意以一种通用的方式编写,以帮助人们为自己的应用程序进行定制。任务之间没有优先级,就像循环任务调度一样。我根据 MISRA 指南(汽车规范)编写了这个源代码你可以在这里下载

我希望帮助人们在微控制器上管理任务。

于 2012-05-08T18:02:43.917 回答
1

在 8051 上,我使用简单的堆栈切换器完成了双任务。如果每个任务只使用 16 层堆栈,我希望在 PIC 上也可以这样做。代码将是这样的(假设 _altSP 在公共银行中)

_InitTask2:
    movff _STKPTR,_altSP
    movlw 16
    movwf _STKPTR,c
    转到_Task2Start

_TaskSwitch:
    movf _altSP,w,c
    movff _STKPTR,_altSP
    movwf _STKPTR,c
    返回

主任务应该调用 _InitTask2 来启动第二个任务。第二个任务将一直运行,直到它调用_TaskSwitch,然后主任务将按照调用_InitTask2 的指令继续执行。从那时起,每次一个任务调用_TaskSwitch,另一个任务将从它调用_TaskSwitch的最后一个地方恢复执行。

如果您使用这种方法,您的编译器将必须被告知所有寄存器都可能被调用_InitTask2 或_TaskSwitch 丢弃。还必须告知 _Task2Start 及其调用的函数必须与主任务分配不同的变量空间。

我不确定你需要告诉编译器什么让它开心,但我会说合作双任务可以让一些事情很好地工作。

于 2010-08-19T17:41:43.220 回答
0

Protothreads 库是多任务、跨平台的简单方法:http: //dunkels.com/adam/pt/

具有任务同步、计时器和用户数据的 PT 最小调度程序示例:https ://github.com/edartuz/c-ptx

于 2014-05-25T09:54:48.910 回答
0

这就是一个任务循环,以及提供任务的优先级,以及我喜欢将长时间运行的函数分解为切片的简单编码。

http://www.mculabs.com/drivers/qtask.html

于 2009-12-09T09:26:14.253 回答
0

我同意 ndim ——您可以将每个中断处理程序视为类似于“线程”的东西。有时你需要做的所有任务都可以由外部和内部事件触发的中断处理程序来处理——“主循环”是一个什么都不做的空闲循环。

我不知道有些评论者从哪里得到 PIC18 没有“操作系统”的想法。PIC18 有很多特定于 PIC 的多线程库和“多任务操作系统内核”,其中许多是免费和开源的。请参阅PICList:“PIC 微控制器特定的多任务方法”

于 2010-05-22T23:19:22.583 回答
0

我正在这样做(严格来说,固定调用堆栈深度的协作多任务处理)。

它有效,但 Hitec-c 编译器对我不利——它重用内存位置来存储它认为永远不会同时运行的函数中的临时变量。基本上线程会相互破坏。如果我想办法解决这个问题,我会用示例代码更新这个答案。

于 2012-12-22T16:17:27.277 回答