手把手教你学单片机的C语言程序设计(六):编译预处理.pdf_第1页
手把手教你学单片机的C语言程序设计(六):编译预处理.pdf_第2页
手把手教你学单片机的C语言程序设计(六):编译预处理.pdf_第3页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

学 习单 片机 所谓螭译预处理, 是蝙译嚣在对C语言源程序进行正常墒译之前, 先对一些特殊的预处理命令作解释, 产生一个新 的源程序蝙译预处理主要为程序调试 移植等提供便剃, 是一个非常实用的功能 在源程序中 为了区分预处理命令 和一般的C语句的不同所有预处理 命令行都以符号。 群 ” 开头 并且结尾不 用分号。 预处理命令可以出现在程序任 何位 置, 但 习惯上尽可能地写在源程 序 的开头 其作用范围从其出现的位置到 文件尾 。 C语言提供的预处理命令主要有: 宏定义、 文件包含和条件编译。其中宏 定义分为带参数的宏定义和不带参数 的宏定义。 1 不带参数的宏定义 不带参数的宏定义的一般形式为: # d e fi n e标识符 字符 串 它的作用是在编译预处理时。 将源 程序中所有标识符替换成字符串。例 如 ! # d in e P I 31 4 # d e f in e u i n t u n s ig n e d in t 当需要修改元素时 只要直接修改 宏定义即可 无需修改程序中所有出现 元素个数的地方 所以宏定义 不仅提 高了程序的可读 性 便于调试 而且也 方便了程序的移植。 无参数的宏定义使用时, 要注意以 下几个问题: 1 】 宏名一般用大写字母 以便于 与变量名的区舅 0 。当然 用小写字母也 不为锚。 2 ) 在编译预处理中宏名与字符串 进行替换时 不作语法检查 只是简单 的字符替换。 只有在编译时才对已经展 开宏名的源程序进行语法检查。 3 ) 宏名的有效范围是从定义位置 到文件结束。 如果需要终止宏定义的作 用域 可 以用 # u n d e f 命令 。例如 : #u n d ef P r 则该语句之后的P I 不再代表 3 1 4 , 这 样可以曼活控制宏定义的范围。 4) 宏定义时可以引用己经定义的 宏 名。例如 : #d ef i ne R 20 #d ef i n e P I 31 4 #d efi n e AL L PI R 5 对程序中用双引号扩起来的孛 符串内的字符 不进行宏的替换操作。 2 带参数的宏定义 为了进一步扩大宏的应用范围 在 定义宏时 还可以带参数。带参数的宏 定义的一般形式为: # d e fi n e标识 符( 参数表)宇符 串 它的作用是在编译预处理时。 将源 程序中所有标识符替换成字符串。 并且 将字符串中的参数用实际使用的参数 替换。例如 : # d e f in e S ( a b )( a + b ) 2 则源程序中如果使用了S ( 3 4 ) 在 编译预处理时将替换为( 3 + 4 ) 2 。 在 L E D 1 6 2字符 液 晶试 验 板 上 实现两数相加并输出结果, 变量的数据 类型用宏定义的缩写形式。 在我的文档中建立一个文件目录 【 c s l 0 l 。 然后建立 c s 1 0 u v 2的工程项 目 最后建立源程序文件f c s l 0c ) 。 输入 下面的程序 : # in c lu d e R E G 5 1 H 序号( 以下同】 : 1 # d ef i n e u c h u n s i g n e d c h a r 2 u c h a r c o d e S E G 7 f 1 0 I 一 O x c 0 0 x f9 0 X a 4 0 x b 0 0 x 9 9 0 x g 2 0 x 8 2 0 x f 8 0 x 8 0 0 x ,g O : 3 J , 一一一 = 4 一一: v o id m a in ( v o id ) 5 f u c h e r a b s u m; 7 a =5 5 ; 8 b : 2 0 o : 9 s u m= a + b ; il l 0 P 2 =S E G7 a u m 1 。 0 】 : 1 1 P 1 =S E G 7 【 ( s u m1 0 0 ) 1 0 ; # 1 2 P 0 =S E G7 【 s u m1 0 ; # 1 3 w h ile ( 1 1 、 1 4 1 5 编译通过 后 将生 成的 c s l O h e x 文件烧录到8 9 S 5 1芯片中。将芯片插 入到 L E D 1 6 2字符液晶试验板上 试 验板上接通 9 v电源 右边 3 个 L E D数 码管显示“ 2 5 5 。通过宕定义 我们发 现原来长 长的“ u n s ig n e d c h a r 现变成 了 u c h a r 。 是不是更 方便使 用了。 分析程序。 序号 1 I 程序解释 以下同) :包古头文件 RE G51 H 。 序号 2 :数据类型 。u n s ig n e d c h a r 用宕定 义为简写形式 u c h a r 。 序号3 : 数码臂0 9的宇 码。 序号4 : 程序分隅。 序号5 : 定义函数名为ma in 的主函教。 序号6 : m a in的主函数开始。 序号 7 : 定义无符号宇符型变量 a 、 b 、 s u m。 序号8 : a 破值5 5 。 序号9 b赋值 2 0 0 。 序号 1 0 : a 、 b 作加法运算 其和放 s u m 。 序号 1 1 : 取出s u m的首位教送 P 2 口显示。 序号 1 2 : 取出s u m的十位数送 P I口 显示。 序号 1 3 : 取出s u m的个位投送 P O 13 显示。 维普资讯 学习单 片机 序号 1 4 : 动态停机。 序号 1 5 : ma i n的主函数结束。 使用带参数的宏定义进行运算 , 结 果送 L E D 1 6 2 字符液晶 试验板显示。 在我的文档中建立一个文件 目录 ( c s l 1 ) , 然后建立 c s l 1 u v 2的工程项 目。 最后建立源程序文件( c s l 1 c o 输入下面的程序: # i n c lu d e 序号【 以下同) : 1 # d e f in e u c h a r u n s ign e d c h a r 2 # d e f in e S ( a , b )( a - b ) 3 3 u c h a r c o d e S E G7 1 0 】 = 1 0 x c 0 , 0 x f 9 , 0 x a 4 , 0 x b 0 0 x 9 9 0 x 9 2 , 0 x 8 2 0 x f 8 0 x 8 0 。0 x 9 0 。 ; 4 = = 一一一一一5 一一= v o i d m a in ( v o id ) 6 I i i7 u c h a r o u t ; 8 o u t =s ( 1 0 0 5 0 ) : 9 P 2 =S E G 7 o u tJ l 0 0 ; l O P 1 =S E G 7 【 ( o u t 1 0 0 ) 1 0 ; 1 1 P 0 =S E G 7 【 o u t 1 0 ; 1 2 w h il e ( 1 ) : 1 3 1 4 编译通过后。将生成的 c s l 1 h e x 文件烧录到 8 9 S 5 1芯片中,将芯片插 入到 L E D 1 6 2 字符液晶试验板上 。 试 验板上接通 9 V电源, 右边 3个 L E D数 码管显示“ 1 5 O ” 。 分析程序。 序号 1【 程序解释,以下同) :包含头文件 RE G5 1 H 。 序号 2 : 数据类型的宏定义。 序号 3 : 带参数的宏定义 序号4 : 数码管 0 9的字形码。 序号5 : 程序分隔。 序号 6 : 定义函数名为 m a in的主函数。 序号7 : ma i n的主函数开始。 序号 8 : 定义无符号字符型变量o u t 。 序号 9 : 使用参数宏 其结果送o u t 。 序号 1 O : 取出o u t 的百位数送 P 2口显示。 序号 1 1 : 取出o u t 的十位数送 P 1口显示。 序号 1 2 : 取出o u t 的个位数送 P 0 1:3 显示。 序号 1 3 : 动态停机。 序号 1 4 : m a i n 的主函数结束。 “ 文件包含”实际上就是我们前面 已经多次用到的# i n c l u d e命令实现的 功能, 即一个源程序文件可以包含另外 一 个源程序文件的全部内容。“ 文件包 含 ”不仅可 以包含 头文件 例如 : # i n c l u d e,还可以包含用 户 自己编写 的源 程序 文件 例如 : # i n c l u de。 文件包含预 处理命令 的一般形 式 为: # i n c l u d e或 # i n c l u d e “ 文件名” 上述两种 方式的 区别是 :前一 种形式 的文件 名用尖括 弧括 起来 , 系 统将 到包 含 C语言 库 函 数 的头 文件所在的 目录( 通 常是 K E I L目录 中的 in c l u d e子 目录 )中寻找 文件。 后一种形式的文件名用双引号括起 来 , 系统先在 当前 目录 下寻 找 。 若找 不到 , 再到其它路径 中查找。 “ ” 文件包含” 在使用时要注意 : 1 一个 # i n c lu d e命令只能指定一 个被包含的文件。 2 “ 文件包含” 可以嵌套。在文件 包含的嵌套时, 如果文件 1 包含了文件 2 。 而文件 2包含了文件 3 。 则在文件 1 也要包含文件 3 。 并且文件 3的包含要 写在文件 2的包含之前, 即文件 I 中的 “ 文件包含” 说明如下: # in c l u d e # in c l u d e “ 文件包含”命令为多个源程序文 件的组装提供了一种方法。 在编写程序 时。习惯上将公共的符号常量定义 、 数 据类型定义和 e x t e r n 类型的全局变量 说明构成一个源文件 。 并以“ H ” 为文件 名的后缀。 如果其他文件用到这些说明 时。 只要包含该文件即可。 无需再重新 说明, 减少了工作量。而且这样编程使 得各源程序文件中的数据结构 、 符号常 量以及全局变量形式统一 , 便于程序的 修改和调试。 “ 条件编译”命令允许对程序中的 内容选择性地编译 。 即可以根据一定的 条件选择是否编译。 条件编译的命令主要有 以下几种 形式 : 形式 1 # if d e f标识符 程序段 I # els e 程序段 2 # en dif 它的作用是当 “ 标识符”已经由 # d e f i n e定义过了 则编译“ 程序段 1 ” 。 否则编译“ 程序段 2 ” 。 其 中如果不需要 编译“ 程序段 2 ” 。 则上述形式可以变换 为: # if d e f标识符 程序段 1 # en di f 形式 2 # if n d e f标识符 程序段 1 # els e 程序段 2 #e n dif 它的作用是当 “ 标识符 没有由 # d e f i n e定义过。 则编译“ 程序段 1 ” 。 否 则编译“ 程序段 2 ” 。同样当无“ 程序段 2 ” 时。 则上述形式变换为: # if n d e f标识符 程序段 1 #e n dif 形式 3 # I f表达式 程序段 1 #e l s e e 程序段 2 #e ndif 它的作用是 当“ 表达式 ” 值 为真 时 。 编译 程序段 1 。 番则编译程序段 2。同样 当无程序段 2时, 则上 述形 式变换 为 : # 表达式 程序段 1 57 维普资讯 #e n di f 以上三种形式的条件编译预处理 结构都可以嵌套使用。 当# e l s e后嵌套 lf 时, 可以使用预处理命令 # e l if , 它相 当于 # e l s e# i f 。 在程序中使用条件编译主要是为 了方便程序的调试和移植。 在 C语言程序中。用户可 以根据 自己的需要对数据类型重新定义。使 用关键字 t y p e d e f 的定义方法如下: t y p e d e f已有的数据类型新的数据类 型名: 其中“ 已有的数据类型” 是指上面 所介绍的 C语言 中所有的数据类型。 包括结构 、 指针和数组等。 “ 新的数据类 型名” 可按用户自己的习惯或根据任务 需要决定。 关键字 t y p e d e f 的作用只是 将 C语言 中已有 的数据类型作了置 换。 因此可用置换后的新数据类型名来 进行变量的定义。例如: t y p e d e f i n t WO R D ; 定义 w o r d 为新的整型数据类型名 一 般而言 。 对 t y p e d e f 定义 的新 数据类型用大写字母表示 。以便与 C语言 中原有 的数据 类型相 区别 。 另外还要注意 。 用 t y p e d e f 可 以定义 各种新 的数据类型名 。但不能直接 用来定义变量。t y p e d e f 只是对已有 的数据 类 型 作 了一 个 名字 上 的置 换 。并没有创造出一个新的数据类 型 。例 如前 面例子 中 的 WOR D, 它 只是 I n 1 类型 的一个新名字而已。 采 用 t y p e d e f 来 重新定 义数 据类 型有 利于程序的移植 。同时还可 以简化 较长的数据类型定 义 ( 如结构数据 类型等 ) 。在 采用 多模块 程序设 计 时,如 果不同的模块程序源文件 中 用到同一类型的数据时 ( 尤其是像 数 组 、 指针 、 结构 、 联合 等复杂 数据 类型 ) 。经 常用 t y p e d e f 将这些数据 重 新 定 义 并放 到 一 个 单独 的 文件 中 。 需 要 时 再 用 预 处 理 命 令 # i n c l u d e将它们包含进来 。 学习单 片机 用 t y p e d e f 重新定义数据类型 , 变 量 v a l 赋值后送 L E D 1 2 8 6 4图形液晶 试验板上的 8个 L E D显示 ,模拟彩灯 闪烁。 在我的文档中建立一个文件 目录 ( c s 1 2) 。 然后建立 c s l 2 u v 2的工程项 目。 最后建立源程序文件( c s 1 2 c o 输入下面的程序: # in c l u d e 序号( 以下同) : 1 t y p e d e f u n s ig n e d c h a r U8 一 B YT E ; 2 t y p e d e f u n s ig n e d i n t U1 6 _ WOR D; 3 v o i d d e l a y ( U 1 6 _ WOR D k ) : 4 = ; = ; 一一一= 5 = = v o i d m a in ( v o i d ) 6 I| | U8 一B Y TE v a l ; 8 w h i le ( 1 ) 9 1 0 v a l = O x 5 5 ; 1 1 P O = v a l ; 1 2 d e l a y ( 5 0 0 ) ; 1 3 v a l = O x a a ; 1 4 P O = v a l ; 1 5 d e l a y ( 5 0 0 ) ; 1 6 1 , 1 7 1 8 一 一 一一 一 一 一 一 1 9 一 一 v o id d e la y ( U 1 6 WO R D k ) 2 0 2 1 U 1 6 _ WOR D i ,j : 2 2 f o r ( i = O : i k : i+ + ) f 2 3 f o r ( j = O ; j 1 2 1 l j + + ) 2 4 2 5 2 6 编 译通 过 后 。将 生 成 的 c s l 2 h e x文 件烧 录 到 8 9 S 5 1芯片 中 , 将 芯 片 插入 到 L E D 1 2 8 6 4图形 液 晶 试验板 上 ,拔 下 S X排针 上的 8个 短路 块。试验板 接通 5 V电源后 8 个 L E D的奇数 位点 亮 0 5秒 , 然后 偶数位又点亮 0 5秒 。 反 复循环 煞 是好看。 我们对程序进行分析。 序号 1( 程序解释以下同) :包含头文件 RE G5 1 H 。 序号 2 : 用t y p e d e f 重新定义数据类型 定义 U8 _B Y T E为 8 位长度的无符号字符型数据 类型 。 序号 3 : 用t y p e d e f 重新定义数据类型。 定义 U 1 6 _ WOR D为 1 6 位长度的无符号整型数 据类型。 序号 4 : 延时子函数声明。 序号 5: 程 序分 隔。 序号 6 : 定义函数名为 m a in的主函数。 序号 7 : m a in的主函数开始。 序号 8 : 定义无符号字符型变量v a l 序 号 9: wh i le循环语 句进行 无限循 环。 序号 1 0 : w h i le循环语句开始。 序号 1 1 : v a l 赋值 0 x 5 5 。 序号 1 2 : v a l 送 P O口 显示。 序号 1 3 : 调用0 5 秒延时子函数。 序号 1 4 : v a l 赋值 O x a a 。 序号 1 5 : v a l 送 P O口显示。 序号 1 6 : 调用0 5 秒延时子函数。 序号 1 7 : w h il e 循环语句结束。 序号 1 8 : ma i n的主函数结束。

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论