一,项目背景:
优化裸机项目,考虑到硬件资源有限,所以不移植rtos,采用的方案是“软件定时器+状态机”
注意点:
软件定时器的任务要求短小精悍,要在定时时间到达前运行完毕。原因:未做保存现场和恢复现场。
二,下面是cubemx的配置:
我还做了其他功能,但是这里仅描述“时钟配置”,“定时器配置”
(1)时钟72MHZ
(2)定时器2通道1
设计要求:主频72MHZ,软件定时器的时基为1ms;
定时器参数解读:
(1)psc:7199
72M/(7199+1)= 10000HZ;
(2)per:9
(9+1)/10000=1/1000,即1ms定时器溢出一次
(3)除此之外还做了串口,can,pwm等功能,但是和本篇文章的主题无关。所以不描述。
三,在生成的hal库代码中添加软件逻辑实现软件定时器
涉4个文件:
1.SoftTimer.c实现软件定时器的框架
2.SoftTimer.h用于声明函数和变量
3.tim.c,在里面添加定时器中断服务函数
4.main.c实现功能接口的测试
/* soft_timer.c/h 3.0 */
#include "SoftTimer.h"
#include "stdio.h"
static volatile uint32_t tickCnt = 0; //Èí¼þ¶¨Ê±Æ÷ʱÖÓ½ÚÅÄ
static softTimer timer[TIMER_NUM]; //Èí¼þ¶¨Ê±Æ÷Êý×é
/*****************************************************
* function: ¸üÐÂʱÖÓ½ÚÅÄ
* param:
* return:
* note: ÐèÔÚ¶¨Ê±Æ÷ÖжÏÄÚÖ´ÐÐ
******************************************************/
void tickCnt_Update(void)
{
tickCnt++;
}
/*****************************************************
* function: »ñȡʱÖÓ½ÚÅÄ
* param:
* return: ʱÖÓ½ÚÅÄ
* note:
******************************************************/
uint32_t tickCnt_Get(void)
{
return tickCnt;
}
/*****************************************************
* function: Èí¼þ¶¨Ê±Æ÷³õʼ»¯
* param:
* return:
* note:
******************************************************/
void softTimer_Init(void)
{
uint16_t i;
for(i=0; i<TIMER_NUM; i++) {
timer[i].state = SOFT_TIMER_STOPPED;
timer[i].mode = MODE_ONE_SHOT;
timer[i].match = 0;
timer[i].period = 0;
timer[i].cb = NULL;
timer[i].argv = NULL;
timer[i].argc = 0;
}
}
/*****************************************************
* function: »ñÈ¡Èí¼þ¶¨Ê±Æ÷״̬
* param: Èí¼þ¶¨Ê±Æ÷ID
* return: ¶¨Ê±Æ÷״̬
* note:
******************************************************/
uint8_t softTimer_GetState(uint16_t id)
{
return timer[id].state;
}
/*****************************************************
* function: Æô¶¯Èí¼þ¶¨Ê±Æ÷
* param1: Èí¼þ¶¨Ê±Æ÷ID
* param2: ¶¨Ê±Æ÷ģʽ
* param3: ÑÓʱʱ¼ä(¶ÔÖÜÆÚ¶¨Ê±Æ÷£¬ÒàÊÇÖÜÆÚʱ¼ä)£¬µ¥Î»TIME_BASE_MS
* param4: »Øµ÷º¯ÊýÖ¸Õë
* param5: »Øµ÷º¯Êý²ÎÊý£º²ÎÊýÖ¸Õë
* param6: »Øµ÷º¯Êý²ÎÊý£º²ÎÊý³¤¶È
* return:
* note:
******************************************************/
void softTimer_Start(uint16_t id, tmrMode mode, uint32_t delay, callback *cb, void *argv, uint16_t argc)
{
assert_param(id < TIMER_NUM);
assert_param(mode == MODE_ONE_SHOT || mode == MODE_PERIODIC);
timer[id].match = tickCnt_Get() + delay;
timer[id].period = delay;
timer[id].state = SOFT_TIMER_RUNNING;
timer[id].mode = mode;
timer[id].cb = cb;
timer[id].argv = argv;
timer[id].argc = argc;
}
/*****************************************************
* function: Í£Ö¹Èí¼þ¶¨Ê±Æ÷
* param: Èí¼þ¶¨Ê±Æ÷ID
* return:
* note:
******************************************************/
void softTimer_Stop(uint16_t id)
{
assert_param(id < TIMER_NUM);
timer[id].state = SOFT_TIMER_STOPPED;
}
/*****************************************************
* function: ¸üÐÂÈí¼þ¶¨Ê±Æ÷״̬
* param:
* return:
* note:
******************************************************/
void softTimer_Update(void)
{
uint16_t i;
for(i=0; i<TIMER_NUM; i++) {
switch (timer[i].state) {
case SOFT_TIMER_STOPPED:
break;
case SOFT_TIMER_RUNNING:
if(timer[i].match <= tickCnt_Get()) {
timer[i].state = SOFT_TIMER_TIMEOUT;
timer[i].cb(timer[i].argv, timer[i].argc); //Ö´Ðлص÷º¯Êý
}
break;
case SOFT_TIMER_TIMEOUT:
if(timer[i].mode == MODE_ONE_SHOT) {
timer[i].state = SOFT_TIMER_STOPPED;
} else {
timer[i].match = tickCnt_Get() + timer[i].period;
timer[i].state = SOFT_TIMER_RUNNING;
}
break;
default:
printf("timer[%d] state error!\r\n", i);
break;
}
}
}
/* soft_timer.c/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
/* USER CODE BEGIN 1 */
//实现软件定时器
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
tickCnt_Update();//每1毫秒触发一次定时器中断,所以每1ms记录一次
}
/* USER CODE END 1 */
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);
}
以上是基于hal库的代码;
参考代码是基于标准库的,代码:参考https://blog.csdn.net/qq_26904271/article/details/83833168