论文部分内容阅读
摘 要:针对国内32位单片机在工业自动化领域产品设计中的普及使用,结合国外先进实时多任务系统以及传统前后台系统的优点,设计一套由多任务调度机制和前后台中断触发机制相结合的实时操作系统,自动完成任务调度,及任务状态统计分析,通过搭建统一工业级软件运行平台,增强产品的模块化设计,提高产品功能安全性能。
关键词:32位单片机;工业自动化;实时多任务系统;前后台系统;统一工业级软件运行平台;模块化
中图分类号:TP368.1
随着32位单片机功耗及成本的降低,其在工业控制领域的使用正在逐步普及。由于32位单片机提供给了工业级智能型产品开发者更多的内存空间及外设资源同时具有更快的处理速度,更高的运行效率,并且与DSP控制器逐渐同治化,在控制及信号处理领域很有发展前景;在32位单片机前,由于性能的局限性,对每个基于单片机的产品的开发,更多的是考虑如何使用有限的存储空间以存储数据和程序,如何改进算法使得单片机能跑得起来而又不影响实时性。因此每款产品的系统架构几乎都是独立的,是基于该产品的功能定制的,使用的单片机类型也多种多样,不具备通用性,在后期移值和借鉴方面存在很大的困难;随着32位单片机进入工业控制领域,其存储空间大,运行速度快,功耗低,可控外设多等优势突现出来;使得软件系统架构的标准化、规范化得以实现,就如同民用PC操作系统一样,使得所有应用开发者有机会在一个统一的稳定的平台下,采用同一规范开发不同种类的应用程序,实现不同的功能;将功能的实现和系统分离,得以保证系统的稳定性,使产品开发者不再为每款产品搭建低层系统架构,可以专注于产品的功能需求和功能应用的开发;我们通常将32位单片机中采用的系统称为嵌入式系统;
嵌入式系统通常采用两种模式,第一种是前后台系统(也叫超循环系统);第二种是多任务系统;这两个系统各有优点,前后台系统在工业产品方面特别是工业现场仪器仪表类产品比较常见,工业化智能产品功能相对单一通常用于采集传感器信号进行前期处理后将数据信息远传给控制系统,同时只需要处理几件具有前后因果关系的关联事务,而主要强调系统的安全性及可控性,系统注重在某个固定的时间点,执行/完成某个固定时间段的任务,某项任务必须在另一项任务完成后开始执行,否则属于无效任务;多任务系统在民用产品以及二次仪表和控制系统中采用交多,具有可以同时并行处理多项互不相关的任务的能力,能够提供多元化的功能配置,相比前者系统逻辑控制比较复杂,特别是在任务间信息传输和任务见内存分配上,及任务调度机制方面,对开发者各方面具有较高的要求,在多任务系统上开发产品需要循序渐进,要很熟练的掌握系统的性能需要交长时间的学习和使用;
因为32位单片机在商业领域推广已经十几年了,目前国内采用的由几家国外大公司开发的多任务操作系统技术方面已经比较成熟,对现有多任务嵌入式系统版本的更新也多是围绕可执行更多的任务数量,任务优先级数量,任务调度方法,系统检测能力,信息传输方法等方面;而工业控制领域从2011年开始普及32位单片机,因此国内/外仪器仪表生产企业对工业控制产品软件系统架构还没有统一的开发标准;本文就根据国际上对工业产品软件质量及功能安全标准相关要求,结合作者自己在仪器仪表产品开发过程中的实际应用,对工业产品软件系统规范化进行研究;
本文结合Ucos多任务系统以及前后台系统的优点,搭建了一套由多任务调度机制和前后台中断触发机制相结合的实时操作系统,该系统采用标准C语言编写,去除了不同单片机及编译器的相关性,可直接用于各型号32位单片机和高性能16位单片机的应用软件开发;通过加入少量指令也可以用于如电池供电型产品的超低功耗应用;
首先将系统的任务处理机从功能模块中独立出来;任务处理机作为系统的核心,主要功能是任务调度,以及任务运行状态分析处理;它并不关心任务具体完成的功能,只是确保各任务能够按照开发者提供给系统的任务配置正常运行,并统计输出具体的性能参数,给任务提供一个稳定的运行平台同时方面开发者读取个任务运行状态,减少任务开发过程中的不确定性;开发者只需要将功能需求,以任务的形式提交给系统,简单配置任务的优先级别,以及响应时间,系统自动运行并反馈任务状态,帮助开发者对任务进行优化;一个任务必须对应一个功能模块;而一个功能模块可以设计多个自任务;为了结构简单,逻辑清晰每个功能模块最好将任务数保持在三个以下;同一个功能模块下的任务之间的通信,可通过模块内部变量直接完成;不同功能模块下的任务之间的通信,可通过模块提供的接口完成;这样可以优化系统的模块化配置,减少某功能运行出错带来不确定因素;每个功能模块相互独立,有各自的初始化配置,完成任务,纠错与自恢复能力;系统通过任务状态机读取任务配置信息,自动完成任务调度,并将任务信息提供给相应功能模块分析处理,当任务执行时序发生错乱时系统能对其进行监控并进行恢复如图1:
图1
每个功能模块由输入接口、输出接口、模块内部变量和方法三部分组成如图2:
图2
任务处理机由任务状态分析机、任务调度机、模块内部变量和方法三部分组成如图3:
图3
为了满足任务安全控制要求,需要在进入任务前设置先决条件判定,任务完成后设置后续条件判定以避免任务执行逻辑顺序出错,如果运行过程中发现存在错误,既对任务安全状态进行恢复如图4:
图4
根据工业仪器仪表产品的需求分析可以将系统分解为十个主要的功能模块如图5:
图5
对以上功能模块进行详细设计得到与各模块功能对应的子任务函数及模块间通信接口如图6:
图6
以下是该系统软件设计,该系统是通过一个时钟中断进行驱动,时钟节拍通常设置为10~100ms,这里中断只是调用OS_TickInt函数产生一个时钟信号,而不进行具体操作(如果在中断加入退出低功耗指令,可以在每个节拍到来时唤醒系统,完成任务后再次触发指令进入低功耗模式),所有任务调度主要是通过时钟节拍中断触发Task_Tick系统任务完成,在单片机空闲状态下Task_Tick系统任务持续执行,计算采集到的中断中产生的时钟信号;并根据优先级和任务响应时间为依据将任务唤醒并执行;通过实验测试该系统能为每个任务提供一个准确的时钟管理,以至于不会因为某项任务运行时间较长,影响到其它任务时钟的准确性;由于该系统没有采用多任务系统中的子任务堆栈方式,高优先级的任务无法打断运行中的任务,但提供了任务遗失数据统计信息,能够满足绝大多数应用;该系统通过提供运行参数副本的形式供功能模块任务查询;而对副本数据的篡改也不会影响到系统的稳定性;本系统可提供任务执行时间长度,任务响应时间,任务计数器,任务丢失次数,任务优先级,任务超时警告,任务ID,任务名称等信息的统计;相对过去的前后台系统方式,本系统可提供的信息量更多,使得开发人员错误分析更方便,也降低了开发人员对系统的熟悉程度要求; 以下为时钟信号采集函数由类定时器中断函数调用,为系统运行提供基础时钟;
void OS_TickInt(void){
Task_TickNum++;
Goin=1;
}
以下为系统时钟运算及任务调度函数,通过时钟管理器计算OS_TickInt捕获到的时钟信号,并转换成系统时钟节拍,驱动任务;
void Task_Tick(void){
uint8_t i,indexa=0,indexbegin=0;
if(Goin==1){
Goin=0;
Task_TickNumNow=Task_TickNum;
Task_TickNum=0;
if(Task_TickNumNow!=0){
for(i=0;i _Task_Sched[i].Tick+=Task_TickNumNow;
}
}
}
for(i=0;i=_Task_Sched[i].TickReload/Ticker){
if(indexbegin==0){
indexa=i;
indexbegin=1;
} if(_Task_Sched[i].Prio>=_Task_Sched[indexa].Prio){
indexa=i;
}
Goinsub=1;
}
}
if(Goinsub!=0){
Task_Seqcheck();
TaskPtr=_Task_Sched[indexa].Point; _Task_Sched[indexa].TimerLoseNum=Task_TickNumNow*Ticker/_Task_Sched[indexa].TickReload;
_Task_Sched[indexa].Goin=1; _Task_Sched[indexa].Tick=_Task_Sched[indexa].Tick%(_Task_Sched[indexa].TickReload/Ticker);
_OSStatus.TaskCurIndex=indexa;
Task_TickStart=Task_TickNum;
}
}
通过调用各模块初始化函数,完成系统及外设初始化状态配置,并将子任务插入系统就绪任务列表;
void SysConfig_Ini(void){
SystemInit(); //MCU时钟配置
OS_Ini(); //系统初始化 Task_Create(FirstTask,500,1,"First Task12124214"); //FirstTask任务建立,重装载时间500ms,优先级1,名称"First Task12124214"(由于字符数超过15个字符,系统按ID号给任务分配名称为"ID:xxx")
Task_Create(SecondTask,60,2,"Second Task"); //SecondTask任务建立,重装载时间60ms,优先级2,名称"Second Task"
}
上面的例子里,在系统上电时通过SysConfig_Ini函数配置向系统提交了10个常用任务,系统为每个任务分配了一个独立的时钟管理,通过时钟及任务优先级驱动各任务的运行。经过电脑仿真,效果如图7,说明该系统调度任务的效果能够达到预期要求,可以用于工业产品安全功能设计。
图7
参考文献:
[1]Halbleiterspeicher-Testfolgen.Th.John,E.Schaefer,Elektronipraxis,H.6,18-26 and H.7,10-14,1980.
[2]Signaturanalyse in der Datenverarbeitung.D.Leisengang,M,Wagner,Elektronik 32,H.21,S.67-72,1983.
[3]安全技术中的微机——面向开发者和生产者的一种工具.H.Holscher,J.Rader,Verlag TUV Rheinland,Koln,1986,ISBN 3-88585-315-9.
[4]计算机现在已能安全地执行关键的安全功能.Otto Berg von Linde,Railway Gazette international,Vol.135,No.11,1979.
[5]嵌入式实时操作系统uC/OS-II原理及应用.北京航空航天大学出版社.
作者简介:石磊(1981.5-),男,重庆人,中级,硕士,研究方向:自动化仪器仪表开发及软件工程应用。
关键词:32位单片机;工业自动化;实时多任务系统;前后台系统;统一工业级软件运行平台;模块化
中图分类号:TP368.1
随着32位单片机功耗及成本的降低,其在工业控制领域的使用正在逐步普及。由于32位单片机提供给了工业级智能型产品开发者更多的内存空间及外设资源同时具有更快的处理速度,更高的运行效率,并且与DSP控制器逐渐同治化,在控制及信号处理领域很有发展前景;在32位单片机前,由于性能的局限性,对每个基于单片机的产品的开发,更多的是考虑如何使用有限的存储空间以存储数据和程序,如何改进算法使得单片机能跑得起来而又不影响实时性。因此每款产品的系统架构几乎都是独立的,是基于该产品的功能定制的,使用的单片机类型也多种多样,不具备通用性,在后期移值和借鉴方面存在很大的困难;随着32位单片机进入工业控制领域,其存储空间大,运行速度快,功耗低,可控外设多等优势突现出来;使得软件系统架构的标准化、规范化得以实现,就如同民用PC操作系统一样,使得所有应用开发者有机会在一个统一的稳定的平台下,采用同一规范开发不同种类的应用程序,实现不同的功能;将功能的实现和系统分离,得以保证系统的稳定性,使产品开发者不再为每款产品搭建低层系统架构,可以专注于产品的功能需求和功能应用的开发;我们通常将32位单片机中采用的系统称为嵌入式系统;
嵌入式系统通常采用两种模式,第一种是前后台系统(也叫超循环系统);第二种是多任务系统;这两个系统各有优点,前后台系统在工业产品方面特别是工业现场仪器仪表类产品比较常见,工业化智能产品功能相对单一通常用于采集传感器信号进行前期处理后将数据信息远传给控制系统,同时只需要处理几件具有前后因果关系的关联事务,而主要强调系统的安全性及可控性,系统注重在某个固定的时间点,执行/完成某个固定时间段的任务,某项任务必须在另一项任务完成后开始执行,否则属于无效任务;多任务系统在民用产品以及二次仪表和控制系统中采用交多,具有可以同时并行处理多项互不相关的任务的能力,能够提供多元化的功能配置,相比前者系统逻辑控制比较复杂,特别是在任务间信息传输和任务见内存分配上,及任务调度机制方面,对开发者各方面具有较高的要求,在多任务系统上开发产品需要循序渐进,要很熟练的掌握系统的性能需要交长时间的学习和使用;
因为32位单片机在商业领域推广已经十几年了,目前国内采用的由几家国外大公司开发的多任务操作系统技术方面已经比较成熟,对现有多任务嵌入式系统版本的更新也多是围绕可执行更多的任务数量,任务优先级数量,任务调度方法,系统检测能力,信息传输方法等方面;而工业控制领域从2011年开始普及32位单片机,因此国内/外仪器仪表生产企业对工业控制产品软件系统架构还没有统一的开发标准;本文就根据国际上对工业产品软件质量及功能安全标准相关要求,结合作者自己在仪器仪表产品开发过程中的实际应用,对工业产品软件系统规范化进行研究;
本文结合Ucos多任务系统以及前后台系统的优点,搭建了一套由多任务调度机制和前后台中断触发机制相结合的实时操作系统,该系统采用标准C语言编写,去除了不同单片机及编译器的相关性,可直接用于各型号32位单片机和高性能16位单片机的应用软件开发;通过加入少量指令也可以用于如电池供电型产品的超低功耗应用;
首先将系统的任务处理机从功能模块中独立出来;任务处理机作为系统的核心,主要功能是任务调度,以及任务运行状态分析处理;它并不关心任务具体完成的功能,只是确保各任务能够按照开发者提供给系统的任务配置正常运行,并统计输出具体的性能参数,给任务提供一个稳定的运行平台同时方面开发者读取个任务运行状态,减少任务开发过程中的不确定性;开发者只需要将功能需求,以任务的形式提交给系统,简单配置任务的优先级别,以及响应时间,系统自动运行并反馈任务状态,帮助开发者对任务进行优化;一个任务必须对应一个功能模块;而一个功能模块可以设计多个自任务;为了结构简单,逻辑清晰每个功能模块最好将任务数保持在三个以下;同一个功能模块下的任务之间的通信,可通过模块内部变量直接完成;不同功能模块下的任务之间的通信,可通过模块提供的接口完成;这样可以优化系统的模块化配置,减少某功能运行出错带来不确定因素;每个功能模块相互独立,有各自的初始化配置,完成任务,纠错与自恢复能力;系统通过任务状态机读取任务配置信息,自动完成任务调度,并将任务信息提供给相应功能模块分析处理,当任务执行时序发生错乱时系统能对其进行监控并进行恢复如图1:
图1
每个功能模块由输入接口、输出接口、模块内部变量和方法三部分组成如图2:
图2
任务处理机由任务状态分析机、任务调度机、模块内部变量和方法三部分组成如图3:
图3
为了满足任务安全控制要求,需要在进入任务前设置先决条件判定,任务完成后设置后续条件判定以避免任务执行逻辑顺序出错,如果运行过程中发现存在错误,既对任务安全状态进行恢复如图4:
图4
根据工业仪器仪表产品的需求分析可以将系统分解为十个主要的功能模块如图5:
图5
对以上功能模块进行详细设计得到与各模块功能对应的子任务函数及模块间通信接口如图6:
图6
以下是该系统软件设计,该系统是通过一个时钟中断进行驱动,时钟节拍通常设置为10~100ms,这里中断只是调用OS_TickInt函数产生一个时钟信号,而不进行具体操作(如果在中断加入退出低功耗指令,可以在每个节拍到来时唤醒系统,完成任务后再次触发指令进入低功耗模式),所有任务调度主要是通过时钟节拍中断触发Task_Tick系统任务完成,在单片机空闲状态下Task_Tick系统任务持续执行,计算采集到的中断中产生的时钟信号;并根据优先级和任务响应时间为依据将任务唤醒并执行;通过实验测试该系统能为每个任务提供一个准确的时钟管理,以至于不会因为某项任务运行时间较长,影响到其它任务时钟的准确性;由于该系统没有采用多任务系统中的子任务堆栈方式,高优先级的任务无法打断运行中的任务,但提供了任务遗失数据统计信息,能够满足绝大多数应用;该系统通过提供运行参数副本的形式供功能模块任务查询;而对副本数据的篡改也不会影响到系统的稳定性;本系统可提供任务执行时间长度,任务响应时间,任务计数器,任务丢失次数,任务优先级,任务超时警告,任务ID,任务名称等信息的统计;相对过去的前后台系统方式,本系统可提供的信息量更多,使得开发人员错误分析更方便,也降低了开发人员对系统的熟悉程度要求; 以下为时钟信号采集函数由类定时器中断函数调用,为系统运行提供基础时钟;
void OS_TickInt(void){
Task_TickNum++;
Goin=1;
}
以下为系统时钟运算及任务调度函数,通过时钟管理器计算OS_TickInt捕获到的时钟信号,并转换成系统时钟节拍,驱动任务;
void Task_Tick(void){
uint8_t i,indexa=0,indexbegin=0;
if(Goin==1){
Goin=0;
Task_TickNumNow=Task_TickNum;
Task_TickNum=0;
if(Task_TickNumNow!=0){
for(i=0;i
}
}
}
for(i=0;i
if(indexbegin==0){
indexa=i;
indexbegin=1;
} if(_Task_Sched[i].Prio>=_Task_Sched[indexa].Prio){
indexa=i;
}
Goinsub=1;
}
}
if(Goinsub!=0){
Task_Seqcheck();
TaskPtr=_Task_Sched[indexa].Point; _Task_Sched[indexa].TimerLoseNum=Task_TickNumNow*Ticker/_Task_Sched[indexa].TickReload;
_Task_Sched[indexa].Goin=1; _Task_Sched[indexa].Tick=_Task_Sched[indexa].Tick%(_Task_Sched[indexa].TickReload/Ticker);
_OSStatus.TaskCurIndex=indexa;
Task_TickStart=Task_TickNum;
}
}
通过调用各模块初始化函数,完成系统及外设初始化状态配置,并将子任务插入系统就绪任务列表;
void SysConfig_Ini(void){
SystemInit(); //MCU时钟配置
OS_Ini(); //系统初始化 Task_Create(FirstTask,500,1,"First Task12124214"); //FirstTask任务建立,重装载时间500ms,优先级1,名称"First Task12124214"(由于字符数超过15个字符,系统按ID号给任务分配名称为"ID:xxx")
Task_Create(SecondTask,60,2,"Second Task"); //SecondTask任务建立,重装载时间60ms,优先级2,名称"Second Task"
}
上面的例子里,在系统上电时通过SysConfig_Ini函数配置向系统提交了10个常用任务,系统为每个任务分配了一个独立的时钟管理,通过时钟及任务优先级驱动各任务的运行。经过电脑仿真,效果如图7,说明该系统调度任务的效果能够达到预期要求,可以用于工业产品安全功能设计。
图7
参考文献:
[1]Halbleiterspeicher-Testfolgen.Th.John,E.Schaefer,Elektronipraxis,H.6,18-26 and H.7,10-14,1980.
[2]Signaturanalyse in der Datenverarbeitung.D.Leisengang,M,Wagner,Elektronik 32,H.21,S.67-72,1983.
[3]安全技术中的微机——面向开发者和生产者的一种工具.H.Holscher,J.Rader,Verlag TUV Rheinland,Koln,1986,ISBN 3-88585-315-9.
[4]计算机现在已能安全地执行关键的安全功能.Otto Berg von Linde,Railway Gazette international,Vol.135,No.11,1979.
[5]嵌入式实时操作系统uC/OS-II原理及应用.北京航空航天大学出版社.
作者简介:石磊(1981.5-),男,重庆人,中级,硕士,研究方向:自动化仪器仪表开发及软件工程应用。