找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 684|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

STM32F03C8T6實現(xiàn)軟件定時器--進(jìn)行任務(wù)調(diào)度

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:684871 發(fā)表于 2025-3-21 10:06 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
背景:        最近做項目,需要快速開發(fā)和節(jié)省資源?紤]基于單片機(jī)的硬件定時器實現(xiàn)“軟件定時器的功能”,最終實現(xiàn)任務(wù)調(diào)度。
代碼移植思路:
        1)開1個定時器,配置該定時器1ms溢出1次,每溢出1次,某個標(biāo)志位就自增一次;
        2)然后移植下列代碼,就能實現(xiàn)軟件定時器功能了。



代碼如下:
1)cubemx配置時鐘
2)cubemx配置定時器




設(shè)計要求:主頻72MHZ,軟件定時器的時基為1ms;
定時器參數(shù)解讀:
(1)psc:7199
72M/(7199+1)= 10000HZ;
(2)per:9
(9+1)/10000=1/1000,即1ms定時器溢出一次
除此之外還做了串口,can,pwm等功能,但是和本篇文章的主題無關(guān)。所以不描述。

(3)生成代碼





4)移植軟件定時器代碼
在生成的hal庫代碼中添加軟件邏輯實現(xiàn)軟件定時器
涉4個文件:
1.SoftTimer.c實現(xiàn)軟件定時器的框架
2.SoftTimer.h用于聲明函數(shù)和變量
3.tim.c,在里面添加定時器中斷服務(wù)函數(shù)
4.main.c實現(xiàn)功能接口的測試



  1. /* soft_timer.c/h  3.0 */

  2. #include "SoftTimer.h"
  3. #include "stdio.h"


  4. static volatile uint32_t tickCnt = 0;           //Èí¼þ¶¨Ê±Æ÷ʱÖÓ½ÚÅÄ

  5. static softTimer timer[TIMER_NUM];        //Èí¼þ¶¨Ê±Æ÷Êý×é

  6. /*****************************************************
  7. * function: ¸üÐÂʱÖÓ½ÚÅÄ
  8. * param:   
  9. * return:   
  10. * note:     ÐèÔÚ¶¨Ê±Æ÷ÖжÏÄÚÖ´ÐÐ
  11. ******************************************************/
  12. void tickCnt_Update(void)
  13. {
  14.         tickCnt++;
  15. }

  16. /*****************************************************
  17. * function: »ñȡʱÖÓ½ÚÅÄ
  18. * param:   
  19. * return:   Ê±ÖÓ½ÚÅÄ
  20. * note:     
  21. ******************************************************/
  22. uint32_t tickCnt_Get(void)
  23. {
  24.   return tickCnt;
  25. }

  26. /*****************************************************
  27. * function: Èí¼þ¶¨Ê±Æ÷³õʼ»¯
  28. * param:   
  29. * return:   
  30. * note:     
  31. ******************************************************/
  32. void softTimer_Init(void)
  33. {
  34.         uint16_t i;
  35.        
  36.         for(i=0; i<TIMER_NUM; i++) {
  37.                 timer[i].state = SOFT_TIMER_STOPPED;
  38.                 timer[i].mode = MODE_ONE_SHOT;
  39.                 timer[i].match = 0;
  40.                 timer[i].period = 0;
  41.                 timer[i].cb = NULL;
  42.                 timer[i].argv = NULL;
  43.                 timer[i].argc = 0;
  44.         }
  45. }

  46. /*****************************************************
  47. * function: »ñÈ¡Èí¼þ¶¨Ê±Æ÷״̬
  48. * param:    Èí¼þ¶¨Ê±Æ÷ID
  49. * return:   ¶¨Ê±Æ÷״̬
  50. * note:     
  51. ******************************************************/
  52. uint8_t softTimer_GetState(uint16_t id)
  53. {
  54.         return timer[id].state;
  55. }

  56. /*****************************************************
  57. * function: Æô¶¯Èí¼þ¶¨Ê±Æ÷
  58. * param1:   Èí¼þ¶¨Ê±Æ÷ID
  59. * param2:   ¶¨Ê±Æ÷ģʽ
  60. * param3:   ÑÓʱʱ¼ä(¶ÔÖÜÆÚ¶¨Ê±Æ÷£¬ÒàÊÇÖÜÆÚʱ¼ä)£¬µ¥Î»TIME_BASE_MS
  61. * param4:   »Øµ÷º¯ÊýÖ¸Õë
  62. * param5:   »Øµ÷º¯Êý²ÎÊý£º²ÎÊýÖ¸Õë
  63. * param6:   »Øµ÷º¯Êý²ÎÊý£º²ÎÊý³¤¶È
  64. * return:   
  65. * note:     
  66. ******************************************************/
  67. void softTimer_Start(uint16_t id, tmrMode mode, uint32_t delay, callback *cb, void *argv, uint16_t argc)
  68. {
  69.         assert_param(id < TIMER_NUM);
  70.         assert_param(mode == MODE_ONE_SHOT || mode == MODE_PERIODIC);
  71.        
  72.         timer[id].match = tickCnt_Get() + delay;
  73.         timer[id].period = delay;
  74.         timer[id].state = SOFT_TIMER_RUNNING;
  75.         timer[id].mode = mode;
  76.         timer[id].cb = cb;
  77.         timer[id].argv = argv;
  78.         timer[id].argc = argc;
  79. }

  80. /*****************************************************
  81. * function: Í£Ö¹Èí¼þ¶¨Ê±Æ÷
  82. * param:    Èí¼þ¶¨Ê±Æ÷ID
  83. * return:   
  84. * note:     
  85. ******************************************************/
  86. void softTimer_Stop(uint16_t id)
  87. {
  88.         assert_param(id < TIMER_NUM);
  89.         timer[id].state = SOFT_TIMER_STOPPED;
  90. }

  91. /*****************************************************
  92. * function: ¸üÐÂÈí¼þ¶¨Ê±Æ÷״̬
  93. * param:   
  94. * return:   
  95. * note:     
  96. ******************************************************/
  97. void softTimer_Update(void)
  98. {
  99.         uint16_t i;
  100.        
  101.         for(i=0; i<TIMER_NUM; i++) {
  102.           switch (timer[i].state) {
  103.       case SOFT_TIMER_STOPPED:
  104.                           break;
  105.                
  106.                   case SOFT_TIMER_RUNNING:
  107.                           if(timer[i].match <= tickCnt_Get()) {
  108.                                   timer[i].state = SOFT_TIMER_TIMEOUT;
  109.                                         timer[i].cb(timer[i].argv, timer[i].argc);       //Ö´Ðлص÷º¯Êý
  110.                           }
  111.                           break;
  112.                        
  113.                   case SOFT_TIMER_TIMEOUT:
  114.                                 if(timer[i].mode == MODE_ONE_SHOT) {
  115.                             timer[i].state = SOFT_TIMER_STOPPED;
  116.                                 } else {
  117.                                         timer[i].match = tickCnt_Get() + timer[i].period;
  118.                                         timer[i].state = SOFT_TIMER_RUNNING;
  119.                                 }
  120.                           break;
  121.                
  122.                   default:
  123.                           //printf("timer[%d] state error!\r\n", i);
  124.                           break;
  125.           }
  126.   }
  127. }
復(fù)制代碼




  1. /* soft_timer.h/h  3.0 */

  2. #ifndef _SOFT_TIMER_H
  3. #define _SOFT_TIMER_H

  4. #include "stdint.h"


  5. /* ������ʱ��ʱ�ӽ��ĵ�λ */
  6. #define TIME_BASE_MS                                  1    //1ms

  7. /* ������ʱ������ */
  8. #define TIMER_NUM                   10

  9. /* ��ʱ��ID */
  10. #define TASK0            0
  11. #define TASK1            1
  12. #define TASK2            2
  13. #define TASK3            3
  14. #define TASK3            4
  15. #define TASK3            5
  16. #define TASK3            6
  17. #define TASK3            7
  18. #define TASK3            8
  19. #define TASK3            9

  20. typedef void callback(void *argv, uint16_t argc);

  21. typedef struct softTimer {
  22.         uint8_t state;           //״̬
  23.         uint8_t mode;            //ģʽ
  24.         uint32_t match;          //����ʱ��
  25.         uint32_t period;         //��ʱ����
  26.         callback *cb;            //�ص�����ָ��
  27.         void *argv;              //����ָ��
  28.         uint16_t argc;           //��������
  29. }softTimer;

  30. typedef enum tmrState {
  31.         SOFT_TIMER_STOPPED = 0,  //ֹͣ
  32.         SOFT_TIMER_RUNNING,      //����
  33.         SOFT_TIMER_TIMEOUT       //��ʱ
  34. }tmrState;

  35. typedef enum tmrMode {
  36.         MODE_ONE_SHOT = 0,       //����ģʽ
  37.         MODE_PERIODIC,           //����ģʽ
  38. }tmrMode;


  39. void tickCnt_Update(void);
  40. uint32_t tickCnt_Get(void);
  41. void softTimer_Init(void);
  42. uint8_t softTimer_GetState(uint16_t id);
  43. void softTimer_Start(uint16_t id, tmrMode mode, uint32_t delay, callback *cb, void *argv, uint16_t argc);
  44. void softTimer_Stop(uint16_t id);
  45. void softTimer_Update(void);

  46. #endif //_SOFT_TIMER_H
復(fù)制代碼
  1. ## tim.c里添加定時器中斷服務(wù)函數(shù)

  2. ***
  3. ```c
  4. /* USER CODE BEGIN 1 */
  5. //實現(xiàn)軟件定時器
  6. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  7. {
  8.   tickCnt_Update();//每1毫秒觸發(fā)一次定時器中斷,所以每1ms記錄一次
  9. }
  10. /* USER CODE END 1 */
復(fù)制代碼
  1. ## main.c中添加三行代碼以及實現(xiàn)User_config_task_for_sort_timer(); Task_for_User_Uart_handle()是我實現(xiàn)的串口回環(huán)測試,可以不添加

  2. ***

  3. ```c
  4. int main(void)
  5. {
  6.   /* USER CODE BEGIN 1 */

  7.   /* USER CODE END 1 */

  8.   /* MCU Configuration--------------------------------------------------------*/

  9.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  10.   HAL_Init();

  11.   /* USER CODE BEGIN Init */

  12.   /* USER CODE END Init */

  13.   /* Configure the system clock */
  14.   SystemClock_Config();

  15.   /* USER CODE BEGIN SysInit */

  16.   /* USER CODE END SysInit */

  17.   /* Initialize all configured peripherals */
  18.   MX_GPIO_Init();
  19.   MX_DMA_Init();
  20.   MX_CAN_Init();
  21.   MX_USART1_UART_Init();
  22.   MX_USART2_UART_Init();
  23.   MX_USART3_UART_Init();
  24.   MX_I2C1_Init();
  25.   MX_TIM4_Init();
  26.   MX_TIM2_Init();//打開定時器2,目的是應(yīng)用于軟件定時器
  27.   /* USER CODE BEGIN 2 */
  28.   HAL_TIM_Base_Start_IT(&htim2);//使能定時器----一定要開,否則無法使用
  29.   User_config_UART_DMA();
  30.   HAL_UART_Transmit(&huart1, "MCU_RESET\r\n", strlen("MCU_RESET\r\n"), 100);
  31.   User_config_task_for_sort_timer();//這里實現(xiàn)了軟件定時器掛載的任務(wù)

  32.   /* USER CODE END 2 */
  33.   /* Infinite loop */
  34.   /* USER CODE BEGIN WHILE */
  35.   while (1)
  36.   {
  37.     /* USER CODE END WHILE */
  38.     /* USER CODE BEGIN 3 */
  39.     softTimer_Update();//實現(xiàn)任務(wù)調(diào)度
  40.   }
  41.   /* USER CODE END 3 */
  42. }

  43. void User_config_task_for_sort_timer()
  44. {
  45.     softTimer_Start(TASK0, MODE_PERIODIC, 1000, stringPrint, 0, 0); //啟動軟件定時器
  46.    // softTimer_Start(TASK1, MODE_PERIODIC, 10, Task_for_User_Uart_handle, 0, 0); //10ms解析一次串口,用于串口回顯測試
  47. }

  48. void stringPrint(void *argv, uint16_t argc)
  49. {
  50.   HAL_UART_Transmit(&huart1, "111111\r\n", strlen("111111\r\n"), 100);

  51. }
復(fù)制代碼





時間間隔約為1S;

以上是基于hal庫的代碼;
參考代碼是基于標(biāo)準(zhǔn)庫的,代碼:參考https://blog.csdn.net/qq_26904271/article/details/83833168

評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:469589 發(fā)表于 2025-4-1 11:49 | 只看該作者
本帖最后由 GlenXu 于 2025-4-24 09:03 編輯

看上去有點復(fù)雜,但思路還是不錯的。我做過類似的,但用的是SWITCH做調(diào)度的,有點過于簡單
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表