自己动手写RTOS:01基础知识和理论部分

自己动手写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;
			}
		}
	}	

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小薛1988

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值