打印
[MM32硬件]

【MM32 eMiniBoard测评报告】SysTick实现软定时器进行线程调度

[复制链接]
550|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
       在平时我们针对裸机进行开发不使用RTOS的时候,有时候需要使用到简单的线程调度,如果使用硬件定时器实现的话,可能会受到硬件本身定时器资源的限制,这时候我们可以使用SysTick实现软件定时器。
        软件定时器是用程序模拟出来的定时器,可以由一个硬件定时器模拟出成千上万个软件定时器,这样程序在需要使用较多定时器的时候就不会受限于硬件资源的不足,这是软件定时器的一个优点,即数量不受限制。
        SysTick俗称嘀嗒定时器,是Cortex内核自带的组件,它是一个24位的递减计数器,用户仅需掌握ARM的CMSIS软件提供的一个函数SysTick_Config即可,原代码如下:
/* ##################################    SysTick function  ############################################ */
/** \ingroup  CMSIS_Core_FunctionInterface
    \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
    \brief      Functions that configure the System.
  @{
*/

#if (__Vendor_SysTickConfig == 0)

/** \brief  System Tick Configuration

    The function initializes the System Timer and its interrupt, and starts the System Tick Timer.
    Counter is in free running mode to generate periodic interrupts.

    \param [in]  ticks  Number of ticks between two interrupts.

    \return          0  Function succeeded.
    \return          1  Function failed.

    \note     When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
    function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
    must contain a vendor-specific implementation of this function.

*/
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk)  return (1);      /* Reload value impossible */

  SysTick->LOAD  = ticks - 1;                                  /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
  return (0);                                                  /* Function successful */
}
函数的形参表示内核时钟多少个周期后触发一次Systick定时中断,比如形参配置为如下数值。
-- SystemCoreClock / 1000  表示定时频率为 1000Hz, 也就是定时周期为  1ms。
-- SystemCoreClock / 500   表示定时频率为 500Hz,  也就是定时周期为  2ms。
-- SystemCoreClock / 2000  表示定时频率为 2000Hz, 也就是定时周期为  500us。

          本次实验中使用软定时器实现了两个线程调度函数,其中第一个线程实现了按键扫描的功能,第二个线程实现了板载LED流水灯的功能,main函数如下:
#include "delay.h"
#include "sys.h"
#include "led.h"
#include "key.h"
#include "uart.h"
#include "soft_timer.h"


//变量定义
uint8_t count = 0;
extern u32 SystemCoreClock;

struct soft_timer test_timer1,test_timer2;        //creat 2 soft timers

void timer1_call_back(void);                //call back functions when timer over
void timer2_call_back(void);

void hw_timer_init(void)
{

        SysTick_Config(SystemCoreClock / 100);                                        //10 ms
        NVIC_SetPriority (SysTick_IRQn, 1);                                //NVIC config  

}

//按键扫描函数
void KeyScan(void)
{       
        uint8_t  t;
        t=KEY_Scan(0);                    //得到键值
        switch(t)
        {                                 
        case KEY1_PRES:         //K1默认不连PC13,默认连接reset复位按键,所以按下K1会复位
                        printf("KEY1 Clicked!\r\n");  
                        break;
        case WKUP_PRES:
                        printf("KEY2 Clicked!\r\n");
                        break;
        case KEY3_PRES:                               
                        printf("KEY3 Clicked!\r\n");
                        break;
        case KEY4_PRES:                               
                        printf("KEY4 Clicked!\r\n");
                        break;
        default:
                        break;       
        }
}

void timer1_call_back(void)
{

        reload_timer(&test_timer1,10);                //
        start_timer(&test_timer1);                        //should be restart because of one shot software timer.

        //按键扫描
        KeyScan();
}

void timer2_call_back(void)
{

        reload_timer(&test_timer2,30);               
        start_timer(&test_timer2);

        count++;
        if(count==1)
        {
                LED1_ON();
                LED2_OFF();
                LED3_OFF();
                LED4_OFF();       
        }else if(count==2)
        {
                LED1_OFF();
                LED2_ON();
                LED3_OFF();
                LED4_OFF();       
        }else if(count==3)
        {
                LED1_OFF();
                LED2_OFF();
                LED3_ON();
                LED4_OFF();               
        }else if(count==4)
        {
                count = 0;
                LED1_OFF();
                LED2_OFF();
                LED3_OFF();
                LED4_ON();       
        }
}

/********************************************************************************************************
**函数信息 :main(void)                       
**功能描述 :
**输入参数 :无
**输出参数 :无
********************************************************************************************************/
int main(void)
{
   
    delay_init();       
    LED_Init();                                       //初始化与LED连接的硬件接口
    KEY_Init();                      //初始化与按键连接的硬件接口
        uart_initwBaudRate(9600);        //串口初始化
       
        hw_timer_init();
       
        soft_timer_list_reset();

        add_timer(&test_timer1,timer1_call_back,60);        //
        start_timer(&test_timer1);

        add_timer(&test_timer2,timer2_call_back,30);        //
        start_timer(&test_timer2);

       
        //打印欢迎信息
        printf("Soft Timer Test Using SysTick\r\n");
        printf("1、KeyScan\r\n");
        printf("2、LED\r\n");
                          
    while(1)
    {
                                       
        }
}

该工程中已经将软件定时器编写成了驱动文件,便于移植和使用,主要文件为soft_timer.c和soft_timer.h文件,在Keil工程中添加源文件后的目录如下:

使用时需要在SysTick中断处理函数中添加软定时器刷新函数:

接下来使用时进行硬件定时器初始化和中断优先级配置和:

最后就是软件定时器的创建和回调函数编写:

本实验最后实现了LED流水灯和按键扫描两个线程的调度:

本工程完整源码如下:

此部分内容已被设置为付费内容,您可以在支付 2 元 人民币后浏览本楼层全部付费内容点击购买

本楼层付费信息已有1人购买

使用特权

评论回复
沙发
kxsi| | 2020-6-1 16:34 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
板凳
nawu| | 2020-6-1 16:34 | 只看该作者
代码很详细

使用特权

评论回复
地板
qcliu| | 2020-6-1 16:34 | 只看该作者
介绍的很清楚

使用特权

评论回复
5
tfqi| | 2020-6-1 16:35 | 只看该作者
是需要跑系统的吗

使用特权

评论回复
6
wiba| | 2020-6-1 16:35 | 只看该作者
楼主辛苦了

使用特权

评论回复
7
hello、C| | 2020-6-4 13:42 | 只看该作者
看看什么情况,楼主辛苦了

使用特权

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

本版积分规则

个人签名:欢迎参与LabVIEW版块的讨论学习! 点我一键即达

157

主题

2338

帖子

40

粉丝