您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center 汽车系统工程   模型库  
会员   
   
软件架构设计方法、案例与实践
10月15日-16日 北京+线上
车载系统功能开发方法与实践
10月25日-26日 北京+线上
SysML和EA进行系统设计与建模
11月19-20日 北京+线上
     
   
 订阅
嵌入式系统5大状态机设计模式
 
作者:ylm110
 
  45   次浏览      4 次
 2025-9-30
 
编辑推荐:
本文主要介绍了 本文介绍了状态机核心要素、五大实现模式及代码示例,还给出模式选择建议,助力开发者高效打造可靠嵌入式系统相关内容。 希望对您的学习有所帮助。
本文来自于微信公众号嵌入式老杨,由火龙果软件Linda编辑、推荐。

“ 状态机是嵌入式系统开发的关键工具,能将复杂逻辑拆解为清晰的状态与转移规则。本文介绍其核心要素、五大实现模式及代码示例,还给出模式选择建议,助力开发者高效打造可靠嵌入式系统。”

01状态机简介

状态机是一种描述系统在不同状态之间转换行为的数学模型或设计模式,它通过定义有限的状态集合以及状态之间的转移规则,使复杂系统行为变得清晰可控。在嵌入式系统设计中,掌握状态机的核心要素是成功实现的基础。

状态机包含以下四个核心要素:

状态(State):

系统在某一时刻的稳定工作模式或行为阶段。任何时刻系统只能处于一个状态,如嵌入式设备的"待机"、"运行"、"故障"、"休眠"等状态。每个状态对应特定的行为或功能。

事件(Event):

触发状态转换的外部或内部信号,但需要明确的是,只有带特定触发条件的有效信号才构成事件。例如:"按钮按下"(而非所有按钮信号)、"传感器数据变化超过阈值"(而非所有数据变化)、"定时器超时"等。事件是状态转换的催化剂,决定了系统如何从一个状态迁移到另一个状态。

动作(Action):

在状态转换过程中或处于特定状态时执行的操作。动作可分为进入动作(进入状态时执行)、退出动作(离开状态时执行)和状态内动作(在状态持续期间执行)。

状态转移(Transition):

因事件发生而导致从一个状态切换到另一个状态的过程,遵循预定义的转换规则。状态转移规则需满足"当前状态 + 触发事件 + 可选条件 → 下一状态 + 关联动作"的完整表达式,例如:"空闲态 + 按键按下事件 + 按键持续时间≥10ms(消抖后)→ 采样态 + 初始化 ADC 动作"。

状态机主要分为摩尔型(Moore Machine)和米利型(Mealy Machine):

摩尔型的输出只由当前状态决定,比如交通灯 “红灯状态” 固定输出禁止通行信号、“绿灯状态” 固定输出允许通行信号,输出逻辑稳定;米利型的输出由当前状态和输入事件共同决定,比如自动售货机 “待付款状态” 下,投入足额钱币输出出货信号,投入不足则输出提示补款信号,同一状态因事件不同有不同输出,适配动态需求。

02嵌入式状态机的常见实现模式

嵌入式系统状态机的实现模式多样,每种模式都有其适用的场景和特点。以下是五种主流的实现模式:

1.Switch-Case 语句法

通过枚举类型定义所有状态,在大的switch语句中根据当前状态和事件进行分支处理。这是最基础直观的实现方式,适合状态数量少、逻辑简单的场景。其优点是实现简单、代码直白,易于理解;缺点是所有状态和转换逻辑堆叠在一起,可维护性和扩展性较差。

2.状态表驱动法

使用预定义的结构体数组(状态表)描述状态转换规则,每个表项包含"现态、事件、次态、执行动作"。这种方法将数据(转换规则)与逻辑(执行代码)分离,结构清晰,扩展性较好。缺点是需要额外存储状态表,如果状态或事件非常多,表可能会变大。

3.函数指针法

每个状态用独立函数表示,函数内部处理所有可能事件并负责状态转换(通过改变全局或上下文中的函数指针)。这种方法的优点是高内聚,每个状态的行为被封装在各自的函数中,结构模块化程度高;缺点是函数指针的使用需要谨慎,否则可能影响代码可读性。

4.面向对象的状态模式

对于支持C++的嵌入式系统,可采用面向对象的设计模式。定义一个抽象状态基类(接口),为每个具体状态创建一个派生类,实现特定行为。上下文类(Context)持有指向当前状态对象的指针。这种模式的优点是符合开闭原则,添加新状态无需修改已有代码,封装性好;缺点是需要C++支持,每个状态都是一个类实例,会引入一定的内存和运行时开销。

5.分层状态机(HSM)

支持状态嵌套管理复杂逻辑,允许状态具备父子关系,子状态可以继承父状态的行为和转换。这种模式简化了复杂状态系统的管理,提高了复用性,特别适用于非常复杂的系统。

03状态机代码实现

1 Switch-Case语句

以下代码实现了一个按键消抖状态机,通过 KEY_IDLE(空闲)、KEY_DEBOUNCE(消抖)、KEY_PRESSED(按下)、KEY_RELEASE(释放)四个状态,完成按键按下检测、20ms 消抖、LED 控制及按键时长计算功能,主循环每 10ms 轮询一次状态机。


#include "stm32f1xx_hal.h"#include <stdio.h>
// 引脚定义#define KEY_PIN GPIO_PIN_0#define KEY_PORT
GPIOA#define LED_PIN GPIO_PIN_13#define LED_PORT GPIOC
// 状态定义typedef enum {
   KEY_IDLE, // 按键空闲状态
   KEY_DEBOUNCE, // 按键消抖状态
   KEY_PRESSED, // 按键按下状态
   KEY_RELEASE // 按键释放状态
} KeyState_t;
// 全局变量
KeyState_t key_state = KEY_IDLE;uint32_t debounce_time
= 0;uint32_t key_press_duration = 0;
// 函数声明void SystemClock_Config(void);void MX_GPIO_
Init(void);void Error_Handler(void);
// 实际按键读取函数(STM32 HAL库)int is_key_down(void) {
   return (HAL_GPIO_ReadPin(KEY_PORT, KEY_PIN) ==
GPIO_PIN_RESET) ? 1 : 0;
}
// 实际系统时间函数(STM32 HAL库)uint32_t get_millis(void) {
   return HAL_GetTick();
}
// 按键按下处理函数void on_key_pressed(void) {
   printf("Key pressed!\n");
   HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET);
}
// 按键释放处理函数void on_key_released(void) {
   printf("Key released! Duration: %lums\n", key_press_duration);
   HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);
   key_press_duration = 0;
}
// 状态机处理函数void key_fsm(void) {
   switch (key_state) {
      case KEY_IDLE:
          if (is_key_down()) {
             key_state = KEY_DEBOUNCE;
            debounce_time = get_millis();
            printf("State: IDLE -> DEBOUNCE\n");
         }
break;

      case KEY_DEBOUNCE:
          if (get_millis() - debounce_time > 20) {
            if (is_key_down()) {
               key_state = KEY_PRESSED;
               on_key_pressed();
               printf("State: DEBOUNCE -> PRESSED\n");
          } else {
                key_state = KEY_IDLE;
                printf("State: DEBOUNCE -> IDLE\n");
          }
       }
       break;

   case KEY_PRESSED:
       key_press_duration = get_millis() - debounce_time;
       if (!is_key_down()) {
         key_state = KEY_RELEASE;
          printf("State: PRESSED -> RELEASE\n");
       }
       break;

case KEY_RELEASE:
       on_key_released();
       key_state = KEY_IDLE;
      printf("State: RELEASE -> IDLE\n");
       break;

   default:
       // 处理未知状态,增强鲁棒性
      key_state = KEY_IDLE;
       printf("Unknown state! Reset to IDLE\n");
       break;
   }
}
// 主函数int main(void) {
    // 初始化
    ......

   printf("Starting key state machine demo...\n");

   while (1) {
      key_fsm();
       HAL_Delay(10); // 10ms延时,降低CPU占用
    }

   return 0;
}

以上代码状态转移图如下所示:

2 状态表驱动法

以下代码定义了 STATE_A、STATE_B、STATE_C 三个状态和 EVENT_X、EVENT_Y、EVENT_Z 三个事件,通过状态表指定不同状态下接收事件后的跳转目标及执行动作,包含边界检查处理非法状态或事件(复位至 STATE_A)。主函数模拟事件序列测试状态机流转。

#include <stdio.h>#include <stdint.h>
// 状态和事件定义(指定uint8_t类型节省内存)typedef enum : uint8_t {
   STATE_A,
   STATE_B,
   STATE_C,
   STATE_COUNT
} State;
typedef enum : uint8_t {
   EVENT_X,
   EVENT_Y,
   EVENT_Z,
   EVENT_COUNT
} Event;
// 状态表项结构typedef struct {
   State next_state;
   void (*action)(void);
} TransitionEntry;
// 动作函数void action_A_to_B(void) { printf("Transition from A to B\n");
}void action_A_to_C(void) { printf("Transition from A to C\n");
}void action_B_to_A(void)
{ printf("Transition from B to A\n"); }void action_B_to_C(void) { printf
("Transition from B to C\n"); }void action_C_to_A(void) { printf
("Transition from C to A\n"); }void action_C_to_B(void) { printf
("Transition from C to B\n"); }void action_no_op(void) { /* 无操作 */ }
void action_error(void) { printf("Error: Invalid state/event!\n"); }
// 状态表定义const TransitionEntry state_table
[STATE_COUNT][EVENT_COUNT] = {
   [STATE_A] = {
      [EVENT_X] = { .next_state = STATE_B, .action = action_A_to_B },
      [EVENT_Y] = { .next_state = STATE_C, .action = action_A_to_C },
      [EVENT_Z] = { .next_state = STATE_A, .action = action_no_op }
   },
   [STATE_B] = {
       [EVENT_X] = { .next_state = STATE_A, .action = action_B_to_A },
      [EVENT_Y] = { .next_state = STATE_C, .action = action_B_to_C },
      [EVENT_Z] = { .next_state = STATE_B, .action = action_no_op }
   },
   [STATE_C] = {
      [EVENT_X] = { .next_state = STATE_A, .action = action_C_to_A },
      [EVENT_Y] = { .next_state = STATE_B, .action = action_C_to_B },
      [EVENT_Z] = { .next_state = STATE_C, .action = action_no_op }
   }
};
// 当前状态
State current_state = STATE_A;
    // 事件处理函数(含边界检查)void process_event(Event event) {
// 边界检查:防止数组越界
   if (current_state >= STATE_COUNT || event >= EVENT_COUNT) {
      action_error();
      current_state = STATE_A; // 复位到初始状态
      return;
   }

   TransitionEntry entry = state_table[current_state][event];

   if (entry.action != NULL) {
       entry.action();
   }

   current_state = entry.next_state;
    printf("Current state: %d\n", current_state);
}
// 主函数int main(void) {
   printf("Starting state table demo...\n");
   printf("Initial state: %d\n", current_state);

    // 模拟事件序列
   Event events[] = { EVENT_X, EVENT_Y,
EVENT_Z, EVENT_X, 5 }; // 最后一个非法事件测试

    for (int i = 0; i < sizeof(events)/sizeof(events[0]); i++) {
       printf("Processing event: %d\n", events[i]);
      process_event(events[i]);
   }

    return 0;
}

以上代码状态转移图如下所示:

3 函数指针法

以下代码通过函数指针实现了一个 LED 状态机,包含 STATE_OFF(关闭)和 STATE_ON(开启)两个状态,可响应 EVT_BUTTON(按键)和 EVT_TIMEOUT(超时)事件:初始为关闭状态,按键事件触发 LED 点亮并切换到开启状态;开启状态下,按键或超时事件均触发 LED 熄灭并返回关闭状态,还包含空指针异常处理(复位至关闭状态)。主函数模拟事件序列测试状态机流转。

#include <stdio.h>#include <stdint.h>
// 事件类型定义typedef enum { EVT_BUTTON,
EVT_TIMEOUT, EVT_MAX } EventType;
// 状态函数原型typedef void (*state_handler_t)(EventType evt);
// 状态函数声明void state_off(EventType evt);void
state_on(EventType evt);void handle_error(void);
// 全局变量state_handler_t current_state = &state_off;uint32_t light_on_time = 0;
// 动作函数void turn_led_on(void) { printf("LED turned ON\n"); }
void turn_led_off(void) { printf("LED turned OFF\n"); }void handle_error(void)
{ printf("Error handled\n"); }
// 状态函数实现void state_off(EventType evt) {
   switch (evt) {
      case EVT_BUTTON:
         turn_led_on();
         current_state = &state_on;
          light_on_time = 0;
         printf("State: OFF -> ON\n");
         break;
      default:
          printf("State OFF: Ignored event %d\n", evt);
         break;
   }
}
void state_on(EventType evt) {
   switch (evt) {
      case EVT_BUTTON:
         turn_led_off();
         current_state = &state_off;
         printf("State: ON -> OFF\n");
          break;
       case EVT_TIMEOUT:
         turn_led_off();
         current_state = &state_off;
          printf("State: ON -> OFF (Timeout)\n");
         break;
      default:
         printf("State ON: Ignored event %d\n", evt);
          break;
   }
}
// 状态机执行函数(含空指针检查)void state_machine_run(EventType evt) {
   if (current_state != NULL) {
      current_state(evt);
    } else {
      // 处理空指针异常
      handle_error();
      current_state = &state_off; // 复位到初始状态
   }
}
// 模拟事件生成
EventType get_next_event(void) {
   static int count = 0;
   EventType events[] = { EVT_BUTTON,
EVT_TIMEOUT, EVT_BUTTON, EVT_BUTTON };
   return events[count++ % 4];
}
// 主函数int main(void) {
    printf("Starting function pointer state machine demo...\n");

   // 模拟运行
    for (int i = 0; i < 5; i++) {
       EventType evt = get_next_event();
       printf("Processing event: %d\n", evt);
      state_machine_run(evt);

      // 模拟延时
       for (int j = 0; j < 1000000; j++);
    }

    // 测试空指针恢复
    printf("\nTesting error recovery...\n");
   current_state = NULL;
    state_machine_run(EVT_BUTTON);

   return 0;
}

以上代码状态转移图如下所示:

4 面向对象的状态模式

以下代码采用面向对象的状态模式,定义了State抽象接口及OffState(关闭)、OnState(开启)具体状态类,通过Context上下文类管理当前状态。调用Context的request方法时,会触发当前状态的handle方法,实现状态间(关闭→开启→关闭循环)的切换并输出状态信息。

#include <iostream>
// 状态接口class State {public:
virtual void handle(class Context* context) = 0;
virtual ~State() {}
};
// 具体状态类:关闭状态class OffState : public State {public:
void handle(Context* context) override;
};
// 具体状态类:开启状态class OnState : public State {public:
void handle(Context* context) override;
};
// 上下文类class Context {private:
    State* current_state_;
   public:
   Context() : current_state_(new OffState()) {}
    ~Context() {
      delete current_state_; // 手动释放内存
    }

    void set_state(State* new_state) {
      if (current_state_ != nullptr)
         delete current_state_;
       current_state_ = new_state;
    }

   void request() {
       if (current_state_ != nullptr) {
         current_state_->handle(this);
       }
    }

   void display_state(const std::string& state_name) {
      std::cout << "Current state: " << state_name << std::endl;
   }
};
// 状态处理实现void OffState::handle(Context* context) {
    context->display_state("Off");
    std::cout << "Switching to On state" << std::endl;
   context->set_state(new OnState());
}
void OnState::handle(Context* context) {
   context->display_state("On");
    std::cout << "Switching to Off    state" << std::endl;
   context->set_state(new OffState());
}
// 主函数int main() {
    std::cout << "Starting object-oriented state pattern demo..." << std::endl;

   Context context;

   // 模拟几次状态转换
    for (int i = 0; i < 3; i++) {
       context.request();
   }

   return 0;
}

以上代码状态转移图如下所示:

5 分层状态机

以下代码实现了分层状态机,有根状态、开 / 关状态及开的普通 / 高亮子状态,通过hsm_dispatch_event函数让父状态优先处理事件并递归传递,响应按键按下、长按等事件实现状态跳转,主函数模拟事件序列测试状态流转。

#include <stdio.h>#include <stdint.h>
// 状态定义typedef enum {
   STATE_ROOT,
   STATE_ON,
   STATE_OFF,
   STATE_ON_NORMAL,
   STATE_ON_BRIGHT,
   STATE_COUNT
} StateType;
// 事件定义typedef enum {
   EVT_BUTTON_PRESS,
   EVT_BUTTON_LONG_PRESS,
   EVT_TIMEOUT,
   EVT_MAX
} EventType;
// 状态处理函数原型typedef StateType (*state_handler_t)(EventType evt);
// 定义父-子状态映射表(明确层级关系)const
StateType parent_state_map[STATE_COUNT] = {
   [STATE_ROOT] = STATE_ROOT, // 根状态无父状态
   [STATE_ON] = STATE_ROOT, // ON的父状态是根
   [STATE_OFF] = STATE_ROOT, // OFF的父状态是根
   [STATE_ON_NORMAL] = STATE_ON, // NORMAL的父状态是ON
   [STATE_ON_BRIGHT] = STATE_ON // BRIGHT的父状态是ON
};
// 状态处理函数
StateType root_state(EventType evt) {
    printf("Root state handling event: %d\n", evt);
    return STATE_ROOT; // 保持当前状态
}

StateType on_state(EventType evt) {
   switch (evt) {
      case EVT_BUTTON_PRESS:
          printf("On state: Button press -> switching to Off\n");
         return STATE_OFF;
       case EVT_BUTTON_LONG_PRESS:
          printf("On state: Long press -> entering brightness mode\n");
         return STATE_ON;
       default:
         printf("On state: Passing event to root\n");
          return STATE_ON; // 保持当前状态
   }
}

StateType off_state(EventType evt) {
   switch (evt) {
      case EVT_BUTTON_PRESS:
         printf("Off state: Button press -> switching to On\n");
         return STATE_ON;
      default:
          printf("Off state: Passing event to root\n");
         return STATE_OFF; // 保持当前状态
   }
}

StateType on_normal_state(EventType evt) {
   switch (evt) {
      case EVT_BUTTON_LONG_PRESS:
      nbsp;  printf("Normal mode: Long press -> switching to Bright mode\n");
   ;   return STATE_ON_BRIGHT;
      default:
   nbsp;     // 无需处理,事件将传递给父状态
   return STATE_ON_NORMAL;
   }

StateType on_bright_state(EventType evt) {
    switch (evt) {
       case EVT_BUTTON_LONG_PRESS:
         printf("Bright mode: Long press -> switching to Normal mode\n");
         return STATE_ON_NORMAL;
      default:
         // 无需处理,事件将传递给父状态
         return STATE_ON_BRIGHT;
    }
}
// 状态表state_handler_t state_table[STATE_COUNT] = {
   [STATE_ROOT] = root_state,
   [STATE_ON] = on_state,
   [STATE_OFF] = off_state,
   [STATE_ON_NORMAL] = on_normal_state,
   [STATE_ON_BRIGHT] = on_bright_state
};
   // 事件传递函数(父状态优先处理,递归传递)
void hsm_dispatch_event(StateType* current_state, EventType evt) {
// 1. 先调用当前状态的处理函数,获取新状态
   StateType new_state = state_table[*current_state](evt);

// 2. 更新当前状态
*current_state = new_state;

// 3. 若当前状态不是根状态,传递给父状态
    StateType parent = parent_state_map[*current_state];
   if (parent != *current_state) { // 避免根状态递归
      hsm_dispatch_event(&parent, evt);
   }
}
// 状态机上下文typedef struct {
   StateType current_state;
    uint32_t timer;
} StateMachine;
// 主函数int main(void) {
   printf("Starting hierarchical state machine demo...\n");

   StateMachine fsm = { .current_state = STATE_OFF };

   // 测试事件序列
   EventType events[] =
{ EVT_BUTTON_PRESS,
EVT_BUTTON_LONG_PRESS, EVT_BUTTON_PRESS };

   for (int i = 0; i < sizeof(events)/sizeof(events[0]); i++) {
       printf("\nProcessing event: %d\n", events[i]);
       hsm_dispatch_event(&fsm.current_state, events[i]);
      printf("Final state after event: %d\n", fsm.current_state);
   }

    return 0;
}

以上代码状态转移图如下所示:

04如何选择状态机实现模式

选择合适的状态机实现模式需要综合考虑系统复杂度、资源约束、开发团队技能和长期维护需求。以下是关键选择因素:

考量因素 推荐模式 原因与细节说明
系统复杂度 简单系统: Switch-Case法 状态数量少(≤3个),事件数量少(≤2个),逻辑简单,变动少
中等复杂度: 状态表驱动法/函数指针法 状态和事件较多(状态数×事件数≤32),规则明确,需要较好扩展性
复杂系统: 面向对象模式/分层状态机 状态和事件多(状态数×事件数>32),有层次化需求,需要高维护性和扩展性
资源约束 极度受限: Switch-Case法 内存极度有限(<1KB RAM),执行效率要求高
资源适中: 状态表驱动法/函数指针法 内存适中(1-4KB RAM),状态表内存开销可接受(状态/事件少时)
资源丰富: 面向对象模式 内存充足(>4KB RAM),可接受面向对象的开销
实时性要求 高实时性: Switch-Case法/函数指针法 执行效率高,时间可预测
一般实时性: 状态表驱动法 查表操作带来轻微开销
软实时: 面向对象模式 虚函数调用带来一定开销
团队技能 C语言为主: Switch-Case/状态表 团队熟悉C语言,嵌入式经验丰富
C++熟练: 面向对象模式 团队熟练掌握C++和面向对象设计
长期维护 变化少: Switch-Case法 需求稳定,后期变动可能性小
频繁变更: 状态表驱动法/面向对象模式 需要频繁添加新状态或修改转换规则

1 通信机制选择

状态机需要与外部环境通信,常见通信机制有:

轮询:

持续检查条件或标志位,实现简单但CPU占用高,适合简单系统(无RTOS,主循环轮询)。

事件触发:

通过中断或回调异步通知,响应快资源占用低,适合事件驱动系统(如中断触发状态转换)。

阻塞等待:

线程阻塞等待事件发生,节省CPU但可能引入线程切换开销,适合多线程IO操作(需RTOS支持)。

消息队列:

通过线程安全队列进行异步通信,解耦生产消费双方,适合多任务环境(复杂系统,多事件源)。

2.不同状态机模式与通信机制的适配:

Switch-Case/函数指针法:

中断服务函数(ISR)中仅"标记事件标志位",主循环中检查标志位并调用状态机处理。

状态表驱动法:

ISR中"将事件加入事件队列",主循环中从队列取出事件并匹配状态表。

面向对象模式:

ISR中"调用Context的事件入队接口",主循环中调用context->request()处理事件。

05总结

状态机模式是嵌入式系统开发的强大工具,能够将复杂逻辑分解为有限状态和明确转移规则,显著提升代码可读性和可维护性。根据实际项目需求选择合适模式至关重要:

简单系统(状态少、逻辑简单、变动少):优先选择Switch-Case语句法,实现简单直观,资源占用少。

中等复杂度系统(状态和事件较多,规则明确):推荐状态表驱动法或函数指针状态法,平衡复杂度和性能,易于扩展。

复杂系统(C++环境,高可维护性要求):选择面向对象状态模式或分层状态机,虽然资源开销较大,但提供了最好的封装性和扩展性。

多任务环境:采用消息队列机制,结合RTOS实现任务间通信。

   
45   次浏览       4 次
 
相关文章

CMM之后对CMMI的思考
对软件研发项目管理的深入探讨
软件过程改进
软件过程改进的实现
 
相关文档

软件过程改进框架
软件过程改进的CMM-TSP-PSP模型
过程塑造(小型软件团队过程改进)
软件过程改进:经验和教训
 
相关课程

以"我"为中心的过程改进(iProcess )
iProcess过程改进实践
CMMI体系与实践
基于CMMI标准的软件质量保证

最新活动计划
软件架构设计方法、案例实践 10-15[北京]
数据架构、数据治理数据运营 10-17[北京]
车载系统功能开发方法与实践 10-25[北京]
SysML和EA系统设计与建模 11-19[北京]
AI辅助软件测试方法与实践 10-26[北京]
OCSMP 认证培训课程 11-18[北京]
 
 
最新文章
iPerson的过程观:要 过程 or 结果
基于模型的需求管理方法与工具
敏捷产品管理之 Story
敏捷开发需求管理(产品backlog)
Kanban看板管理实践精要
最新课程
基于iProcess的敏捷过程
软件开发过程中的项目管理
持续集成与敏捷开发
敏捷过程实践
敏捷测试-简单而可行
更多...   
成功案例
英特尔 SCRUM-敏捷开发实战
某著名汽车 敏捷开发过程与管理实践
北京 敏捷开发过程与项目管理
东方证券 基于看板的敏捷方法实践
亚信 工作量估算
更多...