《项目驱动——编程入门【应用材料】》由会员分享,可在线阅读,更多相关《项目驱动——编程入门【应用材料】(31页珍藏版)》请在金锄头文库上搜索。
1、电子实验中心电子实验中心项目驱动项目驱动-单片机应用设计技术单片机应用设计技术 电子实验中心电子实验中心一、前后台系统与嵌入式系统的不同一、前后台系统与嵌入式系统的不同设计:每按一次按键,发光二极管改设计:每按一次按键,发光二极管改变一次状态。(电路略)变一次状态。(电路略)1、前后台系统示例程序如下:、前后台系统示例程序如下:沐风书苑沐风书苑 电子实验中心电子实验中心Sbit LED = P11;Sbit KEY = P21;Void delay(unsigned int i)while(i-);Void main()while(1)if(KEY=0)沐风书苑沐风书苑 电子实验中心电子实验中
2、心delay(1000);if(KEY=0)LED != LED;while(KEY=0);沐风书苑沐风书苑 电子实验中心电子实验中心vTinyOS示例程序如下:示例程序如下:void main (void) static void _taskKEY(void); static void _taskLED(void); _timer0Init(); tnOsInit(); tnOsTaskCreate(_taskKEY, _GucTaskStks0); tnOsTaskCreate(_taskLED, _GucTaskStks1); tnOsStart();沐风书苑沐风书苑 电子实验中心电子实
3、验中心vstatic void _taskKEY (void)vv tnOsSemCreate(&_GosSem, 1);v while (1) v while (KEY != 0) v v tnOsTimeDly(TICKS_PER_SEC / 100); v v tnOsSemPost(&osSem);v while ( KEY = 0)v v tnOsTimeDly(TICKS_PER_SEC / 100); v v v沐风书苑沐风书苑 电子实验中心电子实验中心vstatic void _taskLED (void)vv while (1) v v tnOsSemPend(&_GosSe
4、m, 0);v LED != LED;v v沐风书苑沐风书苑 电子实验中心电子实验中心二、嵌入式基础知识二、嵌入式基础知识 当使用操作系统时,如果将这些当使用操作系统时,如果将这些“可执可执行的程序单元行的程序单元”进行分类,即可得到在操作进行分类,即可得到在操作系统调度下的系统调度下的“用户任务用户任务”,简称任务,简称任务(Task)。当任务)。当任务“独占独占”CPU 的运行期间,的运行期间,则一个任务看不见另一个任务,也就是说,则一个任务看不见另一个任务,也就是说,一个任务不可能象调用一个任务不可能象调用“子程序子程序”那样调用那样调用另一个任务,因此任务之间的信息传递只能另一个任务,
5、因此任务之间的信息传递只能通过通过“异步异步”的方式来完成,即由操作系统的方式来完成,即由操作系统的各种的各种“通信通信”机制来实现,比如,机制来实现,比如,信号量信号量(Semaphore)与消息邮箱()与消息邮箱(Message Postbox)等。等。沐风书苑沐风书苑 电子实验中心电子实验中心并发性(并发性(Concurrent)与调度()与调度(Schedulingv 简单应用的典型设计为顺序运行,一次简单应用的典型设计为顺序运行,一次执行一条指令,按预先设定的顺序运行,执行一条指令,按预先设定的顺序运行,然而这种模式对于嵌入式实时应用是不合然而这种模式对于嵌入式实时应用是不合适的,因
6、为通常要在紧密的时间约束内处适的,因为通常要在紧密的时间约束内处理多个输入和输出,假设在多理多个输入和输出,假设在多CPU 系统中,系统中,每个任务都有自己的每个任务都有自己的CPU,那么它们的运,那么它们的运行状态就是真正的行状态就是真正的“并发运行并发运行”。沐风书苑沐风书苑 电子实验中心电子实验中心并发性(并发性(Concurrent)与调度()与调度(Scheduling)沐风书苑沐风书苑 电子实验中心电子实验中心并发性(并发性(Concurrent)与调度()与调度(Scheduling)沐风书苑沐风书苑 电子实验中心电子实验中心任务状态任务状态沐风书苑沐风书苑 电子实验中心电子实验
7、中心任务之间的关系任务之间的关系 任务同步(任务同步(Synchronization) 任务间的同步是一种直接作用,任务间的同步是一种直接作用,“任务同步任务同步”是指系统中的是指系统中的多个任务之间存在某种时序关系,需要相互协作才能共同完成一多个任务之间存在某种时序关系,需要相互协作才能共同完成一项任务。比如,一个任务运行到某一时间点时,要求另一个任务项任务。比如,一个任务运行到某一时间点时,要求另一个任务为它提供消息,在未获得消息之前,该任务处于阻塞状态,获得为它提供消息,在未获得消息之前,该任务处于阻塞状态,获得消息后被唤醒进入就绪状态。消息后被唤醒进入就绪状态。 任务互斥(任务互斥(E
8、xclusion) 任务间的互斥是一种间接作用,由于内存中的多个任务要求任务间的互斥是一种间接作用,由于内存中的多个任务要求共享某一资源,而有些资源必须互斥,因此各任务之间只能竞争共享某一资源,而有些资源必须互斥,因此各任务之间只能竞争使用这些资源。使用这些资源。“任务间的互斥任务间的互斥”是指当有若干任务都要使用某是指当有若干任务都要使用某一共享资源时,最多允许一个任务使用,而其它要使用该资源的一共享资源时,最多允许一个任务使用,而其它要使用该资源的任务必须阻塞,直到占有该资源的任务释放为止。比如,当有人任务必须阻塞,直到占有该资源的任务释放为止。比如,当有人使用厕所时,则其它人都不能使用,
9、直到当前使用者出来后,其使用厕所时,则其它人都不能使用,直到当前使用者出来后,其他人才能使用。他人才能使用。沐风书苑沐风书苑 电子实验中心电子实验中心临界资源(临界资源(Critical Resources)与临界区()与临界区(Critical Section) 任务间的互斥涉及到共享资源的竞争使用,因任务间的互斥涉及到共享资源的竞争使用,因此竞争使用这些资源的任务在执行使用这些资源的程此竞争使用这些资源的任务在执行使用这些资源的程序时也会受到一定的限制,从而也就引出了临界资源序时也会受到一定的限制,从而也就引出了临界资源与临界区的概念。与临界区的概念。(1)临界资源)临界资源在操作系统中将
10、一次只允许一个任务使用的资源称之在操作系统中将一次只允许一个任务使用的资源称之为临界资源。为临界资源。(2)临界区)临界区在操作系统中将并发任务中访问临界资源的程序称之在操作系统中将并发任务中访问临界资源的程序称之为临界区,临界区也常常叫做互斥区。为临界区,临界区也常常叫做互斥区。沐风书苑沐风书苑 电子实验中心电子实验中心上下文切换(上下文切换(Context Switch)沐风书苑沐风书苑 电子实验中心电子实验中心可重入性(可重入性(Reentrant) 由于任务的并发性,因此经常会出现调用同一个由于任务的并发性,因此经常会出现调用同一个函数的情况,如果一段程序可以被多个任务同时调用,函数的
11、情况,如果一段程序可以被多个任务同时调用,而不必担心数据被破坏,那么这样的程序就是可重入而不必担心数据被破坏,那么这样的程序就是可重入的程序。的程序。 一般来说,具有可重入性的函数应该只使用局部一般来说,具有可重入性的函数应该只使用局部变量,因为函数的局部变量保持在变量,因为函数的局部变量保持在CPU 内部的寄存器内部的寄存器或堆栈中,所以可以保证不同的任务调用同一个函数或堆栈中,所以可以保证不同的任务调用同一个函数时不会发生冲突。如果函数一定要使用全局变量的话,时不会发生冲突。如果函数一定要使用全局变量的话,那么一定要对使用的全局变量进行必要的保护。由此那么一定要对使用的全局变量进行必要的保
12、护。由此可见,可见,C 编译器也应该具有产生可重入代码的能力。编译器也应该具有产生可重入代码的能力。沐风书苑沐风书苑 电子实验中心电子实验中心成于大气成于大气 信达天下信达天下程序存储区2040H 832121H 452041H 2120H 47当前PC指令代码单片机工作机制单片机工作机制沐风书苑沐风书苑 电子实验中心电子实验中心子程序调用及返回指令子程序调用及返回指令 长调用长调用LCALL addr16;PC addr16addr15812H 机器码机器码addr70三字节指令三字节指令 ;PC (PC)+3 ;SP (SP)+1, (SP) PC70 ;SP (SP)+1, (SP) P
13、C158;在调用子程序之前,保护断点地址在调用子程序之前,保护断点地址几条重要的汇编语言几条重要的汇编语言沐风书苑沐风书苑 电子实验中心电子实验中心 绝对调用绝对调用ACALL addr11双字节指令双字节指令 ; PC (PC)+ 2 ; SP (SP)+1, (SP) PC70 ; SP (SP)+1, (SP) PC158; 在调用子程序之前,保护断点地址在调用子程序之前,保护断点地址A10A9A810001A7 A0机器码机器码; PC100 A100 沐风书苑沐风书苑 电子实验中心电子实验中心 子程序返回子程序返回RET ; PC158 (SP) , SP (SP) - 122H机器
14、码机器码单字节指令单字节指令 中断返回中断返回RETI32H机器码机器码单字节指令单字节指令 ; PC70 (SP) , SP (SP) - 1 ; PC158 (SP) , SP (SP) - 1 ; PC70 (SP) , SP (SP) - 1“0”触发触发器器优先级优先级状态状态沐风书苑沐风书苑 电子实验中心电子实验中心vPC例程讲解例程讲解。a+;Delay();();b+;。沐风书苑沐风书苑 电子实验中心电子实验中心setjmp 与与longjmp 的实现的实现 本书所有例子均是基于本书所有例子均是基于SDCC51 编译器来实现的,为了编译器来实现的,为了提高兼容性,所以提高兼容性
15、,所以SDCC51 提供的库函数都很复杂。为了简提供的库函数都很复杂。为了简化这两个函数,于是约定以下规则:化这两个函数,于是约定以下规则:1. 限定限定SDCC51 为小模式为小模式(-model-small);2. 限定限定SDCC51 的的 integer 和和long 库被编译成可重入的库被编译成可重入的 (-int-long-reent);3. 限定限定SDCC51 所有函数被编译成可重入的所有函数被编译成可重入的(-stack-auto);4. 修改修改setjmp 与与longjmp 的返回值为的返回值为char;5. 取消取消longjmp 的第的第2 个参数,当调用个参数,当
16、调用longjmp 时,则让时,则让setjmp 的返回值始终为的返回值始终为1。 由于制定了以上规则,则完全可以使用由于制定了以上规则,则完全可以使用C 语言来编写语言来编写setjmp 和和longjmp 了。了。沐风书苑沐风书苑 电子实验中心电子实验中心(1)jmp_bufjmp_buf 定义定义(setjmp.h) #define _SP_SIZE 1 /*堆栈指针长度堆栈指针长度 */ #define _BP_SIZE _SP_SIZE /*编译器虚拟的寄存器,用于重入编译器虚拟的寄存器,用于重入*/ #define _RET_SIZE 2 /*返回地址长度返回地址长度 */ typ
17、edef unsigned char jmp_buf_RET_SIZE + _SP_SIZE + _BP_SIZE;沐风书苑沐风书苑 电子实验中心电子实验中心(2)setjmp setjmp 就是将相应的寄存器和就是将相应的寄存器和setjmp 的返回地的返回地址保存到址保存到jmp_buf 数组类型的变量中,即保存的寄存数组类型的变量中,即保存的寄存器只有变量器只有变量bp 的当前值、堆栈指针的当前值(的当前值、堆栈指针的当前值(SP)和返回地址和返回地址addr15addr0。对于。对于80C51 系列单片机系列单片机来说,由于调用函数是使用来说,由于调用函数是使用ACALL 或或LCAL
18、L 来指令来指令实现的,因此这些指令会将函数的返回地址实现的,因此这些指令会将函数的返回地址(两个字节两个字节)保存在堆栈中。保存在堆栈中。由于由于setjmp 不需要在堆栈中保存其它的数据,因此不需要在堆栈中保存其它的数据,因此可以用程序清单可以用程序清单5.7(46)和程序清单和程序清单5.7(47)保存返回地保存返回地址,根据约定函数最后返回址,根据约定函数最后返回0,setjmp()定义详见程定义详见程序清单序清单5.7。沐风书苑沐风书苑 电子实验中心电子实验中心39 char setjmp (jmp_buf jbBuf)40 41 data unsigned char *pucBuf
19、 = (data void*)0; 42 /* 指向上下文信息存储位置的指针指向上下文信息存储位置的指针 */43 pucBuf = (data unsigned char *)jbBuf;44 *pucBuf+ = bp; /* 保存保存bp 的当前值的当前值 */45 *pucBuf+ = SP; /* 保存保存sp 的当前值的当前值 */46 *pucBuf+ = *(unsigned char data *)SP); /* 保存返回地址的高保存返回地址的高8 位位 */47 *pucBuf = *(unsigned char data *)(char)(SP - 1); /* 保存返回
20、地址的低保存返回地址的低8 位位 */48return 0;49 沐风书苑沐风书苑 电子实验中心电子实验中心(3)longjmp longjmp()定义如程序清单定义如程序清单5.8 所示,所示,首先从参数首先从参数jbBuf 中恢复中恢复bp 的值,并从的值,并从jbBuf 中取出堆栈指针的原始值保存到中取出堆栈指针的原始值保存到ucSpSave 变量中,然后将返回地址保存变量中,然后将返回地址保存到到ucSpSave 指向的位置,接着将当前堆指向的位置,接着将当前堆栈指针设置为栈指针设置为ucSpSave 的值,最后函数的值,最后函数返回返回1。沐风书苑沐风书苑 电子实验中心电子实验中心5
21、8 char longjmp (jmp_buf jbBuf)59 60 unsigned char ucSpSave; /* 保存的堆栈指针保存的堆栈指针 */61 data unsigned char *pucBuf = (data void *)0; /* 指向上下文信息存储位置的指针指向上下文信息存储位置的指针 */63 pucBuf = (data unsigned char *)jbBuf;64 bp = *pucBuf+; /* 恢复恢复bp */65 ucSpSave = *pucBuf+; /* 读取堆栈指针读取堆栈指针 */66 *(unsigned char data *)
22、ucSpSave) = *pucBuf+; 67 /* 恢复返回地址的高恢复返回地址的高8 位位 */67 *(unsigned char data *)(char)(ucSpSave - 1)= *pucBuf; /* 恢复返回地址的低恢复返回地址的低8 位位 */68 SP = ucSpSave; /* 恢复堆栈指针恢复堆栈指针 */69 return 1;70 沐风书苑沐风书苑 电子实验中心电子实验中心范例分析范例分析 setjmp 与与longjmp 在后续的操作系统中起到在后续的操作系统中起到了至关重要的作用,因此初学者必须搞清楚它们了至关重要的作用,因此初学者必须搞清楚它们之间的关
23、系,否则将无法掌握操作系统的设计思之间的关系,否则将无法掌握操作系统的设计思想和实现原理,下面将通过一个实例来说明想和实现原理,下面将通过一个实例来说明setjmp 与与longjmp 的具体作用,详见程序清单的具体作用,详见程序清单5.5。沐风书苑沐风书苑 电子实验中心电子实验中心 #include 29 jmp_buf jbTest;30 unsigned char ucSum0;31 unsigned char ucSum1;32 unsigned char ucSum2;41 void func0 (void)42 43 ucSum0+;44 longjmp(jbTest, 1);45
24、 ucSum0+; 46 /* 程序始终不会执行到这里程序始终不会执行到这里 */46 沐风书苑沐风书苑 电子实验中心电子实验中心55 void func1 (void) /* 程序始终不会执行这个函数程序始终不会执行这个函数 */56 57 ucSum1+;58 67 void func2 (void)68 69 ucSum2+;70 沐风书苑沐风书苑 电子实验中心电子实验中心 void main (void)80 81 int iRt;83 while (1) 84 85 iRt = setjmp(jbTest); 84 /*由于直接调用由于直接调用setjmp,因此其返回值为,因此其返回值为0*/85 if (iRt = 0)86 86 func0();87 func1();88 /* 程序始终不会执行到这里程序始终不会执行到这里 */88 else 89 func2();90 91 92 沐风书苑沐风书苑