个人笔记
文章目录
- 准备一个 51 单片机工程
- 将 Small RTOS51 相关文件添加到工程
- 一个简单的程序
- 运行效果
- 遇到的问题
准备一个 51 单片机工程
我打算拿一个现成的 51 单片机工程来移植 Small RTOS51,
当然,也可以重新创建一个新的工程。
将 Small RTOS51 相关文件添加到工程
将源码目录的下面三个文件夹复制到我们的工程目录下,
下面的三个头文件其实都来自 “h” 文件夹,之所以把它们复制到项目根目录,一是可以省去包含头文件,二是即使包含了 h 目录下头文件,KEILC51 目录下的 OS_CPU_A.ASM 依然会报错(暂时没找到解决报错的办法,所以直接将头文件放到根目录)。
仿照源码目录下的几个例程,将 Small RTOS51 的源文件添加到 Keil 工程中,
在放 main() 函数的文件里添加 Small RTOS51 的总头文件 “config.h”,同时编写一个空的 mian()(没有任何实际功能的 main() ),编译工程,暂时没有报错。
根据工程目录修改 config.h 下的部分头文件的路径。例如,将原本的#include "..\os\OS.H"
改为 #include "os\OS.H"
(貌似头文件识别不考虑大小写)
一个简单的程序
这是一个简单的测试程序,实现了 3 个 LED 的循环亮灭(3 个 灯相互独立,互不影响地”同时“闪烁)。
#include "config.h"
#define led_out P2 //将单片机的P2端口定义为led,8个IO
void TaskA(void);
void TaskB(void);
void TaskC(void);
int main()
{
// RTOS 初始化
OSInit();
// 定时器初始化
TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
// 创建任务
OSTaskCreate(TaskA, NULL, 0);
OSTaskCreate(TaskB, NULL, 1);
OSTaskCreate(TaskC, NULL, 2);
while(1)
{
PCON = PCON | 0x01; /* CPU进入休眠状态 */
}
}
// 任务 A
void TaskA(void)
{
while(1)
{
OSWait(K_TMO, 250);
led_out &= ~(0x1 << 0); // 第一个灯亮
OSWait(K_TMO, 250);
led_out |= (0x1 << 0); // 第一个灯灭
}
}
// 任务 B
void TaskB(void)
{
while(1)
{
OSWait(K_TMO, 250);
led_out &= ~(0x1 << 1); // 第二个灯亮
OSWait(K_TMO, 250);
led_out |= (0x1 << 1); // 第二个灯灭
}
}
// 任务 C
void TaskC(void)
{
while(1)
{
OSWait(K_TMO, 250);
led_out &= ~(0x1 << 2); // 第三个灯亮
OSWait(K_TMO, 250);
led_out |= (0x1 << 2); // 第三个灯灭
}
}
上面这个测试程序能让 P2.0,P2.1 和 P2.2 三个引脚上的 LED 以 250ms 的间隔闪烁,但如果只添加上面这些代码,LED 的闪烁周期并不是 250ms。首先,定时器溢出周期 1ms 的前提是单片机外部晶振为 12MHz(可以参考我的另一篇笔记实验14:定时器0中断)
另外,我所用的单片机 STC89C52 定时器 0 在工作方式 1 的情况下,每次溢出后需要重新给定时器赋值(重载),这个任务需要在定时器中断里完成,Small RTOS51 默认将定时器 0 作为系统时钟源,系统时钟中断函数位于 OS_CPU_C.c 文件中,为了不破坏源码,我们选择在用户函数 UserTickTimer()
里添加定时器计数值重载的操作。
UserTickTimer() 并没有在源码中定义,需要用户自己定义。
// 系统时钟中断(定时器0中断)用户函数
void UserTickTimer()
{
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
}
Small RTOS51 默认没有使能系统定时器中断中的用户函数,需要修改 OS_CFG.h 下的 EN_USER_TICK_TIMER
宏的值。
运行效果
实物效果不方便展示,所以选择用仿真的方式:
遇到的问题
如果工程创建时添加了 STARTUP.A51 文件,需要将其从 Keil 工程中删除,不然会导致任务无法调度。
STARTUP.A51 一般是工程刚创建时添加的: