自己动手写RTOS
一、基础知识
1.枚举
1.1枚举
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;
2、定义枚举类型的同时定义枚举变量
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
3、省略枚举名称,直接定义枚举变量
enum
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
1.2枚举和typedef
#ifndef _KEY_H_
#define _KEY_H_
//定义枚举类型,代表按键的下标和总的个数,增加按键个数只需要在枚举类型里
//添加KEY3这样
typedef enum
{
KEY1,
KEY2,
KEY_NUM
}KEY_ID_TYPEDEF;
//声明枚举类型时,给成员赋值,默认是从0开始按照加1递增,比如0,1,2
typedef enum
{
KEY_IDLE, //空闲
KEY_PRESS, //短按
KEY_LONG_PRESS,//长按
KEY_RELEASE=7//释放
}KEY_STATE_TYPEDEF;
**错误的枚举例子**
enum
{
ENUM_0,
ENUM_10 = 10,
ENUM_11
};
2.结构体
3.队列
4.函数指针
4.1不带参数和返回值
void (*fun)(void);//声明一个函数指针
void sun(void);//声明一个函数
//函数的实现
void sun(void)
{
}
//将函数指针指向函数
fun = sun;
//调用函数指针
(*fun)();
4.2函数指针和typedef的组合
int add(int a, int b) {
return a + b;
}
typedef int (PTypeFun1)(int, int); // 声明一个函数类型
typedef int (*PTypeFun2)(int, int); // 声明一个函数指针类型
int (*padd)(int, int); // 传统形式,定义一个函数指针变量
int main() {
PTypeFun1 *pTypeAdd1 = add;
PTypeFun2 pTypeAdd2 = add;
padd = add;
cout << pTypeAdd1(1, 2) << endl;
cout << pTypeAdd2(1, 2) << endl;
cout << padd(1, 2) << endl;
return 0;
}
我们为什么一定要使用 typedef 定义函数指针呢?
首先,使用 typedef 定义函数指针,代码看起来更简洁,也更不容易出错。
其次,当函数指针作为其它函数的参数,特别是作为返回值时,直接使用的函数指针无法编译。
#include <stdio.h>
void FunA() {
printf("call FunA\n");
}
void FunB(int n) {
printf("call FunB. n is : %d\n", n);
}
typedef void (*PtrFunA)();
typedef void (*PtrFunB)(int);
// 函数指针作为函数参数使用
void usePtrFunA(PtrFunA p) {
p();
}
void usePtrFunB(PtrFunB p, int n) {
p(n);
}
//下面这种语法编译器已经无法识别了
//(void (*PtrFunA)()) getPtrFunA2() {
// return FunA;
//}
// 函数指针作为函数返回值使用
PtrFunA getPtrFunA() {
PtrFunA p = FunA;
return p;
}
PtrFunB getPtrFunB() {
PtrFunB p = FunB;
return p;
}
int main() {
// 获取 FunA 函数的函数指针
PtrFunA a = getPtrFunA();
// 使用 FunA 函数的函数指针
usePtrFunA(a);
// 获取 FunB 函数的函数指针
PtrFunB b = getPtrFunB();
// 使用 FunB 函数的函数指针
usePtrFunB(b, 1);
return 0;
}
简单实例
OS_System.h
typedef enum
{
OS_SLEEP, // 任务休眠
OS_RUN = !OS_SLEEP // 任务运行
}OS_TaskStateTypedef;
typedef struct OS_TASK
{
void (*task)(void); // 任务函数指针
OS_TaskStateTypedef RunFlag; // 任务状态
unsigned short RunPeriod; // 任务运行周期
unsigned short RunTimer; // 任务调度计时时间
}OS_TaskTypedef;
void OS_TaskInit(void);
void OS_TaskCreat(u8 ID, void(*Fun)(void), u16 period, OS_TaskStateTypedef flag);
OS_System.c
volatile OS_TaskTypedef OS_Task[OS_TASK_SUM]; //任务数组
/*******************
初始化任务
**********************/
void OS_TaskInit(void)
{
U8 i;
for(i=0; i<OS_TASK_SUM; i++)
{
OS_Task[i].task = 0;
OS_Task[i].RunFlag= OS_SLEEP;
OS_Task[i].RunPeriod= 0;
OS_Task[i].RunTimer= 0;
}
}
/*******************
创建任务
**********************/
void OS_TaskCreat(u8 ID, void(*Fun)(void), u16 period, OS_TaskStateTypedef flag)
{
if(!OS_Task[ID].task)
{
OS_Task[ID].task = Fun; // 任务对应函数实例
OS_Task[ID].RunFlag= OS_SLEEP;
OS_Task[ID].RunPeriod= period;
OS_Task[ID].RunTimer= 0;
}
}
void OS_Start(void)
{
u8 i
while(1)
{
for(i=0; i<OS_TASK_SUM; i++)
{
if(OS_Task[i].RunFlag == OS_RUN) // 轮训查看任务是否准备好
{
OS_Task[i].RunFlag == OS_SLEEP;
(*(OS_Task[ID].task))();
}
}
}
}
/*******************
定时回调函数,用于在定时中断函数里调动
**********************/
void OS_ClockInterruptCallbck(void)
{
u8 i
for(i=0; i<OS_TASK_SUM; i++)
{
if(OS_Task[i].task)
{
OS_Task[i].RunTimer++;
// 定时周期到,置位运行状态为可以运行
if(OS_Task[i].RunTimer >OS_Task[i].RunPeriod)
{
OS_Task[i].RunTimer = 0;
OS_Task[ID].RunFlag= OS_RUN;
}
}
}
}