[PIC®/AVR®/dsPIC®产品]

【CuriosityNano测评报告】+PIC18F16Q41 轻量级定时器调度

[复制链接]
6449|15
手机看帖
扫描二维码
随时随地手机跟帖
qjp1988113|  楼主 | 2021-8-31 10:18 | 显示全部楼层 |阅读模式
本帖最后由 pzsh 于 2021-8-31 13:41 编辑

最近在网上看到个TMT,简单的定时器调度系统~这不,我来看一下~
其实PIC18F16Q41的FLASH空间不小了,按道理移植RTOS都绰绰有余。
但是本质上都是定时器的调度~
不废话,先上MCC配置:
CLOCK(64M):
A1.png
USART1(9600,N,8,1):
A2.png
TIMER0(设置成1ms中断):
A3.png
PIN(UART,LED,KEY):
A4.png
编译生成代码:
加载TMT文件:
tmt.h(其中,进临界和出临界改成自己MCU对于的函数)
/* 
* File:   tmt.h
* Author: Administrator
*
* Created on August 31, 2021, 9:45 AM
*/

#ifndef TMT_H
#define        TMT_H

#ifdef        __cplusplus
extern "C" {
#endif

/**
* [url=home.php?mod=space&uid=247401]@brief[/url]     硬件平台相关的头文件,提供硬件运行的基本环境,一般是寄存器头文件。
* [url=home.php?mod=space&uid=1543424]@Details[/url]   The header files related to the hardware platform provide
*            the basic environment for hardware operation, generally
*            register header files..
**/
#include  "../mcc_generated_files/mcc.h"


/**
* [url=home.php?mod=space&uid=247401]@brief[/url]     进入TMT临界区宏函数,需要关闭相关定时器的中断。
* [url=home.php?mod=space&uid=1543424]@Details[/url]   Enter the TMT critical section macro function.
*            It is necessary to turn off the interrupt of the related timer.
* [url=home.php?mod=space&uid=536309]@NOTE[/url]      需要根据硬件平台,移植合适的关定时器中断代码。
*            It is necessary to transplant the appropriate off-timer
*            interrupt code according to the hardware platform.
**/
//#define       ENTER_TMT_CRI_AREA()    do{ __HAL_TIM_DISABLE_IT(&htim1,TIM_IT_UPDATE); }while(0)  //32版本
#define       ENTER_TMT_CRI_AREA()    do{ TMR0_StopTimer(); }while(0) //51版本

/**
* @brief     退出TMT临界区宏函数,需要打开相关定时器的中断。
* @details   Enter the TMT critical section macro function.
*            It is necessary to turn on the interrupt of the related timer.
* [url=home.php?mod=space&uid=536309]@NOTE[/url]      需要根据硬件平台,移植合适的开定时器中断代码。
*            It is necessary to transplant the appropriate on-timer
*            interrupt code according to the hardware platform.
**/
//#define       EXTI_TMT_CRI_AREA()     do{ __HAL_TIM_ENABLE_IT(&htim1,TIM_IT_UPDATE); }while(0) //32版本
#define       EXTI_TMT_CRI_AREA()     do{ TMR0_StartTimer(); }while(0) //51版本


/**
* @brief     TMT的变量类型重定义,如果有冲突,请配置为0。
* @details   The variable type of TMT is redefined.
*            If there is a conflict, please configure it to 0..
**/
#if                   (0)

        typedef  unsigned char   uint8_t; /*!<  8 bits */
        typedef  unsigned int   uint16_t; /*!< 16 bits */

#endif

/*-----------------------------------------------------------------------
|                                CONFIG                                 |
-----------------------------------------------------------------------*/

/**
* @brief     任务数量控制宏,用来确定TMT需要调度的最大任务数量。
* @details   The number of tasks control macro is used to
*            determine the maximum number of tasks that TMT
*            needs to schedule.
**/
#define           TMT_TASK_NUM           (8)


/*-----------------------------------------------------------------------
|                                 DATA                                  |
-----------------------------------------------------------------------*/


/**
* @brief     任务的执行状态枚举体。
* @details   The execution status enumerator of the task.
**/
typedef enum
{
    Task_Stop = 1,   /*!< 停止运行状态。*/
        Task_Continue = !Task_Stop /*!< 继续运行状态。*/
}TaskState_Type;


/**
  * @brief   TMT函数自检枚举体,指示函数是否正常执行。
  *          TMT function self checks enumerator.
  *          indicating whether the function is normally executed.
***/
typedef enum
{
        TMT_NOK= 1,     /* Function self checking failed */
        TMT_OK = !TMT_NOK /* Function self checking successfed */
}TMT_FunState_Type;


/*-----------------------------------------------------------------------
|                             API FUNCTION                              |
-----------------------------------------------------------------------*/

/**
* @brief   TMT初始化函数,注册相关元素。
* @details The TMT initializes the function
*          and registers the associated elements.
* @param   None.
* [url=home.php?mod=space&uid=266161]@return[/url]  None.
**/
void TMT_Init(void);


/**
* @brief   TMT的API操作函数结构体。
* @details The TMT API manipulates the function structure.
**/
typedef struct
{
        /**
         * @brief     TMT更新任务调度tick时间。
         * @details   TMT update task schedule tick time.
         * @param[in] None.
         * [url=home.php?mod=space&uid=266161]@return[/url]    None.
         * @note      在定时器中断服务函数中调用。
         *            Called in the timer interrupt service function.
         * [url=home.php?mod=space&uid=389923]@example[/url]   TMT.Tick();
        **/
        void (*Tick) (void);
        
        
        /**
         * @brief     TMT运行函数,是任务调度器。
         * @details   TMT runs the function, which is the task scheduler.
         * @param[in] None.
         * @return    None.
         * @note      在main函数的无限循环中调用。
         *            Called in the infinite loop of main.
         * [url=home.php?mod=space&uid=389923]@example[/url]   TMT.Run();
        **/
        void (*Run) (void);
        
        
        /**
         * @brief     TMT创建一个任务函数。
         * @details   TMT creates a task function.
         * @param[in] entry 任务函数入口指针.
         *            A pointer function without formal parameters.
         * @param[in] setTime 任务调度的时间 task run time (ticks)
         * @return    [TMT_OK]创建成功.Create successfully.
         * @return    [TMT_NOK]创建失败.        Create failed.
         * @note      在main函数的无限循环中调用。
         *            Called in the infinite loop of main.
         * @example   TMT.Create(enrty,500); //定时entry任务为500ticks调度一次
        **/        
        TMT_FunState_Type (*Create) (void (*entry) (void), uint16_t setTime);
        
        
        /**
         * @brief     TMT删除一个任务函数。
         * @details   TMT creates a task function.
         * @param[in] entry 任务函数入口指针.
         *            A pointer function without formal parameters.
         * @return    [TMT_OK]删除成功.Delete successfully.
         * @return    [TMT_NOK]删除失败.        Delete failed.
         * @example   TMT.Delete(enrty); //删除entry任务
        **/               
        TMT_FunState_Type (*Delete) (void (*entry) (void));
        
        
        /**
         * @brief     TMT控制一个任务的调度时间函数。
         * @details   The TMT controls the scheduling time function of a task.
         * @param[in] entry 任务函数入口指针.
         *            A pointer function without formal parameters.
         * @param[in] setTime 任务调度的时间 task run time (ticks)
         * @return    [TMT_OK]修改成功.The modification was successful.
         * @return    [TMT_NOK]修改失败.The modification was failed.
         * @example   TMT.TimeCtrl(enrty,100); //修改entry任务为100ticks调度一次
        **/        
        TMT_FunState_Type (*TimeCtrl) (void (*entry) (void), uint16_t setTime);
        
        
        /**
         * @brief     TMT控制一个任务运行状态函数。
         * @details   TMT controls a task running state function.
         * @param[in] entry 任务函数入口指针.
         *            A pointer function without formal parameters.
         * @param[in] state 任务运行状态.Task running status
         * @return    [TMT_OK]修改成功.The modification was successful.
         * @return    [TMT_NOK]修改失败.The modification was failed.
         * @example   TMT.RunCtrl(enrty,Task_Stop); //修改entry任务为停止运行.
        **/               
        TMT_FunState_Type (*RunCtrl) (void (*entry) (void), TaskState_Type state);
}TMT_Type;


/**
* @brief   对外声明的TMT操作函数结构体。
* @details TMT operation function structure declared externally.
* @note    所有需要被外部调用的函数,都包含在这个结构体中.
*          All functions that need to be called externally
*          are included in this structure.
**/
extern TMT_Type TMT;


#ifdef        __cplusplus
}
#endif

#endif        /* TMT_H */

TMT.C
/*-----------------------------------------------------------------------
|                            FILE DESCRIPTION                           |
-----------------------------------------------------------------------*/
/*----------------------------------------------------------------------
  - File name     : TMT.c
  - Author        : zeweni
  - Update date   : 2020.06.26                  
  -        Copyright(c)  : 2020-2021 zeweni. All rights reserved.
-----------------------------------------------------------------------*/
/*------------------------------------------------------------------------
|                            COPYRIGHT NOTICE                            |
------------------------------------------------------------------------*/
/*
* Copyright (C) 2021, zeweni (17870070675@163.com)

* This file is part of task management time slice framework.
* Abbreviated as TMT.

* Task management time slice framework is free software: you can redist-
* ribute it and/or modify it under the terms of the Apache-2.0 License.

* Task management time slice framework is distributed in the hope that it
* will be useful,but WITHOUT ANY WARRANTY; without even the implied  
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Apache-2.0 License for more details.

* You should have received a copy of the Apache-2.0 License.Task management
* time slice framework. If not, see <http://www.apache.org/licenses/>.
**/
/*-----------------------------------------------------------------------
|                               INCLUDES                                |
-----------------------------------------------------------------------*/
#include "TMT.h"
/*-----------------------------------------------------------------------
|                                 DATA                                  |
-----------------------------------------------------------------------*/

/**
* @brief     最大任务数量宏,再封装一层。
* @details   The maximum number of tasks is a macro,
*            and then one layer is encapsulated.
**/
#define  TASKS_MAX       TMT_TASK_NUM


/**
* @brief   定义TMT相关操作函数结构体。
* @details Define the structure of the TMT related operation functions.
**/
TMT_Type TMT;


/**
* @brief   TMT的类,包含公共和私有两个属性。
* @details Class of TMT, containing both public and private properties.
**/
static struct Class
{
        TMT_Type Public;  /*!< 公共部分,对外开放的属性,具体定义在头文件。*/
        
        struct Private   /*!< 私有部分,仅限本文件内调用。*/
        {
                struct
                {
                        void (* Entry) (void); /*!< 任务函数入口指针。*/
                        uint16_t TIMCount;     /*!< 任务调度时间计数器。*/
                        uint16_t SetTime;      /*!< 任务设置的调度时间。*/
                        uint8_t State;         /*!< 任务运行状态。*/
                }Comp[TASKS_MAX];
               
                uint8_t Num;   /*!< 已经创建的任务数量。*/
        }Private;
        
}Object;

/*-----------------------------------------------------------------------
|                               FUNCTION                                |
-----------------------------------------------------------------------*/

/**
* @brief     TMT更新任务调度tick时间。
* @details   TMT update task schedule tick time.
* @param[in] None.
* @return    None.
**/
static void TMT_Update_Tick_t(void)
{
        uint8_t i;
        for(i = 0; i< Object.Private.Num; i++)
    {
                 /* If time arrives */
        if(Object.Private.Comp[i].TIMCount > 0 )
        {
            Object.Private.Comp[i].TIMCount--;
        }
        }        
}

/**
* @brief     TMT运行函数,是任务调度器。
* @details   TMT runs the function, which is the task scheduler.
* @param[in] None.
* @return    None.
**/
static void TMT_Run_t(void)
{
        uint8_t index;
        for(index = 0; index < Object.Private.Num; index++)
        {
                 /* If time arrives */
                if(Object.Private.Comp[index].TIMCount == 0 && Object.Private.Comp[index].State != Task_Stop)
                {
                        Object.Private.Comp[index].TIMCount = Object.Private.Comp[index].SetTime;
                        
                        /*
                                To prevent process conflict,
                                only one process can be executed in the same time period.
                        */
                        if(Object.Private.Comp[index].Entry != (void*)(0) )
                        {
                                Object.Private.Comp[index].Entry();  /* Run task */
                        }
                }
        }
}


/**
* @brief     TMT创建一个任务函数。
* @details   TMT creates a task function.
* @param[in] entry 任务函数入口指针.
*            A pointer function without formal parameters.
* @param[in] setTime 任务调度的时间 task run time (ticks)
* @return    [TMT_OK]创建成功.Create successfully.
* @return    [TMT_NOK]创建失败.        Create failed.
**/        
static TMT_FunState_Type TMT_Create_t(void (*entry) (void),uint16_t setTime)
{        
    static uint8_t task_num = 0; /* Initialize to 0 */
        if(task_num < TASKS_MAX)
        {
                Object.Private.Comp[task_num].Entry = entry;
                Object.Private.Comp[task_num].SetTime = setTime;
                Object.Private.Comp[task_num].TIMCount = setTime;
                Object.Private.Comp[task_num].State = Task_Continue;
                task_num += 1;
                Object.Private.Num = task_num;
                return TMT_OK;
        }
        else
        {
                return TMT_NOK;        
        }               
}


/**
* @brief     TMT删除一个任务函数。
* @details   TMT creates a task function.
* @param[in] entry 任务函数入口指针.
*            A pointer function without formal parameters.
* @return    [TMT_OK]删除成功.Delete successfully.
* @return    [TMT_NOK]删除失败.        Delete failed.
**/        
static TMT_FunState_Type TMT_Delete_t(void (*entry) (void))
{        
    uint8_t index;
    if(Object.Private.Num > 0)
    {
        ENTER_TMT_CRI_AREA();
               
        for(index = 0; index < Object.Private.Num; index++)
        {
            if(Object.Private.Comp[index].Entry == entry)
            {
                    Object.Private.Num--;
                    Object.Private.Comp[index].Entry = Object.Private.Comp[Object.Private.Num].Entry;
                    Object.Private.Comp[index].SetTime = Object.Private.Comp[Object.Private.Num].SetTime;
                    Object.Private.Comp[index].TIMCount = Object.Private.Comp[Object.Private.Num].TIMCount;
                    Object.Private.Comp[index].State = Object.Private.Comp[Object.Private.Num].State;
                    EXTI_TMT_CRI_AREA();
                    return TMT_OK;
            }
        }
    }
    EXTI_TMT_CRI_AREA();
    return TMT_NOK;
}


/**
* @brief     TMT控制一个任务运行状态函数。
* @details   TMT controls a task running state function.
* @param[in] entry 任务函数入口指针.
*            A pointer function without formal parameters.
* @param[in] state 任务运行状态.Task running status
* @return    [TMT_OK]修改成功.The modification was successful.
* @return    [TMT_NOK]修改失败.The modification was failed.
**/        
static TMT_FunState_Type TMT_RunCtrl_t(void (*entry)(void),TaskState_Type state)
{
        uint8_t index;
        for(index = 0; index<Object.Private.Num; index++)
        {
                if(Object.Private.Comp[index].Entry == entry)
                {
                    Object.Private.Comp[index].State = state;
                        return TMT_OK;
                }
        }
        return TMT_NOK;
}


/**
* @brief     TMT控制一个任务的调度时间函数。
* @details   The TMT controls the scheduling time function of a task.
* @param[in] *taskFunc (void) 任务函数入口指针.
*            A pointer function without formal parameters.
* @param[in] setTime 任务调度的时间 task run time (ticks)
* @return    [TMT_OK]修改成功.The modification was successful.
* @return    [TMT_NOK]修改失败.The modification was failed.
**/        
static TMT_FunState_Type TMT_TimeCtrl_t(void (*entry) (void),uint16_t setTime)
{        
        uint8_t index;
        for(index = 0; index< Object.Private.Num; index++)
        {
                if(Object.Private.Comp[index].Entry == entry)
                {
                        Object.Private.Comp[index].TIMCount = setTime;
                        Object.Private.Comp[index].SetTime = setTime;
                        return TMT_OK;
                }
        }
        return TMT_NOK;
}


/**
* @brief   TMT初始化函数,注册相关元素。
* @details The TMT initializes the function
*          and registers the associated elements.
* @param   None.
* @return  None.
**/
void TMT_Init(void)
{
        Object.Public.Run = TMT_Run_t;
        Object.Public.Tick = TMT_Update_Tick_t;
        Object.Public.Create = TMT_Create_t;
        Object.Public.Delete = TMT_Delete_t;
        Object.Public.TimeCtrl = TMT_TimeCtrl_t;
        Object.Public.RunCtrl = TMT_RunCtrl_t;
        Object.Private.Num = 0;
        
        TMT = Object.Public;
}

/*-----------------------------------------------------------------------
|                   END OF FLIE.  (C) COPYRIGHT zeweni                  |
-----------------------------------------------------------------------*/



在timer0中断函数里面添加TMT核心任务处理函数:
#include "../TMT/tmt.h"
volatile uint32_t mscnt=0;

void TMR0_CallBack(void)
{
    // Add your custom callback code here
    mscnt++;
    if(mscnt>=500)
    {
        //LED0_Toggle();
        mscnt=0;
    }
   
    TMT.Tick();
   
    if(TMR0_InterruptHandler)
    {
        TMR0_InterruptHandler();
    }
}
在main函数里面新建2个任务,并运行(主要开总中断):

#include "mcc_generated_files/mcc.h"
#include "tmt/tmt.h"



void TMT_Demo0(void)
{
        LED0_Toggle();
}

uint8_t j=0;
void TMT_Demo1(void)
{
        printf("the j is %d!\r\n",j++);
}

/*
                         Main application
*/
void main(void)
{
    uint8_t i=0;
    // Initialize the device
    SYSTEM_Initialize();

    // If using interrupts in PIC18 High/Low Priority Mode you need to enable the Global High and Low Interrupts
    // If using interrupts in PIC Mid-Range Compatibility Mode you need to enable the Global Interrupts
    // Use the following macros to:

    TMT_Init();
        
        TMT.Create(TMT_Demo0,500);
        TMT.Create(TMT_Demo1,500);
   
    // Enable the Global Interrupts
    INTERRUPT_GlobalInterruptEnable();

    // Disable the Global Interrupts
    //INTERRUPT_GlobalInterruptDisable();

    while (1)
    {
        // Add your application code
        //printf("the i is %d!\r\n",i++);
        // __delay_ms(300);
        TMT.Run();
    }
}
下载,运行:
看串口输出端:
B1.png
看板上LED:
K1.gif
虽然简单,但是很好的诠释了系统调度的流程,好了,今天就到这!
谢谢观看~

使用特权

评论回复
pzsh| | 2021-8-31 13:41 | 显示全部楼层
看flash和RAM配置,的确跑个RTOS没问题

使用特权

评论回复
51xlf| | 2021-9-3 21:30 | 显示全部楼层
能够一直RT-Thead吗?        

使用特权

评论回复
i1mcu| | 2021-9-3 21:30 | 显示全部楼层
这个芯片多大的flash呢   

使用特权

评论回复
pmp| | 2021-9-3 21:31 | 显示全部楼层
可以直接配置生成RTOS代码 ?      

使用特权

评论回复
mmbs| | 2021-9-3 21:31 | 显示全部楼层
主要是RAM和flash决定的。     

使用特权

评论回复
1988020566| | 2021-9-3 21:31 | 显示全部楼层
有移植成功的教程吗?      

使用特权

评论回复
lzbf| | 2021-9-3 21:32 | 显示全部楼层
PIC18F16Q41的FLASH空间很大吗   

使用特权

评论回复
houjiakai| | 2021-9-3 21:32 | 显示全部楼层
这个是官网申请的板子吗   

使用特权

评论回复
youtome| | 2021-9-3 21:32 | 显示全部楼层
定时器中断函数            

使用特权

评论回复
cemaj| | 2021-9-3 21:32 | 显示全部楼层
TMT是什么?      

使用特权

评论回复
jimmhu| | 2021-9-3 21:32 | 显示全部楼层
定时器的调度具体含义是什么   

使用特权

评论回复
1988020566| | 2021-9-3 21:32 | 显示全部楼层
期待楼主分享详细的移植教程。   

使用特权

评论回复
qjp1988113|  楼主 | 2021-9-4 19:04 | 显示全部楼层
houjiakai 发表于 2021-9-3 21:32
这个是官网申请的板子吗

是的

使用特权

评论回复
qjp1988113|  楼主 | 2021-9-4 19:28 | 显示全部楼层
i1mcu 发表于 2021-9-3 21:30
这个芯片多大的flash呢

64K FLASH,4K RAM

使用特权

评论回复
littlelida| | 2021-9-14 15:28 | 显示全部楼层
TMT是什么东西?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

111

主题

627

帖子

2

粉丝