在PIC18上使用C实现多线程

在PIC18上使用C实现多线程,c,multithreading,embedded,pic,pic18,C,Multithreading,Embedded,Pic,Pic18,既然没有操作系统,如何在编程时创建并行运行的线程?您可以在上面安装一个RTO(有,也可以签出) 否则,您可以尝试通过使用setjmp和longjmp来实现 对于PICs解决的问题类型,如果您尝试使用中断或轮询而不是多线程的不同设计,可能会更好。如果根本没有操作系统,您(显然)必须自己重新创建必要的功能 最简单的方法可能是安装一个以适当频率运行的定时器中断(可能取决于您的实际时钟速度,但可能在100-1000 Hz范围内)。在中断处理程序中,您需要检查当前线程的状态,并决定是否应该发生切换 然后,

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

您可以在上面安装一个RTO(有,也可以签出)

否则,您可以尝试通过使用
setjmp
longjmp
来实现


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

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

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

然后,技巧是在必要时进行切换,并从中断处理程序返回到另一个线程

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

您还可以考虑安装一些内核

是PIC18的“protothreads”示例,看起来代码量合理。不过,我对语义不太清楚


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

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

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


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

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

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


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

您可能希望从嵌入式系统编程中阅读本文:

CCS编译器包括一个RTO。我没有用过,但从:

CCS实时操作系统 (RTOS)允许PIC微控制器 运行定期计划的任务 不需要中断。这 是由一个函数完成的 (RTOS_RUN())作为 调度员。计划任务时 要运行,dispatch函数提供 处理器对该任务的控制。 当任务完成或执行时 不再需要处理器, 返回对处理器的控制 到调度函数,然后 将处理器的控制权交给 计划执行的下一个任务 在适当的时间执行。这 这个过程叫做合作 多任务


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

这正是要做的事情,一个任务循环,以及规定任务的优先级,以及我喜欢的将长时间运行的函数分解成片的简单编码

我同意ndim——您可以将每个中断处理程序看作一个“线程”。 有时,您需要执行的所有任务都可以由外部和内部事件触发的中断处理程序来处理——“主循环”是一个不执行任何操作的空闲循环

我不知道一些评论者是从哪里得知PIC18没有“操作系统”的。
有相当多的PIC专用多线程库和PIC18的“多任务操作系统内核”,其中许多都是免费和开源的。请参阅。

在8051上,我使用一个简单的堆栈切换器完成了双重任务。我希望在PIC上也能做到这一点,只要每个任务只使用16层堆栈。代码应该是这样的(假设altSP在公共银行中)

_初始化任务2: movff_STKPTR,_altSP movlw 16 movwf_STKPTR,c 转到任务2开始 _任务开关: 莫夫-阿尔茨普,w,c movff_STKPTR,_altSP movwf_STKPTR,c 返回 主任务应该调用_InitTask2来启动第二个任务。第二个任务将一直运行,直到调用_TaskSwitch,然后主任务将按照调用_InitTask2的指令继续执行。从那时起,每当一个任务调用_TaskSwitch时,另一个任务将从它上次调用_TaskSwitch的位置恢复执行

如果使用这种方法,则必须通知编译器所有寄存器都可能被调用_InitTask2或_TaskSwitch而损坏。它还必须被告知_Task2Start及其调用的函数必须与主任务分配单独的变量空间


我不确定您需要告诉编译器什么才能使其满意,但我要说的是,协同双任务可以使某些事情非常好地工作。

我想用C编程语言共享我的微型内核,以管理微控制器上的任务。您可以创建具有期间的任务、暂停、恢复和一次性更改任务期间 _InitTask2: movff _STKPTR,_altSP movlw 16 movwf _STKPTR,c goto _Task2Start _TaskSwitch: movf _altSP,w,c movff _STKPTR,_altSP movwf _STKPTR,c return