背景: 最近做项目,需要快速开发和节省资源。考虑基于单片机的硬件定时器实现“软件定时器的功能”,最终实现任务调度。
代码移植思路:
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
|