-------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
#ifndef _countof #define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0])) #endif #ifndef NULL #define NULL 0 #endifsys.timer.c中的调度模块:
#include <avr/interrupt.h>
#include "Drv_Timer.h"
#include "sys_timer.h"
typedef void(*p_task_funtion)(void);
typedef struct 
{
    uint8_t delay;          // 任务延时计数
    uint8_t period;         // 任务运行间隔
    p_task_funtion task;    // 任务函数
}T_sys_task, *pT_sys_task;
// 这个数组用来注册和管理任务队列
static T_sys_task sys_task_ctrl[10];
static pT_sys_task p_sys_task_ctrl = sys_task_ctrl;
// ==========================================================================================================
// 初始化系统任务队列
// 
// ==========================================================================================================
void sys_task_init(void)
{
    uint8_t index = 0;
    for(index = 0; index < _countof(sys_task_ctrl); index++)
    {
        (p_sys_task_ctrl + index)->delay  = 0;
        (p_sys_task_ctrl + index)->period = 0;
        (p_sys_task_ctrl + index)->task   = NULL;
    }
}
// ==========================================================================================================
// 添加任务到任务队列
// 
// ==========================================================================================================
void sys_task_add(uint8_t delay, uint8_t period, p_task_funtion task)
{
    uint8_t index = 0;
    for(index = 0; index < _countof(sys_task_ctrl); index++)
    {
        if(NULL == (p_sys_task_ctrl + index)->task) { break; }
    }
    if(index >= _countof(sys_task_ctrl)) { return; }
    (p_sys_task_ctrl + index)->delay  = delay;
    (p_sys_task_ctrl + index)->period = period - 1;
    (p_sys_task_ctrl + index)->task   = task;
}
// ==========================================================================================================
//      系统任务定时器
// 
// (1). 使用Timer0的OCF0中断产生1ms的时标
// 
// ==========================================================================================================
void sys_timer_init(void)
{
    // 定时器0初始化:CTC模式、OC0引脚不连接、64预分频
    Drv_Timer0_init(T0_WGM_CTC, COM_MODE_NONE, T0_CLK_SOURCE_CLK_64);
    // 设置初值:TCNT0=0、OCR0=122
    Drv_Timer0_set_TCNT0_OCR0(0, 122);
    // 使能OCF0中断
    Drv_Timer0_INT_Enable(INT_MODE_OCF, ENABLE);
}
// ==========================================================================================================
//      系统定时器中断(中断周期=1ms)
// 
// (1). 使用Timer0的CTC中断调度各个任务
// (2). sys_task_add中将delay初始化为0,意味着第1次进入这个中断、就会执行这个任务
// 
// ==========================================================================================================
volatile uint8_t temp2016; // 调试用
ISR(TIMER0_COMP_vect)
{
    uint8_t index = 0;
    for(index = 0; index < _countof(sys_task_ctrl); index++)
    {
        temp2016 = index;
        if(NULL != (p_sys_task_ctrl + index)->task)
        {
            if(0 == (p_sys_task_ctrl + index)->delay)
            {
                (p_sys_task_ctrl + index)->delay = (p_sys_task_ctrl + index)->period;
                (p_sys_task_ctrl + index)->task();
            }
            else
            {
                (p_sys_task_ctrl + index)->delay--;
            }
        }
    }
}Mod_LED_display.c中的数码管任务:// ==========================================================================================================
//      LED数码管显示数据的刷新
// 
// (1). 在系统定时器中定时刷新
// 
// ==========================================================================================================
void Mod_LED_display_update(void)
{
    PORTD ^= (1 << PD0);  // 运行时刻标记
    // 熄灭当前数码管、并保持3个时钟周期的熄灭,用来避免余晖
    *p_LED_display_ctrl->seg_code = segment_code[_countof(segment_code) - 1];
    // 切换到下1个数码管
    p_LED_display_ctrl->index++;
    if(p_LED_display_ctrl->index > (_countof(segment_index) - 1))
    {
        p_LED_display_ctrl->index = 0;
    }
    // 修改位选、修改显示
    *p_LED_display_ctrl->seg_index |= segment_index[_countof(segment_index) - 1];
    *p_LED_display_ctrl->seg_index &= segment_index[p_LED_display_ctrl->index];
    *p_LED_display_ctrl->seg_code   = segment_code[p_LED_display_ctrl->data[segment_index[p_LED_display_ctrl->index]]];
}main.c中初始化3个任务:// ==========================================================================================================
// 主函数
// ==========================================================================================================
#include <avr/io.h>
#include "Mod_LED_Displayer.h"
#include "sys_timer.h"
#include "system.h"
#include "config.h"
void Mod_test01(void)
{
    PORTD ^= (1 << PD1);  // 运行时刻标记
}
void Mod_test02(void)
{
    PORTD ^= (1 << PD2);  // 运行时刻标记
}
// ==========================================================================================================
// main函数
// ==========================================================================================================
int main(void)
{
    // ------------------------------------------------------------------------------------------------------
    // 关全局中断
    cli();
    // 系统初始化
    sys_init();
    // 开全局中断
    sei();
    // PD[2:0]初始化为输出0  
    DDRD  |=   (1 << DDD0) | (1 << DDD1) | (1 << DDD2);  
    PORTD &= ~((1 << PD0 ) | (1 << PD1 ) | (1 << PD2 ));
    // 注册3个任务
    sys_task_add(0, 3, Mod_LED_display_update);  // 从时刻0开始运行,以后每隔3个时刻运行一次(1个时刻是1ms)
    sys_task_add(1, 3, Mod_test01);              // 从时刻1开始运行,...
    sys_task_add(2, 3, Mod_test02);              // 从时刻2开始运行,...
    // CPU数值计算
    Mod_LED_display(123456789);
    // ------------------------------------------------------------------------------------------------------
    while(1)
    {
    }
    return 0;
}
// ==========================================================================================================
//      LED数码管显示数据的刷新
// 
// (1). 在系统定时器中定时刷新
// 
// ==========================================================================================================
void Mod_LED_display_update(void)
{
    PORTD |= (1 << PD0);  // 运行时刻标记
    // 熄灭当前数码管、并保持3个时钟周期的熄灭,用来避免余晖
    *p_LED_display_ctrl->seg_code = segment_code[_countof(segment_code) - 1];
    // 切换到下1个数码管
    p_LED_display_ctrl->index++;
    if(p_LED_display_ctrl->index > (_countof(segment_index) - 1))
    {
        p_LED_display_ctrl->index = 0;
    }
    // 修改位选、修改显示
    *p_LED_display_ctrl->seg_index |= segment_index[_countof(segment_index) - 1];
    *p_LED_display_ctrl->seg_index &= segment_index[p_LED_display_ctrl->index];
    *p_LED_display_ctrl->seg_code   = segment_code[p_LED_display_ctrl->data[segment_index[p_LED_display_ctrl->index]]];
    PORTD &= ~(1 << PD0);  // 运行时刻标记
}      任务1开始时PD0为高电平,任务1结束后PD0为低电平,也就是说、PD0的高电平时间就是任务1消耗的时间。原文:http://blog.csdn.net/manon_des_source/article/details/51811758