背景: 最近做項目,需要快速開發和節省資源。考慮基于單片機的硬件定時器實現“軟件定時器的功能”,最終實現任務調度。
代碼移植思路:
1)開1個定時器,配置該定時器1ms溢出1次,每溢出1次,某個標志位就自增一次;
2)然后移植下列代碼,就能實現軟件定時器功能了。
代碼如下:
1)cubemx配置時鐘
2)cubemx配置定時器
設計要求:主頻72MHZ,軟件定時器的時基為1ms;
定時器參數解讀:
(1)psc:7199
72M/(7199+1)= 10000HZ;
(2)per:9
(9+1)/10000=1/1000,即1ms定時器溢出一次
除此之外還做了串口,can,pwm等功能,但是和本篇文章的主題無關。所以不描述。
(3)生成代碼
4)移植軟件定時器代碼
在生成的hal庫代碼中添加軟件邏輯實現軟件定時器
涉4個文件:
1.SoftTimer.c實現軟件定時器的框架
2.SoftTimer.h用于聲明函數和變量
3.tim.c,在里面添加定時器中斷服務函數
4.main.c實現功能接口的測試
- /* soft_timer.h/h 3.0 */
- #ifndef _SOFT_TIMER_H
- #define _SOFT_TIMER_H
- #include "stdint.h"
- /* ������ʱ��ʱ�ӽ��ĵ�λ */
- #define TIME_BASE_MS 1 //1ms
- /* ������ʱ������ */
- #define TIMER_NUM 10
- /* ��ʱ��ID */
- #define TASK0 0
- #define TASK1 1
- #define TASK2 2
- #define TASK3 3
- #define TASK3 4
- #define TASK3 5
- #define TASK3 6
- #define TASK3 7
- #define TASK3 8
- #define TASK3 9
- typedef void callback(void *argv, uint16_t argc);
- typedef struct softTimer {
- uint8_t state; //״̬
- uint8_t mode; //ģʽ
- uint32_t match; //����ʱ��
- uint32_t period; //��ʱ����
- callback *cb; //�ص�����ָ��
- void *argv; //����ָ��
- uint16_t argc; //��������
- }softTimer;
- typedef enum tmrState {
- SOFT_TIMER_STOPPED = 0, //ֹͣ
- SOFT_TIMER_RUNNING, //����
- SOFT_TIMER_TIMEOUT //��ʱ
- }tmrState;
- typedef enum tmrMode {
- MODE_ONE_SHOT = 0, //����ģʽ
- MODE_PERIODIC, //����ģʽ
- }tmrMode;
- void tickCnt_Update(void);
- uint32_t tickCnt_Get(void);
- void softTimer_Init(void);
- uint8_t softTimer_GetState(uint16_t id);
- void softTimer_Start(uint16_t id, tmrMode mode, uint32_t delay, callback *cb, void *argv, uint16_t argc);
- void softTimer_Stop(uint16_t id);
- void softTimer_Update(void);
- #endif //_SOFT_TIMER_H
復制代碼- ## tim.c里添加定時器中斷服務函數
- ***
- ```c
- /* USER CODE BEGIN 1 */
- //實現軟件定時器
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
- {
- tickCnt_Update();//每1毫秒觸發一次定時器中斷,所以每1ms記錄一次
- }
- /* USER CODE END 1 */
復制代碼- ## main.c中添加三行代碼以及實現User_config_task_for_sort_timer(); Task_for_User_Uart_handle()是我實現的串口回環測試,可以不添加
- ***
- ```c
- int main(void)
- {
- /* USER CODE BEGIN 1 */
- /* USER CODE END 1 */
- /* MCU Configuration--------------------------------------------------------*/
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
- HAL_Init();
- /* USER CODE BEGIN Init */
- /* USER CODE END Init */
- /* Configure the system clock */
- SystemClock_Config();
- /* USER CODE BEGIN SysInit */
- /* USER CODE END SysInit */
- /* Initialize all configured peripherals */
- MX_GPIO_Init();
- MX_DMA_Init();
- MX_CAN_Init();
- MX_USART1_UART_Init();
- MX_USART2_UART_Init();
- MX_USART3_UART_Init();
- MX_I2C1_Init();
- MX_TIM4_Init();
- MX_TIM2_Init();//打開定時器2,目的是應用于軟件定時器
- /* USER CODE BEGIN 2 */
- HAL_TIM_Base_Start_IT(&htim2);//使能定時器----一定要開,否則無法使用
- User_config_UART_DMA();
- HAL_UART_Transmit(&huart1, "MCU_RESET\r\n", strlen("MCU_RESET\r\n"), 100);
- User_config_task_for_sort_timer();//這里實現了軟件定時器掛載的任務
- /* USER CODE END 2 */
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- softTimer_Update();//實現任務調度
- }
- /* USER CODE END 3 */
- }
- void User_config_task_for_sort_timer()
- {
- softTimer_Start(TASK0, MODE_PERIODIC, 1000, stringPrint, 0, 0); //啟動軟件定時器
- // softTimer_Start(TASK1, MODE_PERIODIC, 10, Task_for_User_Uart_handle, 0, 0); //10ms解析一次串口,用于串口回顯測試
- }
- void stringPrint(void *argv, uint16_t argc)
- {
- HAL_UART_Transmit(&huart1, "111111\r\n", strlen("111111\r\n"), 100);
- }
復制代碼
時間間隔約為1S;
以上是基于hal庫的代碼;
參考代碼是基于標準庫的,代碼:參考https://blog.csdn.net/qq_26904271/article/details/83833168
|