单片机关键任务优先级的实现学习

news2024/11/16 20:57:23

与总体产品联调时,需要各个单机系统严格按照总体要求,进行数据输出,时间的偏差将出现系统异常,控制失败等不稳定情况产生,甚至影响到产品安全。

因此必须确保某些关键任务的优先执行。单片机任务优先级一般有两种方式实现,基于单片机中断服务的中断函数进行实现基于实时操作系统的任务调度实现

基于中断服务函数实现的任务优先级对单片机硬件资源有要求,而对于实时操作系统的任务调度方式,仅需一个定时器就可完成多任务多优先级的管理。

参与某产品联调时,总体要求每间隔5ms向总控发
送一次关键数据。

当系统联调运行时,总控会产生超时报警,报警内容是通信超时。

经过排查排除了硬件问题、电磁干扰问题、程序逻辑错误未正常发送数据等问题。

通过报警时间比对,发现该报警出现时间没有规律性。通过示波器查看发现,其发送数据周期没有严格按照5ms 间隔时间发送,发送时间落在 5ms 区间段内,任意时间点都可能会进行关键数据的传递,无法预测下次一次发送数据的准确时间,当系统在规定时间内未接收到数据时,产生系统报警。

经过对程序进行逻辑分析,出现问题原因是单片机运
行任务是顺序执行,只有轮到发送数据任务执行时,才能发送数据,如果其他任务占用执行时间过长,将会导致发送任务不能在5ms时间内再次获得运行机会,因此也无法按时发送数据,造成数据超时问题。

在这里插入图片描述

1 关键任务优先执行方法
1.1 查找问题

下位机程序任务流程如图1所示:

下位机程序按照项目功能需求,将不同功能划分为不
同任务,根据每个任务特点,制定的间隔时间不一致,

如 对RS485等通信口监听时,其响应时间在50ms满足要求,自然环境下温度变化缓慢,因此温度采集500ms一次也满足要求。通过计时器进行技术,当5ms时置位5ms任务标志位,10ms时置位5ms和10ms任务标志位,通过任务标志位定义了任务执行频率,优先级高的任务得到更多执行次数。该种任务执行方式称为任务协同方式,当一个任务执行时,必须等到该任务执行完成,才能执行下一个任务。当某一时刻,多个时间任务被置位时,其按照顺序结构运行程序,任务需要排队执行,实时性不高。

下位机程序使用任务协同方式进行运行,分别定义了
5ms,10ms,20ms,50ms,100ms,200ms,500ms 等任务。

所有的任务基于顺序执行,其中5ms程序critical_task
作为关键任务。某个时刻,如定时器在计数到500ms时,其上的5ms,10ms,20ms,50ms,100ms,200ms 时间标志位被置位,任务均得到执行,导致500ms这一时刻需要顺序执行很多任务,如在5ms内不能执行完全部任务,那么下一次的关键任务程序 critical_task 将不能按时被执行,导致输出超时情况产生。 为解决超时问题,必须提升critical_task 任务的优先级,提升任务优先级的方式较多,常用的方式有中断服务函数(前后台系统)、实时操作系统实现。

1.2 关键任务任务由前后台系统保证

单片机是单核处理器,不能同时执行多个任务。

从主程序架构上看,该种顺序执行方式不能保证关键
任务critical_task 的优先执行。因此应该使用某种方式
能够中断当前正在顺序执行的任务,转向执行优先级较高的任务。

单片机中断是指正在执行一项任务A,然后突然停止
任务A去执行任务B,执行完任务B再回来继续执行任务
A 的过程。单片机中断有很多触发源,如定时器中断、外部按键中断、通信发送、接收数据中断,每个中断源都可以打断正在执行的任务,转向执行中断任务,中断任务执行完毕后,继续回到当前的任务进行未完成的操作,利用单片机的中断特性,能够保证某些代码的及时执行。将某些关键任务放入中断服务函数中,就能打断顺序执行任务而优先执行中断任务,使用该种方式提升了关键任务的优先级。
在这里插入图片描述

单片机中断源的产生有很多方式,与产品联调问题是
不能在5ms时准确的进行数据传输,因此需要在5ms时产生一次任务中断,以执行发送任务。为了满足上述要求,选择定时器中断可满足要求。

定时器中断是指单片机内部有一个从0开始向上(向
下)计数的计数器,每一次计数时间均相同,设置一个计
数目标值,当计数器计数到目标值时,会产生一个计数中断,中断后单片机可以打断当前正在执行的程序跳转执行中断服务程序。在中断服务程序中,清除中断服务向量,使得计数器归0重新计数,以此不断循环达到每隔一定时间就产生一次服务中断的工作模式。

在这里插入图片描述

我们将原程序中的critical_task任务从5ms任务重
移除,添加到 Count5ms_OnInterrupt 中断服务程序中,通过前后台方式实现打断其他正在执行任务来保证
critical_task 的优先执行。程序更改后critical_task
能够5ms一次准确输出,系统报警现象被消除。采用此种方法虽然简单,但是突出问题有几个:
(1)使用中断方式来保证优先级需要占用一个中断
来完成,浪费资源。
(2)当有多个关键任务需要执行时,会出现中断嵌
套,关键任务仍然会被打断执行。
(3)违背了中断中只执行不耗时简单操作的原则,
仍然存在隐患。
(4)不能对不同任务进行不同权重的CPU使用权划
分。


C51 单片机任务协同的实现可以通过定时器中断和任务标志位来完成。在 C51 中,定时器的配置和中断处理稍有不同于现代的 ARM Cortex 系列单片机,但基本原理是相似的。下面是一个简单的示例程序,演示如何使用 C51 编写一个任务协同的程序,涉及10ms、30ms、50ms、100ms 的任务执行:

#include <REG51.H>

// 定义任务标志位
bit task_10ms_flag = 0;
bit task_30ms_flag = 0;
bit task_50ms_flag = 0;
bit task_100ms_flag = 0;

// 定义定时器0的初值
#define TIMER0_INIT_VALUE 65536 - (12000 / 12)  // 12MHz晶振,计时1ms

// 定时器0中断处理函数
void Timer0_ISR(void) interrupt 1
{
    static unsigned char count_10ms = 0;
    static unsigned char count_30ms = 0;
    static unsigned char count_50ms = 0;
    static unsigned char count_100ms = 0;

    // 10ms任务
    count_10ms++;
    if (count_10ms >= 10)
    {
        count_10ms = 0;
        task_10ms_flag = 1;
    }

    // 30ms任务
    count_30ms++;
    if (count_30ms >= 30)
    {
        count_30ms = 0;
        task_30ms_flag = 1;
    }

    // 50ms任务
    count_50ms++;
    if (count_50ms >= 50)
    {
        count_50ms = 0;
        task_50ms_flag = 1;
    }

    // 100ms任务
    count_100ms++;
    if (count_100ms >= 100)
    {
        count_100ms = 0;
        task_100ms_flag = 1;
    }
}

void main(void)
{
    // 初始化定时器0
    TMOD = 0x01;  // 定时器0工作在模式1
    TH0 = TIMER0_INIT_VALUE >> 8;  // 预设初值
    TL0 = TIMER0_INIT_VALUE & 0xFF;
    TR0 = 1;  // 启动定时器0
    ET0 = 1;  // 允许定时器0中断
    EA = 1;   // 允许总中断

    while (1)
    {
        // 执行10ms任务
        if (task_10ms_flag)
        {
            task_10ms_flag = 0;
            // 在此处执行10ms的任务
        }

        // 执行30ms任务
        if (task_30ms_flag)
        {
            task_30ms_flag = 0;
            // 在此处执行30ms的任务
        }

        // 执行50ms任务
        if (task_50ms_flag)
        {
            task_50ms_flag = 0;
            // 在此处执行50ms的任务
        }

        // 执行100ms任务
        if (task_100ms_flag)
        {
            task_100ms_flag = 0;
            // 在此处执行100ms的任务
        }
    }
}

程序说明:

  • 定时器设置:使用定时器0(TMOD = 0x01),工作在模式1下,计时器1ms。通过中断每1ms计时,并根据计数器判断是否到达设定的任务执行时间。

  • 任务标志位:使用四个标志位 task_10ms_flagtask_30ms_flagtask_50ms_flagtask_100ms_flag 来表示对应的任务是否需要执行。

  • 任务执行:在主循环中,根据任务标志位的状态执行对应的任务,每次任务完成后将对应的标志位清零。

注意事项:

  • 定时器配置:根据具体的晶振频率和需求调整 TIMER0_INIT_VALUE 的值,确保定时器产生1ms的中断。

  • 任务执行顺序:任务按照设定的时间间隔执行,且串行执行,适合简单控制任务。

  • 实时性:由于是基于定时器中断,任务的实时性取决于定时器的精确性和系统负载。

这个简单的示例展示了如何在 C51 单片机上实现基于定时器和任务标志位的任务协同方式,适用于对实时性要求不是非常高的简单控制和数据采集应用。


在上述的程序中,的确存在一种可能性,即30ms和50ms的任务同时在处理的情况。这是因为任务标志位 task_30ms_flagtask_50ms_flag 可能会在同一个定时器中断周期内同时被置位,从而导致它们在主循环中几乎同时被检测到并执行对应的任务代码段。

要解决这个问题,可以考虑以下几点改进:

  1. 任务优先级管理:在任务标志位设置时,考虑将更高优先级的任务标志位先置位,确保高优先级任务优先执行。例如,在定时器中断处理函数中,先处理100ms任务标志位,然后是50ms、30ms、最后是10ms任务标志位。

  2. 任务执行顺序控制:在主循环中,确保每次只处理一个任务标志位,并且每个任务完成后清除对应的标志位。这样可以避免同时处理多个任务的情况。

  3. 优化任务时间间隔:考虑调整任务的时间间隔,使得不同任务的触发时间点尽可能错开,减少同时触发的可能性。

下面是改进后的代码示例,演示如何根据任务的优先级顺序处理任务标志位:

#include <REG51.H>

// 定义任务标志位
bit task_10ms_flag = 0;
bit task_30ms_flag = 0;
bit task_50ms_flag = 0;
bit task_100ms_flag = 0;

// 定义定时器0的初值
#define TIMER0_INIT_VALUE 65536 - (12000 / 12)  // 12MHz晶振,计时1ms

// 定时器0中断处理函数
void Timer0_ISR(void) interrupt 1
{
    static unsigned char count_10ms = 0;
    static unsigned char count_30ms = 0;
    static unsigned char count_50ms = 0;
    static unsigned char count_100ms = 0;

    // 100ms任务
    count_100ms++;
    if (count_100ms >= 100)
    {
        count_100ms = 0;
        task_100ms_flag = 1;
    }

    // 50ms任务
    if (count_100ms % 50 == 0)
    {
        task_50ms_flag = 1;
    }

    // 30ms任务
    if (count_100ms % 30 == 0)
    {
        task_30ms_flag = 1;
    }

    // 10ms任务
    count_10ms++;
    if (count_10ms >= 10)
    {
        count_10ms = 0;
        task_10ms_flag = 1;
    }
}

void main(void)
{
    // 初始化定时器0
    TMOD = 0x01;  // 定时器0工作在模式1
    TH0 = TIMER0_INIT_VALUE >> 8;  // 预设初值
    TL0 = TIMER0_INIT_VALUE & 0xFF;
    TR0 = 1;  // 启动定时器0
    ET0 = 1;  // 允许定时器0中断
    EA = 1;   // 允许总中断

    while (1)
    {
        // 执行100ms任务
        if (task_100ms_flag)
        {
            task_100ms_flag = 0;
            // 在此处执行100ms的任务
        }

        // 执行50ms任务
        if (task_50ms_flag)
        {
            task_50ms_flag = 0;
            // 在此处执行50ms的任务
        }

        // 执行30ms任务
        if (task_30ms_flag)
        {
            task_30ms_flag = 0;
            // 在此处执行30ms的任务
        }

        // 执行10ms任务
        if (task_10ms_flag)
        {
            task_10ms_flag = 0;
            // 在此处执行10ms的任务
        }
    }
}

改进说明:

  • 优先级处理:在定时器中断处理函数中,先处理更高优先级的任务标志位(例如100ms任务),然后逐级处理较低优先级的任务标志位。这样可以确保在同一个定时器中断周期内只有一个任务标志位被置位。

  • 顺序执行:在主循环中,每次只检测并执行一个任务标志位的任务,确保任务的顺序执行,并在每个任务完成后清除对应的标志位。

通过这样的改进,可以有效避免30ms和50ms任务同时在处理的情况,保证任务执行的可控性和稳定性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1892201.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

My sql 安装,环境搭建

以下以MySQL 8.0.36为例。 一、下载软件 1.下载地址官网&#xff1a;https://www.mysql.com 2. 打开官网&#xff0c;点击DOWNLOADS 然后&#xff0c;点击 MySQL Community(GPL) Downloads 3. 点击 MySQL Installer for Windows 4.点击Archives选择合适版本 5.选择后下载…

【国产开源可视化引擎Meta2d.js】锚点

国产开源 乐吾乐潜心研发&#xff0c;自主可控&#xff0c;持续迭代优化 Github&#xff1a;GitHub - le5le-com/meta2d.js: The meta2d.js is real-time data exchange and interactive web 2D engine. Developers are able to build Web SCADA, IoT, Digital twins and so …

神经网络入门:从零到训练

想要认识神经网络&#xff0c;个人认为还是需要先从回归开始理解 线性回归 回归&#xff08;regression&#xff09;是能为一个或多个自变量与因变量之间关系建模的一类方法。 在自然科学和社会科学领域&#xff0c;回归经常用来表示输入和输出之间的关系。 在机器学习领域中…

【Python机器学习】算法链与管道——构建管道

目录 1、首先&#xff0c;我们构建一个由步骤列表组成的管道对象。 2、向任何其他scikit-learn估计器一样来拟合这个管道 3、调用pipe.score 我们来看下如何使用Pipeline类来表示在使用MinMaxScaler缩放数据后&#xff0c;再训练一个SVM的工作流程&#xff08;暂时不用网格搜…

你知道是怎么运作的吗?神经网络内部原理解析

你知道神经网络是怎么运作的吗&#xff1f;神经网络内部原理解析 “神经网络就是一个具有输入和输出的黑盒” 神经网络模型就是模仿人类大脑神经元传递的过程&#xff0c;从使用者的角度来说&#xff0c;神经网络就是一个具有输入和输出的黑盒模型。 简化模型如下图&#xf…

python 比webdriver更好用的ChromiumPage

优点&#xff08;目前发现的&#xff09;&#xff1a; 不用配合selenium不用下载对应浏览器的webdriver&#xff0c;不用对应浏览器版本不用设置webdriver路径之类的设置目前没看到有出现像webdriver类似的浏览器被控制的提示&#xff0c;使用过程中好像也没被检测出来。每次不…

JAVA实现二分查找,斐波那契数列,深度优先搜索详情教程【包含代码】

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

《企业实战分享 · 内存溢出分析》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; 近期刚转战 CSDN&#xff0c;会严格把控文章质量&#xff0c;绝不滥竽充数&#xff0c;如需交流&#xff…

计算机系统中---信息就是位+上下文

hello.c #include <stdio.h>int main(){printf("hello,world\n");return 0; }hello程序的生命周期是从一个源程序(或者说源文件)开始的&#xff0c;即程序员通过编辑器创建并保存的文本文件&#xff0c;文件名是he11o.c。源程序实际上就是一个由值0和1组成的位…

推荐三款常用接口测试工具!

接口测试是软件开发中至关重要的一环&#xff0c;通过对应用程序接口进行测试&#xff0c;可以验证其功能、性能和稳定性。随着互联网和移动应用的快速发展&#xff0c;接口测试变得越来越重要。为了提高测试效率和质量&#xff0c;开发人员和测试人员需要使用专业的接口测试工…

复分析——第8章——共形映射(E.M. Stein R. Shakarchi)

第8章 共形映射(Conformal Mappings) The results I found for polygons can be extended under very general assumptions. I have undertaken this research because it is a step towards a deeper understanding of the mapping problem, for which not much has hap…

开放式耳机哪个牌子好?2024热门硬核机型推荐,不做冤大头

很多小伙伴私信我&#xff0c;想要挑选一款开放式耳机真的好难啊&#xff0c;现在开放式耳机市场的产品越来越多&#xff0c;知名的品牌和一些新兴的网红品牌哪一个最好&#xff1f;所以这篇文章&#xff0c;作为开放式耳机测评师&#xff0c;教大家如何挑选一款开放式耳机&…

工作助手VB开发笔记(1)

1.思路 1.1 样式 样式为常驻前台的一个小窗口&#xff0c;小窗口上有三到四个按钮&#xff0c;为一级功能&#xff0c;是当前工作内容的常用功能窗口&#xff0c;有十个二级窗口&#xff0c;为选中窗口时的扩展选项&#xff0c;有若干后台功能&#xff0c;可选中至前台 可最…

学生护眼台灯哪个牌子最好?几款口碑好、值得推荐的学生护眼台灯

家长们对孩子的用眼健康很重视&#xff0c;为什么&#xff1f;现在是科技电子时代&#xff0c;人们对电子屏幕的依赖性高&#xff0c;小孩子年纪小&#xff0c;眼部还处于正在发育的阶段&#xff0c;他们在学校中长时间的学习读写&#xff0c;用眼时间长。而且随着科技渗入教学…

36V高性能单双通道多路复用器开关控制器

产品简介 PC221 和 PC222 分别为单 8:1 和双通道 4:1 模拟多路复用器。由于特殊的设计优化&#xff0c;无论是上电状态还是掉电状态&#xff0c; PC221 和 PC222 都可以提供源端过压保护。正常供电状态下&#xff0c;多路复用器源端可以耐受持续的电压高达-50 V 至50 V。当掉电…

JS滚动时显示元素

本篇文章我们将实现文章平滑滑入 ● 其实这原本是用CSS实现的 .section {padding: 15rem 3rem;border-top: 1px solid #ddd;transition: transform 1s, opacity 1s; }.section--hidden {opacity: 0;transform: translateY(8rem); }● 我们的目的呢&#xff0c;就是当滚入到某一…

提升用户购物体验:多语言跨境电商系统源码优化技巧详解

随着全球化的发展&#xff0c;跨境电商已成为一种趋势。而在跨境电商中&#xff0c;多语言的支持是提升用户购物体验的重要一环。为此&#xff0c;本文将详细介绍多语言跨境电商系统源码的优化技巧。 一、多语言支持的重要性 在全球市场中&#xff0c;用户来自不同的国家和地…

日本服务器托管需要注意哪些问题

日本服务器托管是一项涉及多方面因素的重要决策&#xff0c;为了确保托管服务的稳定、高效与安全&#xff0c;企业或个人在托管过程中需要注意以下几个关键问题&#xff1a; 首先&#xff0c;数据中心的基础设施建设标准是决定托管稳定性的关键。这包括数据中心的建筑抗震、抗洪…

你的B端系统考虑移动化了?还没?那就小心out了。

B端系统移动化的趋势是不可阻挡的。随着移动设备的普及和移动互联网的发展&#xff0c;越来越多的企业和组织意识到移动化对于提高工作效率、拓展市场和提供更好的用户体验的重要性。以下是一些导致B端系统移动化趋势不可阻挡的原因&#xff1a; 移动办公需求&#xff1a;越来越…

Excel 宏录制与VBA编程 ——VBA编程技巧篇二 (合并内容相同连续单元格、取消合并单元格并在每个单元格中保留内容)

1、合并内容相同的连续单元格 如果需要合并如图所示的工作表中B列中部门相同的连续单元格 VBA代码&#xff1a; Sub Mergerng()Dim IntRow As IntegerDim i As IntegerApplication.DisplayAlerts FalseWith Sheet1IntRow .Range("A65536").End(xlUp).RowFor i In…