一、
二、代码
/*
STM32F407ZGT6
168MHz
Flash size 1024Kbytes
RAM size 192KB
*/
#include "main.h"
#include <string.h>
#include "systick.h"
#include "usart1.h"
#include "timer2.h"
#include "led.h"
#include "key.h"
/*
整个系统的代码由一个计时器timer2中断发动,timer2 就像是一个发动机,
每隔一定的周期发动一次中断,利用这一个中断的时间去对指定任务的时间
片减1,在主循环中一直遍历系统中所有任务的时间片,如果时间片耗尽了,
则执行该任务。
*/
void task_1(void);
void task_2(void);
void task_3(void);
void task_process(void);
void task_timer(void);
typedef struct{
void (*task)(void);//要执行的任务
uint8_t task_run_flag; //任务运行标志,0不运行 1运行
uint32_t task_time_run; //设置任务运行间隔时间ms
uint32_t task_time_cnt; //运行计时
}task_t;
uint8_t TASK_NUM = 3;
static task_t My_Task[]={
{task_1,0,500,0},
{task_2,0,1000,0},
{task_3,0,2000,0}
};
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
sys_tick_init();
timer2_init();
usart1_init(115200);
led_init();
key_init();
KEY0_FLAG = 0;
TIMER2_TICK = 0;
task_timer2_callback = task_timer;
//初始化时间
for(int i=0;i<TASK_NUM;i++)
{
My_Task[i].task_time_cnt = My_Task[i].task_time_run;
}
while (1)
{
task_process();
}
}
void task_process(void)
{
for(int i=0;i<TASK_NUM;i++)
{
if(My_Task[i].task_run_flag == 1)
{
(My_Task[i].task)();//调用任务函数
My_Task[i].task_run_flag = 0;
}
}
}
void task_timer(void)
{
for(int i=0;i<TASK_NUM;i++)
{
My_Task[i].task_time_cnt--;
if(My_Task[i].task_time_cnt == 0)
{
My_Task[i].task_time_cnt = My_Task[i].task_time_run;//重新赋值
My_Task[i].task_run_flag = 1;
}
}
}
void task_1(void)
{
printf("task_1\n");
}
void task_2(void)
{
printf("task_2\n");
}
void task_3(void)
{
printf("task_3\n");
}
timer2
#ifndef TIMER2_H
#define TIMER2_H
#include "stm32f4xx.h" // Device header
/*
通用定时器用法
TIM2
PA0 TIM2_CH1_ETR
PA5 TIM2_CH1_ETR
外部触发输入(ETR),仅适用于 TIM2、 TIM3、 TIM4
串口使用
Tout =((arr+1)*(psc+1))/Tclk
Tout:定时器溢出的时间(单位us)
arr:重装载值,当计数达到重装载寄存器设置的数字后产生更新事件,并清零从头开始计数。
psc:时钟预分频数
Tclk:定时器工作频率,单位MHz
arr = 100 - 1
psc = 84 - 1
Tclk = 84MHz 定时器时钟84M
Tout =((arr+1)*(psc+1))/Tclk
Tout = 100*84/84 = 100 us = 0.1 ms
*/
//函数指针
typedef void (*timer2_callback)();
extern timer2_callback task_timer2_callback;
extern uint64_t TIMER2_TICK;//计数
void timer2_init(void);
#endif
#include "timer2.h"
#include "usart1.h"
#include "usart2_timer.h"
timer2_callback task_timer2_callback;
uint64_t TIMER2_TICK = 0;
void timer2_init()
{
//从数据手册19/203页时钟树可以知道 APB2 84MHz,APB1 42MHz
//时钟树上分析实际应该是APB1 * 2 = 84MHz APB2*2 = 168MHz
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
//定时器初始化
//Tout =((arr+1)*(psc+1))/Tclk
//Tout 定时器溢出的时间(单位us)
//Tclk 定时器的输入时钟频率(MHz),定时器时钟源,这里是84MHz
uint32_t arr = 1000 - 1;
uint16_t psc = 84 - 1; //Tout=(100*84)/84 = 1000 us = 1 ms 溢出中断一次
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = arr; //重装载值,当定时器的计数值达到这个值,定时器会重新装载
TIM_TimeBaseStructure.TIM_Prescaler = psc; //预分频值,1-65536之间任意分频,设置了用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //系统时钟分频器 TIM_CKD_DIV1=0;TIM_CKD_DIV2=256;TIM_CKD_DIV4=512
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
//中断优先级NVIC设置
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_ClearFlag(TIM2, TIM_FLAG_Update); // 清除溢出中断标志
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); //使能指定的TIM2中断,允许更新中断
TIM_Cmd(TIM2, ENABLE); //使能TIMx
}
//定时器中断服务程序
void TIM2_IRQHandler(void)
{
//TIM更新溢出中断发生
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIMER2_TICK++;
usart1_timer_handle();
usart2_timer_handle();
task_timer2_callback();
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update ); //清除TIMx更新中断标志
}