嵌入式系统程序设计.ppt
《嵌入式系统程序设计.ppt》由会员分享,可在线阅读,更多相关《嵌入式系统程序设计.ppt(282页珍藏版)》请在三一办公上搜索。
1、嵌入式系统程序设计,大连理工大学软件学院嵌入式系统工程系赖晓晨,C/C+语言摘要,C语言的历史和特点预处理程序位运算函数指针C程序的移植,一、C语言的历史和特点,C语言的历史C语言的特点,C语言的优良特性,结构化语言,代码数据分离包含指针特性,允许对地址操作语法简洁紧凑,但功能强大编程方便,运行速度快支持分离编译,C语言的缺点,封装性不如C+,数据安全性上有缺陷 类型检查机制相对薄弱 指针的操作带来许多不安全因素 比其他高级语言较难掌握,二、预处理程序,C89规定的预处理指令有以下几条#if#ifdef#ifndef#else#elif#endif,#define#undef#line#err
2、or#pragma#include,预处理语句的书写规则,作用:对源程序编译之前做一些处理,生成扩展C源程序格式:“#”开头占单独书写行语句尾不加分号,1.宏定义不带参数宏定义一般形式:#define 宏名 宏体功能:用指定标识符(宏名)代替字符序列(宏体),1.宏定义不带参数宏定义一般形式:#define 宏名 宏体功能:用指定标识符(宏名)代替字符序列(宏体),如#define YES 1#define NO 0#define PI 3.1415926#define OUT printf(“Hello,World”);,1.宏定义不带参数宏定义一般形式:#define 宏名 宏体功能:用指
3、定标识符(宏名)代替字符序列(宏体),宏体可缺省,表示宏名定义过,如#define YES 1#define NO 0#define PI 3.1415926#define OUT printf(“Hello,World”);,1.宏定义不带参数宏定义一般形式:#define 宏名 宏体功能:用指定标识符(宏名)代替字符序列(宏体),定义位置:任意(一般在函数外面)作用域:从定义命令到文件结束#undef可终止宏名作用域 格式:#undef 宏名,1.宏定义不带参数宏定义一般形式:#define 宏名 宏体功能:用指定标识符(宏名)代替字符序列(宏体),定义位置:任意(一般在函数外面)作用域:
4、从定义命令到文件结束#undef可终止宏名作用域 格式:#undef 宏名,如 if(x=YES)printf(“correct!n”);else if(x=NO)printf(“error!n”);展开后:if(x=1)printf(“correct!n”);else if(x=0)printf(“error!n”);,1.宏定义不带参数宏定义一般形式:#define 宏名 宏体功能:用指定标识符(宏名)代替字符序列(宏体),宏展开:预编译时,用宏体替换宏名-不作语法检查,定义位置:任意(一般在函数外面)作用域:从定义命令到文件结束#undef可终止宏名作用域 格式:#undef 宏名,1.
5、宏定义不带参数宏定义一般形式:#define 宏名 宏体功能:用指定标识符(宏名)代替字符序列(宏体),宏展开:预编译时,用宏体替换宏名-不作语法检查,定义位置:任意(一般在函数外面)作用域:从定义命令到文件结束#undef可终止宏名作用域 格式:#undef 宏名,引号中的内容与宏名相同不置换,例#define ID 1 语句printf(ID);会输出ID,而非1,1.宏定义不带参数宏定义一般形式:#define 宏名 宏体功能:用指定标识符(宏名)代替字符序列(宏体),宏展开:预编译时,用宏体替换宏名-不作语法检查,定义位置:任意(一般在函数外面)作用域:从定义命令到文件结束#undef
6、可终止宏名作用域 格式:#undef 宏名,宏定义可嵌套,不能递归,例#define ID ID+1(),引号中的内容与宏名相同不置换,例#define DIS1 10#define DIS2 DIS1+10 var=DIS2*2;宏展开:var=10+10*2;,1.宏定义不带参数宏定义一般形式:#define 宏名 宏体功能:用指定标识符(宏名)代替字符序列(宏体),宏展开:预编译时,用宏体替换宏名-不作语法检查,定义位置:任意(一般在函数外面)作用域:从定义命令到文件结束#undef可终止宏名作用域 格式:#undef 宏名,宏定义可嵌套,不能递归,引号中的内容与宏名相同不置换,宏定义中
7、使用必要的括号(),1.宏定义不带参数宏定义一般形式:#define 宏名 宏体功能:用指定标识符(宏名)代替字符序列(宏体),宏展开:预编译时,用宏体替换宏名-不作语法检查,定义位置:任意(一般在函数外面)作用域:从定义命令到文件结束#undef可终止宏名作用域 格式:#undef 宏名,宏定义可嵌套,不能递归,引号中的内容与宏名相同不置换,宏定义中使用必要的括号(),宏体可以省略,表示宏名已被定义过,/*ch3_1.c*/#include#define Aint main()#ifdef Aprintf(A has been definedn);#elseprintf(A has not
8、been definedn);#endifreturn 0;输出为:“A has been defined”,即使把宏定义改为:#define A0输出仍旧为:“A has been defined”。,带参数宏定义一般形式:#define 宏名(参数表)宏体,例#define T(m,n)m*n相当于定义了不带参宏T,其宏体为“(m,n)m*n”,宏展开:形参用实参换,其它字符保留,例#define T(m,n)m*n.area=T(3,2);宏展开:area=3*2;,不能加空格,带参数宏定义一般形式:#define 宏名(参数表)宏体,宏展开:形参用实参换,其它字符保留宏体及各形参外一般
9、应加括号(),例#define T(m,n)m*n.area=T(3,2);宏展开:area=3*2;,例#define CUBE(x)x*x*x a=4;b=6;z=CUBE(a+b);宏展开:z=a+b*a+b*a+b;一般写成:#define CUBE(x)(x)*(x)*(x)宏展开:z=(a+b)*(a+b)*(a+b);,带参的宏与函数区别,Embest开发环境中的宏定义,44b.h有44B0X中各个特殊功能寄存器的宏定义,#define rBWSCON(*(volatile unsigned*)0 x1c80000)#define rBANKCON0(*(volatile uns
10、igned*)0 x1c80004)#define rBANKCON1(*(volatile unsigned*)0 x1c80008)#define rBANKCON2(*(volatile unsigned*)0 x1c8000c)#define rBANKCON3(*(volatile unsigned*)0 x1c80010)#define rBANKCON4(*(volatile unsigned*)0 x1c80014)#define rBANKCON5(*(volatile unsigned*)0 x1c80018),预定义宏,C89规范了五个固有的预定义宏,分别为:_LINE_
11、:行号_FILE_:文件名_DATE_:日期_TIME_:时间_STDC_:1标准C编译器 0非标准C编译器,预定义宏,#include int main()printf(The current file is:%sn,_FILE_);printf(The current line number is:%dn,_LINE_);printf(today is:%sn,_DATE_);printf(the time is:%sn,_TIME_);if(_STDC_=1)printf(this is a standard compilern);else if(_STDC_=0)printf(this
12、 is not a standard compilern);,/exp/pre/macro.c,功能:对源程序中的一部分内容只有满足某种条件的情况下才进行编译。,2.条件编译,#ifdef 标识符程序段1#else程序段2#endif,形式1:,当标识符已经被定义过(使用#define),则对程序段1进行编译,否则编译程序段2。其中#else部分可以省略。,形式1(续):,#define IBM-PC 0/*或#define IBM-PC*/。#ifdef IBM-PC#define INT 16#else#define INT 32#endif,可以用来提高程序的可移植性,形式1(续):,#
13、define DEBUG.#ifdef DEBUGprintf(“x=%d,y=%d”,x,y);#endif,可以用来调试程序,调试结束后只需将define行删掉即可,#ifndef 标识符程序段1#else程序段2#endif,形式2:,当标识符未被定义过,则对程序段1进行编译,否则编译程序段2。(与形式1正相反),#if 表达式程序段1#else程序段2#endif,形式3:,当表达式为真时,则对程序段1进行编译,否则编译程序段2。,#include#define CAP 1int main()char string20=I love China;char c;int i=0;c=str
14、ingi+;while(c!=0)#if CAPif(c=a,形式3:(续),3.文件包含功能:一个源文件可将另一个源文件的内容全部包含进来一般形式:#include“文件名”或#include,直接按标准目录搜索“”先在当前目录搜索,再搜索标准目录可指定路径,3.文件包含功能:一个源文件可将另一个源文件的内容全部包含进来一般形式:#include“filename”或#include,处理过程:预处理时,用被包含文件的内容取代该预处理命令,再把“包含”后的文件作为一个源文件编译,被包含文件内容源文件(*.c)头文件(*.h),宏定义数据结构定义函数说明等,实际上文件名也可以是C源文件,不过这
15、不是良好的编程风格,【例3-5】文件包含一下程序包含一个完整的模块(function.c、function.h、test.c),/*funtion.h*/#ifndef _FUNCTION#define _FUNCTIONvoid f();#endif/*function.c*/#include void f()printf(a example of#include.n);,/*test.c*/#include#include function.hint main()f();return 0;,头文件格式,4.其他预处理指令,#error指令强制编译器停止编译,主要用于程序调试。#error指
16、令的一般形式为:编译到#error时,会显示相应字符串,#error error-message,#error举例,#define CON10#define CON21#define CON3-1int main()#ifCON1#ifCON2#error run to position1#else#error run to position2#endif#else#ifCON3#error run to position3#else#error run to position4#endif#endif,明确程序编译位置,三、位运算,1.位与&,运算规则:两个位都为1,结果为1,否则为0例如:
17、9&0 x0c结果为8,2.位或|,运算规则:两个位都为0,结果为0,否则为1例如:9|0 x0c结果为0 x0d,3.按位取反,运算规则:1变0,0变1用途:使某位取反,3.按位取反(续),例:使某数最低位为0,int a;a=a&0 xfffffffe,3.按位取反(续),例:使某数最低位为0,思考:有没有隐含的问题,int a;a=a&0 xfffffffe,3.按位取反(续),例:使某数最低位为0,/*16位机*/int a;a=a&0 xffffe/*32位机*/a=a&0 xfffffffe,可移植性变差,3.按位取反(续),例:使某数最低位为0,a=a&1/*1能自动适应16位机
18、以及32位机*/,解决办法,4.按位异或,运算规则:判断两位是否相同,同则为0,否则为1用途:使特定位翻转 交换两个值,不用临时变量,4.按位异或(续),不通过中间变量交换两个变量的值/*ch3_7.c*/#include int main()int a=21;int b=43;a=ab;b=ba;a=ab;printf(a=%d,b=%dn,a,b);return 0;,5.左移位,运算规则:将一个数的全部二进制位左移若干位,移出位舍弃,右侧补0用途:移出位没有1时,相当于乘法运算,6.右移位,运算规则:将一个数的全部二进制位右移若干位,移出位舍弃,左侧可能补0或者补1,视计算机系统不同而不
19、同。符号问题:无符号数右移,左侧补0有符号数视计算机系统而定:逻辑右移、算术右移,例:循环右移n位,例:循环右移n位(续),#include int main()unsigned a,b,c,n;scanf(a=%x,n=%d,输入:a=0 x12345678,n=8,显示:a=12345678,c=78123456,四、函数指针,每一个函数模块都有一个首地址,称为函数的入口地址。指向函数的指针称为函数指针,保存的是函数的入口地址(首地址)函数调用:找到函数入口地址;传递参数,1.函数指针的定义方法,格式:int(*ptr1)(int);定义了函数指针ptr1,此指针只能保存具有一个整型参数的
20、整型函数的首地址。注意:int*ptr1(int);这是一条函数声明语句,表示一个带有整数参数的函数返回,返回一个整型指针。int(*ptr1)(int);这个是函数指针,例:,以0.1为步长,计算特定范围内的三角函数之和。,sin(0.1)+sin(0.2)+sin(1.0)cos(0.5)+cos(0.6)+cos(3.0),#include#include double triangle(double(*func)(double),double begin,double end)double step,sum=0.0;for(step=begin;stepend;step+=0.1)su
21、m+=func(step);return sum;int main()double result;result=triangle(sin,0.1,1.0);printf(the sum of sin from 0.1 to 1.0 is%fn,result);result=triangle(cos,0.5,3.0);printf(the sum of cos from 0.5 to 3.0 is%fn,result);return 0;,#include#include double triangle(double(*func)(double),double begin,double end)
22、double step,sum=0.0;for(step=begin;stepend;step+=0.1)sum+=func(step);return sum;int main()double result;result=triangle(sin,0.1,1.0);printf(the sum of sin from 0.1 to 1.0 is%fn,result);result=triangle(cos,0.5,3.0);printf(the sum of cos from 0.5 to 3.0 is%fn,result);return 0;,2.用typedef来简化函数指针,对参数较多的
23、函数类型,定义相应的函数指针比较烦琐,可用typedef关键字简化例如typedef double(*FUN)(double a,double b);,用typedef来简化函数指针(续),格式:int(*ptr1)(int);定义函数指针的别名方法:定义了函数指针ptr1,此指针只能保存具有一个整型参数的整型函数的首地址。,double(*fun1)(double a,double b);typedef double(*FUN)(double a,double b);FUN f1;FUN f2;,用typedef来简化函数指针(续),格式:int(*ptr1)(int);定义函数指针的别名方
24、法:(也可以这样)定义了函数指针ptr1,此指针只能保存具有一个整型参数的整型函数的首地址。,double(*fun1)(double a,double b);typedef double(FUN)(double a,double b);FUN*f1;FUN*f2;,3函数指针数组,声明方式定义了表示定义了一个长度为4的函数指针数组,同时做了初始化。,double(*fp4)(double,double)=f1,f2,f3,f4,4函数指针应用,在嵌入式操作系统中,经常用函数指针来完成任务的调度。例如uC/OS中,任务创建的函数原型为第一个参数为函数指针,INT8U OSTaskCreate(
25、void(*task)(void*pd),void*pdata,OS_STK*ptos,INT8U prio);,五、C程序的移植,为一种机器写的程序,经常需要在其他硬件、操作系统的平台上运行,往往需要对此程序进行一些改动,这个过程叫做程序的移植方便移植的程序称为可移植程序程序不可移植,主要是因为有太多硬件相关的代码,1、避免使用“魔数”,“魔数”(magic number):依赖于系统或处理器的数字。例如表示硬盘缓冲区的大小、屏幕和键盘的特定尺寸等数字。“魔数”的出现使系统可移植性变差。下列代码本质上是不可移植的,fread(buf,256,1,fp);/缓冲区为256B,使用#define
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 嵌入式 系统 程序设计

链接地址:https://www.31ppt.com/p-5404675.html