基于hal库实现stm32f103c8t6裸机项目的“软件定时器”

一,项目背景:
优化裸机项目,考虑到硬件资源有限,所以不移植rtos,采用的方案是“软件定时器+状态机”
注意点:
软件定时器的任务要求短小精悍,要在定时时间到达前运行完毕。原因:未做保存现场和恢复现场。

二,下面是cubemx的配置:
我还做了其他功能,但是这里仅描述“时钟配置”,“定时器配置”
(1)时钟72MHZ
基于hal库实现stm32f103c8t6裸机项目的“软件定时器”_第1张图片

(2)定时器2通道1
基于hal库实现stm32f103c8t6裸机项目的“软件定时器”_第2张图片
基于hal库实现stm32f103c8t6裸机项目的“软件定时器”_第3张图片
基于hal库实现stm32f103c8t6裸机项目的“软件定时器”_第4张图片
设计要求:主频72MHZ,软件定时器的时基为1ms;
定时器参数解读:
(1)psc:7199
72M/(7199+1)= 10000HZ;
(2)per:9
(9+1)/10000=1/1000,即1ms定时器溢出一次

(3)除此之外还做了串口,can,pwm等功能,但是和本篇文章的主题无关。所以不描述。

(4)生成代码
基于hal库实现stm32f103c8t6裸机项目的“软件定时器”_第5张图片
在这里插入图片描述

三,在生成的hal库代码中添加软件逻辑实现软件定时器
涉4个文件:
1.SoftTimer.c实现软件定时器的框架
2.SoftTimer.h用于声明函数和变量
3.tim.c,在里面添加定时器中断服务函数
4.main.c实现功能接口的测试


SoftTimer.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;
	  }
  }
}

基于hal库实现stm32f103c8t6裸机项目的“软件定时器”_第6张图片


SoftTimer.h


/* 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


tim.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()是我实现的串口回环测试,可以不添加


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库实现stm32f103c8t6裸机项目的“软件定时器”_第7张图片
四,测试
基于hal库实现stm32f103c8t6裸机项目的“软件定时器”_第8张图片
基于hal库实现stm32f103c8t6裸机项目的“软件定时器”_第9张图片
时间间隔约为1S;

以上是基于hal库的代码;
参考代码是基于标准库的,代码:参考https://blog.csdn.net/qq_26904271/article/details/83833168

你可能感兴趣的:(stm32f103,stm32,单片机,软件定时器)