游戏秒玩网站,免费推广网址,上海网站建设聚众网络,wordpress编辑器自动标签目录
概述
一、开发环境
二、STM32CubeMx配置
三、编码
四、运行结果
五、代码解释
六、总结 概述 timeslice是一个时间片轮询框架#xff0c;完全解耦的时间片轮询框架#xff0c;非常适合裸机单片机引用。接下来将该框架移植到stm32单片机运行#xff0c;单片机…目录
概述
一、开发环境
二、STM32CubeMx配置
三、编码
四、运行结果
五、代码解释
六、总结 概述 timeslice是一个时间片轮询框架完全解耦的时间片轮询框架非常适合裸机单片机引用。接下来将该框架移植到stm32单片机运行单片机只需用1个定时器作为时钟即可。
一、开发环境
1、硬件平台 STM32F401CEU6 内部Flash : 512KbytesSARM : 96 Kbytes
二、STM32CubeMx配置 2.1、系统时钟配置 2.2、下载调试配置 2.3、TIM配置1ms中断 2.4、usart1配置 2.5、生成代码 2.6、编译工程 三、编码
1、usart.c添加打印
/* USER CODE BEGIN 1 */
#include stdio.h
#ifdef __GNUC__/* With GCC/RAISONANCE, small printf (option LD Linker-Libraries-Small printfset to Yes) calls __io_putchar() */#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/*** brief Retargets the C library printf function to the USART.* param None* retval None*/
PUTCHAR_PROTOTYPE
{/* Place your implementation of fputc here *//* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */HAL_UART_Transmit(huart1, (uint8_t *)ch, 1, 0xFFFF);return ch;
}int fgetc(FILE * f)
{uint8_t ch 0;HAL_UART_Receive(huart1, (uint8_t *)ch, 1, 0xffff);return ch;
}/* USER CODE END 1 */
2、tim1.c
/* USER CODE BEGIN Header */
/********************************************************************************* file tim.c* brief This file provides code for the configuration* of the TIM instances.******************************************************************************* attention** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include tim.h/* USER CODE BEGIN 0 *//* USER CODE END 0 */TIM_HandleTypeDef htim1;/* TIM1 init function */
void MX_TIM1_Init(void)
{/* USER CODE BEGIN TIM1_Init 0 *//* USER CODE END TIM1_Init 0 */TIM_ClockConfigTypeDef sClockSourceConfig {0};TIM_MasterConfigTypeDef sMasterConfig {0};/* USER CODE BEGIN TIM1_Init 1 *//* USER CODE END TIM1_Init 1 */htim1.Instance TIM1;htim1.Init.Prescaler 84-1;htim1.Init.CounterMode TIM_COUNTERMODE_UP;htim1.Init.Period 1000-1;htim1.Init.ClockDivision TIM_CLOCKDIVISION_DIV1;htim1.Init.RepetitionCounter 0;htim1.Init.AutoReloadPreload TIM_AUTORELOAD_PRELOAD_DISABLE;if (HAL_TIM_Base_Init(htim1) ! HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource TIM_CLOCKSOURCE_INTERNAL;if (HAL_TIM_ConfigClockSource(htim1, sClockSourceConfig) ! HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(htim1, sMasterConfig) ! HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM1_Init 2 *//* USER CODE END TIM1_Init 2 */}void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{if(tim_baseHandle-InstanceTIM1){/* USER CODE BEGIN TIM1_MspInit 0 *//* USER CODE END TIM1_MspInit 0 *//* TIM1 clock enable */__HAL_RCC_TIM1_CLK_ENABLE();/* TIM1 interrupt Init */HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 0, 0);HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);/* USER CODE BEGIN TIM1_MspInit 1 *//* USER CODE END TIM1_MspInit 1 */}
}void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{if(tim_baseHandle-InstanceTIM1){/* USER CODE BEGIN TIM1_MspDeInit 0 *//* USER CODE END TIM1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_TIM1_CLK_DISABLE();/* TIM1 interrupt Deinit */HAL_NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn);/* USER CODE BEGIN TIM1_MspDeInit 1 *//* USER CODE END TIM1_MspDeInit 1 */}
}/* USER CODE BEGIN 1 */
#include stdio.h
int timeCount 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){if(htim-Instance TIM1){timeCount;if(timeCount1000){timeCount 0;printf(time 1s\n);}}
}/* USER CODE END 1 */3、在根目录创建timeslice文件夹分别有list.c、list.h、thread_demo.c、thread_demo.h、timeslice.c、timeslice.h文件组成
1、list.c
#include list.hvoid list_init(ListObj* list)
{list-next list-prev list;
}void list_insert_after(ListObj* list, ListObj* node)
{list-next-prev node;node-next list-next;list-next node;node-prev list;
}void list_insert_before(ListObj* list, ListObj* node)
{list-prev-next node;node-prev list-prev;list-prev node;node-next list;
}void list_remove(ListObj* node)
{node-next-prev node-prev;node-prev-next node-next;node-next node-prev node;
}int list_isempty(const ListObj* list)
{return list-next list;
}unsigned int list_len(const ListObj* list)
{unsigned int len 0;const ListObj* p list;while (p-next ! list){p p-next;len;}return len;
}2、list.h
#ifndef _LIST_H
#define _LIST_H#define offset_of(type, member) (unsigned long) ((type*)0)-member
#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offset_of(type, member)))typedef struct list_structure
{struct list_structure* next;struct list_structure* prev;
} ListObj;#define LIST_HEAD_INIT(name) {(name), (name)}
#define LIST_HEAD(name) ListObj name LIST_HEAD_INIT(name)void list_init(ListObj* list);
void list_insert_after(ListObj* list, ListObj* node);
void list_insert_before(ListObj* list, ListObj* node);
void list_remove(ListObj* node);
int list_isempty(const ListObj* list);
unsigned int list_len(const ListObj* list);#define list_entry(node, type, member) \container_of(node, type, member)#define list_for_each(pos, head) \for (pos (head)-next; pos ! (head); pos pos-next)#define list_for_each_safe(pos, n, head) \for (pos (head)-next, n pos-next; pos ! (head); \pos n, n pos-next)#endif3、timeslice.c
#include timeslice.hstatic LIST_HEAD(timeslice_task_list);void timeslice_exec(void)
{ListObj* node;TimesilceTaskObj* task;list_for_each(node, timeslice_task_list){task list_entry(node, TimesilceTaskObj, timeslice_task_list);if (task-is_run TASK_RUN){task-task_hdl();task-is_run TASK_STOP;}}
}void timeslice_tick(void)
{ListObj* node;TimesilceTaskObj* task;list_for_each(node, timeslice_task_list){task list_entry(node, TimesilceTaskObj, timeslice_task_list);if (task-timer ! 0){task-timer--;if (task-timer 0){task-is_run TASK_RUN;task-timer task-timeslice_len;}}}
}unsigned int timeslice_get_task_num(void)
{return list_len(timeslice_task_list);
}void timeslice_task_init(TimesilceTaskObj* obj, void (*task_hdl)(void), unsigned int id, unsigned int timeslice_len)
{obj-id id;obj-is_run TASK_STOP;obj-task_hdl task_hdl;obj-timer timeslice_len;obj-timeslice_len timeslice_len;
}void timeslice_task_add(TimesilceTaskObj* obj)
{list_insert_before(timeslice_task_list, obj-timeslice_task_list);
}void timeslice_task_del(TimesilceTaskObj* obj)
{if (timeslice_task_isexist(obj))list_remove(obj-timeslice_task_list);elsereturn;
}unsigned char timeslice_task_isexist(TimesilceTaskObj* obj)
{unsigned char isexist 0;ListObj* node;TimesilceTaskObj* task;list_for_each(node, timeslice_task_list){task list_entry(node, TimesilceTaskObj, timeslice_task_list);if (obj-id task-id)isexist 1;}return isexist;
}unsigned int timeslice_get_task_timeslice_len(TimesilceTaskObj* obj)
{return obj-timeslice_len;
}4、timeslice.h
#ifndef _TIMESLICE_H
#define _TIMESLICE_H#include list.htypedef enum {TASK_STOP,TASK_RUN
} IsTaskRun;typedef struct timesilce
{unsigned int id;void (*task_hdl)(void);IsTaskRun is_run;unsigned int timer;unsigned int timeslice_len;ListObj timeslice_task_list;
} TimesilceTaskObj;void timeslice_exec(void);
void timeslice_tick(void);
void timeslice_task_init(TimesilceTaskObj* obj, void (*task_hdl)(void), unsigned int id, unsigned int timeslice_len);
void timeslice_task_add(TimesilceTaskObj* obj);
void timeslice_task_del(TimesilceTaskObj* obj);
unsigned int timeslice_get_task_timeslice_len(TimesilceTaskObj* obj);
unsigned int timeslice_get_task_num(void);
unsigned char timeslice_task_isexist(TimesilceTaskObj* obj);#endif5、task_demo.c
#include stdio.h
#include timeslice.h
#include gpio.h// 创建5个任务对象
TimesilceTaskObj task_1, task_2, task_3, task_4, task_5, task_led;// 具体的任务函数
void task1_hdl(void)
{printf( task 1 is running ...\n);
}void task2_hdl(void)
{printf( task 2 is running ...\n);
}void task3_hdl(void)
{printf( task 3 is running ...\n);
}void task4_hdl(void)
{printf( task 4 is running ...\n);
}void task5_hdl(void)
{printf( task 5 is running ...\n);
}void led_hd1(void)
{HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
}// 初始化任务对象并且将任务添加到时间片轮询调度中
void task_init(void)
{timeslice_task_init(task_1, task1_hdl, 1, 10);timeslice_task_init(task_2, task2_hdl, 2, 20);timeslice_task_init(task_3, task3_hdl, 3, 30);timeslice_task_init(task_4, task4_hdl, 4, 40);timeslice_task_init(task_5, task5_hdl, 5, 50);timeslice_task_init(task_led, led_hd1, 6, 1000);timeslice_task_add(task_1);timeslice_task_add(task_2);timeslice_task_add(task_3);timeslice_task_add(task_4);timeslice_task_add(task_5);timeslice_task_add(task_led);
}void task_run(void)
{task_init();printf( task num: %d\n, timeslice_get_task_num());printf( task len: %d\n, timeslice_get_task_timeslice_len(task_3));timeslice_task_del(task_2);printf( delet task 2\n);printf( task 2 is exist: %d\n, timeslice_task_isexist(task_2));printf( task num: %d\n, timeslice_get_task_num());timeslice_task_del(task_5);printf( delet task 5\n);printf( task num: %d\n, timeslice_get_task_num());printf( task 3 is exist: %d\n, timeslice_task_isexist(task_3));timeslice_task_add(task_2);printf( add task 2\n);printf( task 2 is exist: %d\n, timeslice_task_isexist(task_2));timeslice_task_add(task_5);printf( add task 5\n);printf( task num: %d\n, timeslice_get_task_num());printf(\n\ntimeslice running\n);while(1){timeslice_exec();}}
6、task_demo.h
#ifndef _TASK_DEMO_H
#define _TASK_DEMO_Hvoid task_run(void);#endif
4、main.c
/* USER CODE BEGIN Header */
/********************************************************************************* file : main.c* brief : Main program body******************************************************************************* attention** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include main.h
#include tim.h
#include usart.h
#include gpio.h/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include stdio.h
#include task_demo.h
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** brief The application entry point.* retval int*/
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_USART1_UART_Init();MX_TIM1_Init();/* USER CODE BEGIN 2 */HAL_TIM_Base_Start_IT(htim1);printf(heihei\r\n);task_run();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** brief System Clock Configuration* retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct {0};RCC_ClkInitTypeDef RCC_ClkInitStruct {0};/** Configure the main internal regulator output voltage*/__HAL_RCC_PWR_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM 25;RCC_OscInitStruct.PLL.PLLN 168;RCC_OscInitStruct.PLL.PLLP RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ 4;if (HAL_RCC_OscConfig(RCC_OscInitStruct) ! HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(RCC_ClkInitStruct, FLASH_LATENCY_2) ! HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** brief This function is executed in case of error occurrence.* retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef USE_FULL_ASSERT
/*** brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* param file: pointer to the source file name* param line: assert_param error line source number* retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf(Wrong parameters value: file %s on line %d\r\n, file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */分别添加以下6个文件list.c、list.h、task_demo.c、task_demo.h、timeslice.c、timeslice.h。同时把timslice目录下的.h文件包含进项目中来如下所示 注意keil上需要勾选Use MicroLIB否则CubeMX生成的串口工程无法打印问题 四、运行结果 五、代码解释
时间片轮询架构
其实该部分主要使用了面向对象的思维使用结构体作为对象并使用结构体指针作为参数传递这样作可以节省资源并且有着极高的运行效率。
其中最难的部分是侵入式链表的使用这种链表在一些操作系统内核中使用十分广泛这里是参考RT-Thread实时操作系统中的侵入式链表实现。底层侵入式双向链表
该链表是linux内核中使用十分广泛也十分经典其原理具体可以参考文章
https://www.cnblogs.com/skywang12345/p/3562146.html 六、总结 好了终于介绍完毕以后裸机开发有了此时间片论法如虎添翼。感谢各位同仁参阅。
参考文章
1、单片机面向对象思维的架构时间轮片法_strongerHuang的博客-CSDN博客
2、【嵌入式开源库】timeslice的使用完全解耦的时间片轮询框架构-CSDN博客