一.分时复用简介
单片机中的分时复用也被称为前后台系统。分时复用是一种资源共享的方法,可以用来处理多个任务或事件。分时复用通过时间分割的方式,将总的时间划分为多个小的时间段,每个时间段称为一个时间片。然后,系统按照一定的规则将这些时间片分配给不同的任务或事件。在实际工程中,我们将每一个模块视作一个任务,分时复用将这些任务轮询执行,使得整个工程的逻辑更加明朗,清晰。
二.STM32中的实例(试用HAL库)
1.SysTick(系统滴答定时器)
内核级外设,为单片机提供稳定的时钟基准,
初始化中将SysTick设置为最低优先级,即可以被任一中断打断
2.中断处理函数
当发生由SysTick产生的中断后执行void SysTick_Handler(void)函数。
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
该函数默认的样子,用户可以更具自身需求在其中添加中断后的代码;先讲一下HAL_IncTick();
__weak void HAL_IncTick(void)
{
uwTick += uwTickFreq;
}
这个函数被调用来增加一个全局变量“uwTick”作为应用程序的基准时间。在默认实现中,该变量在SysTick ISR中每隔一毫秒增加一次,即SysTick每一毫秒产生一次中断,在stm32g4xx_hal.c中将将HAL_TICK_FREQ_DEFAULT赋值给uwTickFreq,
uint32_t uwTickFreq = HAL_TICK_FREQ_DEFAULT; /* 1KHz */
而HAL_TICK_FREQ_DEFAULT是一个定义在stm32g4xx_hal.h中的宏
#define HAL_TICK_FREQ_10HZ 100U
#define HAL_TICK_FREQ_100HZ 10U
#define HAL_TICK_FREQ_1KHZ 1U
#define HAL_TICK_FREQ_DEFAULT HAL_TICK_FREQ_1KHZ
因此我们可以将中断时间设置为官方推荐的1ms,10ms,100ms;
在stm32g4xx_it.h中创建两个结构体,分别用来保存对各个任务的扫描时间和执行标志位
struct GLOBALVariable1{
uint8_t LED_Taskflag;
};
struct GLOBALVariable2{
uint8_t LED_Taskflag_count;
};
在stm32g4xx_it.c中定义类型为上述结构体的变量
struct GLOBALVariable1 GLOBAL_TASKFLAG;
struct GLOBALVariable2 GLOBAL_TASKFLAG_Count;
以下为后台逻辑
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
if(GLOBAL_TASKFLAG_Count.LED_Taskflag_count==99) {
GLOBAL_TASKFLAG_Count.LED_Taskflag_count=0;
GLOBAL_TASKFLAG.LED_Taskflag=1;
}
else{
GLOBAL_TASKFLAG_Count.LED_Taskflag_count++;
}
/* USER CODE END SysTick_IRQn 1 */
}
每100毫秒将LED_Taskflag置1,即执行LED任务的标志位
extern struct GLOBALVariable1 GLOBAL_TASKFLAG;
while (1)
{
if(GLOBAL_TASKFLAG.LED_Taskflag)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_8);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
HAL_Delay(500);
GLOBAL_TASKFLAG.LED_Taskflag=0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
在前台中如果LED任务的标志位成立就执行LED相关逻辑函数,之后清0;
以上,为本人对分时复用的一些浅显的认识,文章有任何不足之处还请在评论区指出。