【MM32 eMiniBoard测评报告】SysTick实现软定时器进行线程调度
在平时我们针对裸机进行开发不使用RTOS的时候,有时候需要使用到简单的线程调度,如果使用硬件定时器实现的话,可能会受到硬件本身定时器资源的限制,这时候我们可以使用SysTick实现软件定时器。软件定时器是用程序模拟出来的定时器,可以由一个硬件定时器模拟出成千上万个软件定时器,这样程序在需要使用较多定时器的时候就不会受限于硬件资源的不足,这是软件定时器的一个优点,即数量不受限制。
SysTick俗称嘀嗒定时器,是Cortex内核自带的组件,它是一个24位的递减计数器,用户仅需掌握ARM的CMSIS软件提供的一个函数SysTick_Config即可,原代码如下:
/* ################################## SysTick function############################################ */
/** \ingroupCMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_SysTickFunctions SysTick Functions
\brief Functions that configure the System.
@{
*/
#if (__Vendor_SysTickConfig == 0)
/** \briefSystem 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 ticksNumber of ticks between two interrupts.
\return 0Function succeeded.
\return 1Function 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_tt;
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.00
非常感谢楼主分享 代码很详细 介绍的很清楚 是需要跑系统的吗 楼主辛苦了 看看什么情况,楼主辛苦了
页:
[1]