[国产单片机] 【东软载波ES32F369x】SysTick实现软定时器进行简单任务调度

[复制链接]
 楼主| hbzjt2011 发表于 2021-1-5 22:25 | 显示全部楼层 |阅读模式
本帖最后由 hbzjt2011 于 2021-1-5 22:28 编辑

#申请原创#          SysTick俗称嘀嗒定时器,是Cortex内核自带的组件,它是一个24位的递减计数器,利用SysTick实现软定时器结合回调任务函数可以实现简单任务调度。本次演示例子中利用两个软定时器实现了LED灯循环亮灭和按键扫描两个任务。首先将软定时器程序源文件soft_timer.c和soft_timer.h加入工程目中的driver文件夹。soft_timer.c

  1. #include "soft_timer.h"

  2. static struct soft_timer* soft_timer_list;

  3. /**
  4.   * [url=home.php?mod=space&uid=247401]@brief[/url]  reset the soft_timer_list.
  5.   * @retval None.
  6.   */

  7. void soft_timer_list_reset(void)
  8. {
  9.         soft_timer_list = TIMER_NULL;
  10. }


  11. /**
  12.   * [url=home.php?mod=space&uid=247401]@brief[/url]  add a timer to the software timer list.
  13.   * @param  timer---------pointer to the timer you want to add.
  14.   * @param  call_back-----the call back function when the timer is over.
  15.   * @param  time_count-----the timer count.
  16.   * @retval None.
  17.   */


  18. void add_timer(struct soft_timer* timer,void(*call_back)(void),unsigned int time_count)
  19. {
  20.         struct soft_timer* p;

  21.         p = soft_timer_list;

  22.         if(p==TIMER_NULL)                                //if the soft_timer_list have no timer
  23.         {
  24.                 p = timer;
  25.                 p->flag = TIMER_FLAG_SUSPEND;
  26.                 p->tick_count = time_count;
  27.                 p->time_over_proc = call_back;
  28.                 p->next = TIMER_NULL;
  29.                 soft_timer_list = p;

  30.         }
  31.         else
  32.         {
  33.                 p = soft_timer_list;
  34.                 while(p->next!=TIMER_NULL)
  35.                 {
  36.                         p = p->next;
  37.                 }
  38.                 p->next = timer;
  39.                 p->next->flag = TIMER_FLAG_SUSPEND;
  40.                 p->next->tick_count = time_count;
  41.                 p->next->time_over_proc = call_back;
  42.                 p->next->next = TIMER_NULL;
  43.         }
  44.         



  45. }


  46. /**
  47.   * @brief  remove a timer from the software timer list.
  48.   * @retval None.
  49.   */
  50. void remove_timer(struct soft_timer* timer)
  51. {
  52.         struct soft_timer* t;
  53.         for(t = soft_timer_list; t != TIMER_NULL; t = t->next)
  54.         {
  55.                 if(t->next==timer)
  56.                 {
  57.                         t->next = timer->next;
  58.                         break;
  59.                 }
  60.         }
  61. }



  62. /**
  63.   * @brief  start or continue a timer   
  64.   * @retval None.
  65.   */

  66. void start_timer(struct soft_timer* timer)
  67. {
  68.         timer->flag = TIMER_FLAG_RUN ;
  69. }







  70. /**
  71.   * @brief  stop a timer without calling back
  72.   * @retval None.
  73.   */
  74. void stop_timer(struct soft_timer* timer)
  75. {
  76.         timer->flag = TIMER_FLAG_STOP;
  77.         timer->tick_count = 0;
  78. }



  79. /**
  80.   * @brief  stop a timer with calling back
  81.   * @retval None.
  82.   */

  83. void stop_timer_with_call(struct soft_timer* timer)
  84. {
  85.         if(timer->flag == TIMER_FLAG_RUN)
  86.                 timer->tick_count = 0;
  87.         else if(timer->flag == TIMER_FLAG_SUSPEND)
  88.         {
  89.                 timer->flag = TIMER_FLAG_RUN;
  90.                 timer->tick_count = 0;
  91.         }
  92. }



  93. /**
  94.   * @brief  suspend a timer
  95.   * @retval None.
  96.   */
  97. void suspend_timer(struct soft_timer* timer)
  98. {
  99.         if(timer->flag == TIMER_FLAG_RUN)
  100.                 timer->flag = TIMER_FLAG_SUSPEND;
  101. }


  102. /**
  103.   * @brief  reload the tick_count for a timer
  104.   * @retval None.
  105.   */
  106. void reload_timer(struct soft_timer* timer,unsigned int time_count)
  107. {
  108.         timer->flag = TIMER_FLAG_SUSPEND;
  109.         timer->tick_count = time_count;
  110. }



  111. /**
  112.   * @brief  shoulde be called periodicly by the hardware timer ISR
  113.   * @retval None.
  114.   */
  115. void timer_periodic_refresh(void)
  116. {

  117.         struct soft_timer* t;

  118.         for(t = soft_timer_list; t != TIMER_NULL; t = t->next)
  119.         {
  120.                 if(t->flag==TIMER_FLAG_RUN)
  121.                 {
  122.                         if(t->tick_count > 0)
  123.                                 -- t->tick_count;
  124.                         else
  125.                         {
  126.                                 stop_timer(t);
  127.                                 t->time_over_proc();
  128.                         }
  129.                 }
  130.         }
  131.         
  132. }
soft_timer.h

  1. #ifndef __SOFT_TIMER_H__
  2. #define __SOFT_TIMER_H__


  3. struct soft_timer{
  4.         int flag;                                                        //run flag, which can be SUSPEND,RUN,STOP
  5.         unsigned int tick_count;                        //left ticks to be run
  6.         void (*time_over_proc)(void);                //timer over callback function
  7.         struct soft_timer* next;
  8. };

  9. #define TIMER_FLAG_SUSPEND                0
  10. #define TIMER_FLAG_RUN                        1
  11. #define TIMER_FLAG_STOP                        2

  12. #define TIMER_NULL                ((struct soft_timer*)0)


  13. void soft_timer_list_reset(void);
  14. void add_timer(struct soft_timer* timer,void(*call_back)(void),unsigned int time_count);
  15. void remove_timer(struct soft_timer* timer);
  16. void start_timer(struct soft_timer* timer);
  17. void stop_timer(struct soft_timer* timer);
  18. void stop_timer_with_call(struct soft_timer* timer);
  19. void suspend_timer(struct soft_timer* timer);
  20. void reload_timer(struct soft_timer* timer,unsigned int time_count);
  21. void timer_periodic_refresh(void);



  22. #endif /*__SOFT_TIMER_H__*/
然后在main.c程序中配置Systick的周期和中断优先级:
  1. void hw_timer_init(void)
  2. {
  3.         ald_systick_interval_select(SYSTICK_INTERVAL_10MS);                //10 ms
  4.         NVIC_SetPriority (SysTick_IRQn, 1);                                //NVIC config  
  5. }
同时再irq.c文件中的系统嘀嗒定时器中断处理函数中添加软定时器刷新函数:
  1. void SysTick_Handler(void)
  2. {
  3.         ald_inc_tick();
  4.         timer_periodic_refresh();
  5.         return;
  6. }

然后再程序运行开始后初始化定时器,同时复位定时器列表,添加软定时器1和软定时器2,同时在定时器1回调函数中添加按键扫描处理函数,在定时器2回调函数中添加LED灯处理函数,编译下载即可实现两个定时器任务循环调度运行。时间片可以通过定时器创建时设定。工程文件目录如下:

key.c
  1. #include "main.h"
  2. //////////////////////////////////////////////////////////////////////////////////         
  3. //开发板
  4. //按键输入 驱动代码                  
  5. //////////////////////////////////////////////////////////////////////////////////         

  6. //按键初始化函数
  7. void KEY_Init(void)
  8. {
  9.    
  10.         gpio_init_t x;

  11.         x.mode = GPIO_MODE_INPUT;
  12.         x.odos = GPIO_PUSH_PULL;
  13.         x.pupd = GPIO_FLOATING;
  14.         x.podrv = GPIO_OUT_DRIVE_6;
  15.         x.nodrv = GPIO_OUT_DRIVE_6;
  16.         x.flt  = GPIO_FILTER_DISABLE;
  17.         x.type = GPIO_TYPE_CMOS;
  18.         x.func = GPIO_FUNC_1;

  19.         ald_gpio_init(BSP_KEY1_PORT, BSP_KEY1_PIN, &x);
  20.         ald_gpio_init(BSP_KEY2_PORT, BSP_KEY2_PIN, &x);
  21.         ald_gpio_init(BSP_KEY3_PORT, BSP_KEY3_PIN, &x);
  22.         ald_gpio_init(BSP_KEY4_PORT, BSP_KEY4_PIN, &x);
  23.         ald_gpio_init(BSP_KEY5_PORT, BSP_KEY5_PIN, &x);
  24.    
  25. }
  26. //按键处理函数
  27. //返回按键值
  28. //mode:0,不支持连续按;1,支持连续按;
  29. //返回值:
  30. //0,没有任何按键按下
  31. //KEY1_PRES,KEY1按下
  32. //WKUP_PRES,WK_UP按下
  33. //KEY3_PRES,KEY3按下
  34. //KEY4_PRES,KEY4按下
  35. uint8_t KEY_Scan(uint8_t mode)
  36. {         
  37.     static uint8_t key_up=1;//按键按松开标志
  38.     if(mode)key_up=1;  //支持连按                  
  39.     if(key_up&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0||KEY5==0))
  40.     {
  41.         //delay_ms(10);//去抖动
  42.         key_up=0;
  43.         if(KEY1==0)return KEY1_PRES;
  44.         else if(KEY2==0)return KEY2_PRES;
  45.         else if(KEY3==0)return KEY3_PRES;
  46.         else if(KEY4==0)return KEY4_PRES;
  47.                           else if(KEY5==0)return KEY5_PRES;
  48.     }else if(KEY1==1&&KEY3==1&&KEY4==1&&KEY2==1&&KEY5==1)key_up=1;              
  49.     return 0;// 无按键按下
  50. }
key.h

  1. #ifndef __KEY_H
  2. #define __KEY_H         

  3. //////////////////////////////////////////////////////////////////////////////////         
  4. //开发板
  5. //按键驱动代码           
  6. //////////////////////////////////////////////////////////////////////////////////            

  7. /* KEY1 ---> UP
  8. * KEY2 ---> DOWN
  9. * KEY3 ---> MID
  10. * KEY4 ---> LEFT
  11. * KEY5 ---> RIGHT
  12. */
  13. #define BSP_KEY_MAX        5
  14. #define BSP_KEY1_PORT        GPIOB
  15. #define BSP_KEY1_PIN        GPIO_PIN_2
  16. #define BSP_KEY2_PORT        GPIOB
  17. #define BSP_KEY2_PIN        GPIO_PIN_12
  18. #define BSP_KEY3_PORT        GPIOC
  19. #define BSP_KEY3_PIN        GPIO_PIN_10
  20. #define BSP_KEY4_PORT        GPIOC
  21. #define BSP_KEY4_PIN        GPIO_PIN_11
  22. #define BSP_KEY5_PORT        GPIOC
  23. #define BSP_KEY5_PIN        GPIO_PIN_12

  24. #define KEY1  ald_gpio_read_pin(BSP_KEY1_PORT, BSP_KEY1_PIN)//读取按键1
  25. #define KEY2  ald_gpio_read_pin(BSP_KEY2_PORT, BSP_KEY2_PIN)//读取按键2
  26. #define KEY3  ald_gpio_read_pin(BSP_KEY3_PORT, BSP_KEY3_PIN)//读取按键3
  27. #define KEY4  ald_gpio_read_pin(BSP_KEY4_PORT, BSP_KEY4_PIN)//读取按键4
  28. #define KEY5  ald_gpio_read_pin(BSP_KEY5_PORT, BSP_KEY5_PIN)//读取按键5

  29. #define KEY1_PRES        1                //KEY1
  30. #define KEY2_PRES        2                //KEY2
  31. #define KEY3_PRES        3                //KEY3
  32. #define KEY4_PRES        4                //KEY4
  33. #define KEY5_PRES        5                //KEY5

  34. void KEY_Init(void);//IO初始化
  35. uint8_t KEY_Scan(uint8_t mode);          //按键扫描函数        

  36. #endif
main.c
  1. #include "main.h"


  2. /** @addtogroup Projects_Templates_ALD
  3.   * @{
  4.   */

  5. /** @addtogroup Templates
  6.   * @{
  7.   */
  8. extern uart_handle_t h_uart;
  9. uint8_t tx_buf[32];

  10. uint8_t count = 0;

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

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

  14. void hw_timer_init(void)
  15. {
  16.         ald_systick_interval_select(SYSTICK_INTERVAL_10MS);                //10 ms
  17.         NVIC_SetPriority (SysTick_IRQn, 1);                                //NVIC config  
  18. }

  19. //按键扫描函数
  20. void KeyScan(void)
  21. {      
  22.         uint8_t  t;
  23.         t=KEY_Scan(0);                    //得到键值
  24.         switch(t)
  25.         {                                 
  26.                 case KEY1_PRES:
  27.                         sprintf((char *)tx_buf, "KEY1 Clicked!\n");
  28.                         ald_uart_send(&h_uart, tx_buf, sizeof("KEY1 Clicked!\n"), 1000);                        
  29.                         break;
  30.                 case KEY2_PRES:
  31.                         sprintf((char *)tx_buf, "KEY2 Clicked!\n");
  32.                         ald_uart_send(&h_uart, tx_buf, sizeof("KEY2 Clicked!\n"), 1000);                        
  33.                         break;
  34.                 case KEY3_PRES:                              
  35.                         sprintf((char *)tx_buf, "KEY3 Clicked!\n");
  36.                         ald_uart_send(&h_uart, tx_buf, sizeof("KEY3 Clicked!\n"), 1000);                        
  37.                         break;
  38.                 case KEY4_PRES:                              
  39.                         sprintf((char *)tx_buf, "KEY4 Clicked!\n");
  40.                         ald_uart_send(&h_uart, tx_buf, sizeof("KEY4 Clicked!\n"), 1000);                        
  41.                         break;
  42.                 case KEY5_PRES:                              
  43.                         sprintf((char *)tx_buf, "KEY5 Clicked!\n");
  44.                         ald_uart_send(&h_uart, tx_buf, sizeof("KEY5 Clicked!\n"), 1000);                        
  45.                         break;
  46.                 default:
  47.                         break;      
  48.         }
  49. }

  50. void timer1_call_back(void)
  51. {
  52.         reload_timer(&test_timer1,10);                //
  53.         start_timer(&test_timer1);                        //should be restart because of one shot software timer.

  54.         //按键扫描
  55.         KeyScan();
  56. }

  57. void timer2_call_back(void)
  58. {
  59.         reload_timer(&test_timer2,30);               
  60.         start_timer(&test_timer2);
  61.         
  62.         count++;
  63.         if(count==1)
  64.         {
  65.                 ald_gpio_write_pin(LED1_PORT, LED1_PIN, 0);
  66.                 ald_gpio_write_pin(LED2_PORT, LED2_PIN, 1);   
  67.         }else if(count==2)
  68.         {
  69.                 count = 0;
  70.                 ald_gpio_write_pin(LED1_PORT, LED1_PIN, 1);
  71.                 ald_gpio_write_pin(LED2_PORT, LED2_PIN, 0);      
  72.         }
  73. }

  74. /**
  75.   * @brief  This is main function.
  76.   *         Detect running time.
  77.   * @retval Status
  78.   */
  79. int main()
  80. {
  81.         /* Initialize ALD */
  82.         ald_cmu_init();
  83.         /* Configure system clock */
  84.         ald_cmu_pll1_config(CMU_PLL1_INPUT_HOSC_3, CMU_PLL1_OUTPUT_72M);
  85.         ald_cmu_clock_config(CMU_CLOCK_PLL1, 72000000);
  86.         /* Enable peripheral */
  87.         ald_cmu_perh_clock_config(CMU_PERH_GPIO, ENABLE);
  88.         ald_cmu_perh_clock_config(CMU_PERH_UART0, ENABLE);
  89.         
  90.         /* Initialize tx_buf */
  91.         memset(tx_buf, 0x55, sizeof(tx_buf));

  92.         ///* Initialize uart_usb */
  93.         uart_usb_init();
  94.         
  95.         /* Initialize led */
  96.         led_pin_init();
  97.         
  98.         KEY_Init();                      //初始化与按键连接的硬件接口
  99.         
  100.         hw_timer_init();      
  101.         soft_timer_list_reset();

  102.         add_timer(&test_timer1,timer1_call_back,60);        //
  103.         start_timer(&test_timer1);

  104.         add_timer(&test_timer2,timer2_call_back,30);        //
  105.         start_timer(&test_timer2);

  106. //打印信息
  107.         printf_e("Soft Timer Test Using SysTick\r\n");
  108.         printf_e("1、KeyScan\r\n");
  109.         printf_e("2、LED\r\n");

  110.         while (1) {
  111. #if 0
  112.                 /* Send a message */
  113.                 sprintf((char *)tx_buf, "es32 uart test!\n");
  114.                 ald_uart_send(&h_uart, tx_buf, sizeof("es32 uart test!\n"), 1000);
  115.                
  116.                 ald_gpio_write_pin(LED1_PORT, LED1_PIN, 0);
  117.                 ald_gpio_write_pin(LED2_PORT, LED2_PIN, 0);
  118.                 ald_delay_ms(500);
  119.                 ald_gpio_write_pin(LED1_PORT, LED1_PIN, 1);
  120.                 ald_gpio_write_pin(LED2_PORT, LED2_PIN, 1);
  121.                 ald_delay_ms(500);
  122. #endif
  123.                 ald_delay_ms(500);
  124.         }
  125. }
程序编译无误下载后,即可看到LED灯循环亮灭,按下开发板上的五向按键串口进行相应的打印输出。


@21小跑堂

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

255

主题

2826

帖子

44

粉丝
快速回复 在线客服 返回列表 返回顶部