本帖最后由 Eric2013 于 2014-12-15 14:29 编辑
2.4 实验说明 本期教程配套的实验是:基于时间触发的合作式调度器,工程中需要添加如下驱动:
2.4.1 实验一:基于时间触发的合作式调度器实验目的: 1. 学习基于时间触发的合作式调度器。 实验内容: 1. 通过函数SCH_Add_Task添加三个任务 SCH_Add_Task(bsp_KeyScan,1, 10); 按键扫描任务 SCH_Add_Task(AppTask_KeyScan,2, 4); 执行按键打印 SCH_Add_Task(AppTask_LedToggle,3, 500);四个LED灯的闪烁 2. 主程序不断执行SCH_Dispatch_Tasks();刷新函数。 实验现象: 四个LED灯实现每500ms闪烁一次,按下3个按键中的某一个,或者五向摇杆会打印如下信息:
程序设计: 本程序主要分为四个部分: Ø 合作式调度器的设计 Ø 合作式调度器的初始化 Ø 任务API Ø 主程序 下面将这四个部分讲述一下: 1. 合作式调度器的设计 这个已经在前面的1.2小节详细进行了说明,这里就不再赘述了。 2. 合作式调度器的初始化 这里主要是时标间隔的初始化(这个放在了主函数里面实现,也就是嘀嗒定时器的初始化)和任务函数的添加,源代码如下: /* ******************************************************************************************* * 函 数 名: bsp_Init * 功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。 * 只需要调用一次 * 形 参:无 * 返 回 值: 无 ******************************************************************************************* */ void bsp_Init(void) { /* 由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。 启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。 系统时钟缺省配置为168MHz,如果需要更改,可以修改system_stm32f4xx.c 文件 */ bsp_InitLed(); /* 初始LED指示灯端口 */ bsp_InitUart(); /* 初始化串口 */ bsp_InitKey(); /* 初始化按键 */ /* 添加三个任务 */ SCH_Add_Task(bsp_KeyScan, 1,10); SCH_Add_Task(AppTask_KeyScan,2, 4); SCH_Add_Task(AppTask_LedToggle,3, 500); } 3. 任务API 主要是按键任务和LED闪烁任务,按键扫描任务就不说了,这个在前面按键FIFO里面有详细的讲解。 /* ******************************************************************************************* * 函 数 名: AppTask_KeyScan * 功能说明: 打印按键扫描结果 * 形 参:无 * 返 回 值: 无 ******************************************************************************************* */ void AppTask_KeyScan(void) { uint8_t ucKeyCode; ucKeyCode = bsp_GetKey(); /* 读取键值, 无键按下时返回 KEY_NONE = 0 */ if (ucKeyCode != KEY_NONE) { switch (ucKeyCode) { caseKEY_DOWN_K1: /*K1键按下 */ printf("K1键按下, LED1点亮\r\n"); break; caseKEY_UP_K1: /*K1键弹起 */ printf("K1键弹起, LED1熄灭\r\n"); break; caseKEY_DOWN_K2: /*K2键按下 */ printf("K2键按下, LED2点亮\r\n"); break; caseKEY_UP_K2: /*K2键弹起 */ printf("K2键弹起, LED2熄灭\r\n"); break; caseKEY_DOWN_K3: /*K3键按下 */ printf("K3键按下, LED3点亮\r\n"); break; caseKEY_UP_K3: /*K3键弹起 */ printf("K3键弹起, LED3熄灭\r\n"); break; caseJOY_DOWN_U: /* 摇杆UP键按下 */ printf("摇杆上键按下\r\n"); break; caseJOY_DOWN_D: /* 摇杆DOWN键按下 */ printf("摇杆下键按下\r\n"); break; caseJOY_DOWN_L: /* 摇杆LEFT键按下 */ printf("摇杆左键按下\r\n"); break; caseJOY_DOWN_R: /* 摇杆RIGHT键按下 */ printf("摇杆右键按下\r\n"); break; caseJOY_DOWN_OK: /* 摇杆OK键按下 */ printf("摇杆OK键按下\r\n"); break; caseJOY_UP_OK: /*摇杆OK键弹起 */ printf("摇杆OK键弹起\r\n"); break; default: /*其他的键值不处理 */ break; } } } /* ******************************************************************************************* * 函 数 名:AppTask_LedToggle * 功能说明: 四个LED闪烁的程序 * 形 参:无 * 返 回 值: 无 ******************************************************************************************* */ void AppTask_LedToggle(void) { bsp_LedToggle(1); bsp_LedToggle(2); bsp_LedToggle(3); bsp_LedToggle(4); } 4. 主函数 主函数比较简单,主要是在大循环里面调用调度函数。 /* ******************************************************************************************* * 函 数 名: main * 功能说明: c程序入口 * 形 参:无 * 返 回 值: 错误代码(无需处理) ******************************************************************************************* */ int main(void) { bsp_Init(); /* 硬件初始化 */ Printf**(); /* 打印例程信息到串口1 */ bsp_InitTimer(); /* 初始化系统滴答定时器 */ /* 进入主程序循环体 */ while (1) { /* 任务执行函数 */ SCH_Dispatch_Tasks(); } } 2.5 实验总结 简单的总结一下合作式调度器的优缺点: l 这种调度器相对比较的简单,用少量的代码即可实现。 l 基于合作式调度器的应用程序本质上可预测,安全而且可靠。 l 调度器全部由C语言编写。 l 设计阶段要十分的小心以快速的响应外部事件。 l 上面1.3小节提到三个问题是使用合作式调度器的难点。当然,如果只是简单的使用完全没有问题。 这里只给大家介绍了一下如何设计一个简单的合作式调度器,有兴趣的可以做深入的研究。时间触发方式的合作式调度器还是很有研究价值的,特别实在一些安全关键的领域。
参考资料: 1. Patterns fortime-triggered embedded systems英文版和中文版
|