1、模块划分
(1)模块划分的“划”是规划的意思,意指怎样合理的将一个很大的软件划分为一系列功能独立的部分,合作完成系统的需求。
(2)C语言作为一种结构化的程序设计语言,在模块的划分上主要依据功能来进行划分。
2、模块划分的方法
(1)模块即是一个.C文件,或者是一个.h文件的接合,头文件(.h)中是对该模块接口的声明。
(2)某模块提供给其他模块调用的外部函数及数据需要在.h文件中冠以extern关键字声明。
(3)仅在模块内部使用的函数和局部变量需要在.C文件中冠以static声明。
(4)永远不要在.h文件中定义变量:定义变量和声明变量的区别在于定义变量会产生内存分配的操作。
在.h文件中定义了变量,其他.C文件引用了该头文件,会使得各个.C文件都将该变量默认为本地变量,使得该变量无法起到全局共享的作用。
一个不好的例子:
/*module1.h*/int a = 5 ; //在模块1的文件.h文件中定义了int a/*module1.c*/#include "module1.h" //在模块1的文件.c文件中包含了模块1的.h文件/*module2.c*/#include "module1.h" //在模块2的文件.c文件中包含了模块1的.h文件/*module3.c*/#include "module1.h" //在模块3的文件.c文件中包含了模块1的.h文件
一个好的例子:
/*module1.h*/extern int a; //在模块1的文件.h文件中只是声明了int a/*module1.c*/#include "module1.h" //在模块1的文件.c文件中包含了模块1的.h文件int a = 5; //在模块1的文件.c文件中定义了int a/*module2.c*/#include "module1.h" //在模块2的文件.c文件中包含了模块1的.h文件/*module3.c*/#include "module1.h" //在模块3的文件.c文件中包含了模块1的.h文件
3、模块的类型
(1)硬件驱动模块:一种特定的硬件对应一个模块
(2)软件功能模块:其模块的划分应满足低耦合、高内聚的要求,一个功能对应一个模块。
4、任务模式:
(1)单任务:微观串行、宏观串行
(2)多任务:微观串行、宏观并行
串行:每一个时刻只运行一个任务。
并行:一个时间段你运行了多个任务。
5、单任务典型架构
(1)从CPU复位时的指定地址开始执行
(2)跳转至汇编代码startup处开始执行、部分初始化操作。
(3)跳转至用户主程序main处执行,在main函数中完成:
①初始化部分硬件设备
②初始化各软件模块
③进入死循环(无限循环),调用各模块的处理函数。
死循环的程序写法:
while(1){//null}
或者写成:
for(;;){//null}
6、中断服务程序
(1)中断是嵌入式系统的重要组成部分,但是在标准C语言中不包含中断,许多编译器开发商在标准C上增加了对中断的支持,提供新的关键字用于标识中断服务程序(ISR),
例如:_ _interrupt
(2)当一个函数被定义为中断函数(ISR)的时候,编译器会自动为该函数增加中断服务程序所需要的中断现场入栈和出栈代码。
7、中断服务程序的特点:
中断服务程序需要满足如下需求:
(1)不能返回值
(2)不能向中断函数(ISR)传递参数
(3)ISR程序应该尽可能的短小精悍;否则会影响程序的性能
(4)printf(char *IpFormatString, …)函数会带来性能问题,不能在ISR函数中使用,因为变参函数的执行时间比较长。
8、中断服务程序模型
在项目开发中,设计一个队列,在中断服务程序中,只是将中断类型添加进该队列中,在主程序的无限循环中不断扫描中断队列是否有中断产生,有则取出队列中的第一个中断类型,进行相应的处理。
typedef struct tagIntQueue//存放中断的队列{int intType;//中断类型struct tagIntQueue*next;//队列指针}IntQueue;IntQueue* IpIntQueueHead;_ _interrupt ISRexample(){int intType;//中断类型intType = GetSystemType();//获取中断类型QueueAddTail(IpIntQueueHead, intType),//在队列尾中加入新的中断}
9、主程序模型
while(1){if(!IsIntQueueEmpty()){intType = GetFirstInt();switch(intType){case xxx://中断处理函数....break;case xxx:....break;}}}