已阅读5页,还剩107页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1 课程的基本要求 通过本课程的学习 应该掌握C51的程序设计语言 掌握8051的中断 定时器 定位器 串行通信等内部资源的C编程方法 正确理解单片机的C语言模块化设计方法 了解8051外部扩展资源的C程序设计方法 单片机的C语言和程序设计 2 6 2C语言与MCS 51单片机 6 3C51运算符 表达式及其规则 6 4C51数据与运算 6 5C51函数 6 6库函数简介 6 78051内部资源的C51编程 6 1概述 3 6 1单片机的C语言和程序设计 对于8051及其兼容单片机 目前有四种语言支持 汇编语言 BASIC语言 PL M语言和C语言 C语言是一种编译型程序设计语言 它兼顾了各种高级语言的特点 并具备汇编语言的功能 与汇编语言相比 C语言有很多的优点 不要求了解单片机的指令系统 仅要求对8051的存储器结构有初步了解 寄存器分配 不同存储器的寻址及数据类型等细节可由编译器管理 程序有规范的结构 函数库提供很多的标准程序 4 单片机的C语言和标准C语言的比较 C51与标准的C语言定义的库函数不同 C51中的数据类型和标准C的数据类型也有一定的区别 C51变量与标准C中变量的存储模式不一样 C51与标准C的输入 输出处理不一样 C51与标准C语言在函数使用方面有一定的区别 5 学习重点 学习C51程序设计 重点掌握标准C语言和C51的区别 主要内容 C51的数据类型和存储类型 基本运算 构造数据类型 函数以及程序设计中的其他一些问题等内容 6 6 2C语言与MCS 51单片机 6 2 1C语言编译器与程序开发过程 7 6 2 2C51程序结构 全局变量说明 可被本程序的各函数引用 函数1说明 函数n说明主函数main 局部变量说明 只能在本函数内引用 执行语句 包括函数调用语句 形式参数表 函数1 形式参数说明 局部变量说明 只能在本函数内引用 执行语句 包括调用其他函数语句 形式参数表 函数n 形式参数说明 局部变量说明执行语句 8 例6 1程序如下 include include defineCON8279XBYTE OX6EFF defineucharunsignedcharvoidINIT79 8279初始化 voidmain ucharxdata p ucharcodeTAB 0 xC0 0 xF9 0 xA4 0 xB0 0 x99 0 x92 0 x82 0 xF8 0 x80 0 x90 0 1 2 3 4 5 6 7 8 9 INIT79 P 注释部份 这部分内容不会被编译 也不被执行 编译预处理程序编译 执行前系统自动进行的特殊处理特点 以 开头结束处无分号 defineCON8279XBYTE 0 x6EFF define 宏定义命令CON8279 符号常量0 x6EFF 宏体 可以是一个表达式 如3 4 作用 用简单符号代表宏体部份内容意义 直观 多次使用 便于修改注意 define可出现在程序的任一位置 作用范围 由此行到程序末尾 宏定义不是C语句 不必在行末加分号 否则会连分号一起置换 include标准方式只按标准方式 系统存放C库函数头文件所在目录 查找所要包含的文件对CX51 默认只在 C51 include目录下查找 include 先在源文件所在目录找指定头文件 若无再按标准方式找 更保险 9 小结CX51语言程序的基本特点 CX51语言是一种函数式语言 其程序基本组成是函数每个CX51程序必须有一个 也只能有一个主函数main不管主函数在程序中的位置如何 程序执行总是从主函数开始所有变量必须先定义 规定数据类型 后使用每个语句必须用分号 结束 注意是 每个语句 而不 每行语句 编译预处理命令不是语句 行末不能用分号结束 Cx51语言本身没有输入 输出语句 其输入 输出功能须通过调用标准函数通过串行口实现使用系统提供的标准库函数或其他文件提供的现成函数时 必须使用 文件包含 10 6 3C51运算符 表达式及其规则 6 3 1算术运算符及表达式 1 基本的算术运算符 C51语言的算术运算符一共有5种 加法运算符 减法运算符 乘法运算符 除法运算符 模 取余数 运算符 例 14 4 0 x02 11 2 自增 自减 运算符 1 当 j 或 j 时 是先将变量j的值加1 或减小1 再取变量值 2 当j 或j 时 是先取变量值 再把变量的值加1 或减1 例如 inti j k i 4 j i j值为5 i值也为5 i 5 k i k值为5 i值为6 12 3 算术表达式及优先级和结合性 单目运算符优先级高于双目运算符 双目运算符优先级高于双目赋值运算符 13 14 15 6 3 2关系运算符 关系表达式 C51语言共有6种关系运算符 大于 大于等于 等于 不等于 16 6 3 3逻辑运算符及表达式 C51提供三种以逻辑量为操作数的逻辑运算符 逻辑非 逻辑与 逻辑或 例如 若a 3 b 4则 a 0 因为a 3为非0数 即为逻辑1 a b 1 因为a b为非0数 是逻辑1 a b 1 因为a b为非0数 是逻辑1 a b 0 因为 a优先于 17 6 3 4位运算符及表达式 C51语言提供6种位运算符 所有的位运算符都是针对整型操作数 而不能针对实型数据 则 a b 2 按位或 按位异或 按位取反 右移 左移 18 6 3 5赋值运算符 赋值运算符即是把运算符右侧操作数赋给左侧的操作数 即变量名 表达式 当 两侧类型不一致时 系统自动将右边表达式的值转换成左侧变量的类型 再赋给该变量 具体规则如下 当整型变量 实型数据时 实数的小数部分被舍去 当实型变量 整型数据时 变量中的数值为浮点形式 当短字节整型变量 长字节整型数据时 则长字节整型数据的低位数据赋给短字节整型变量 当长字节整型变量 短字节整型数据时 则短字节整型数据赋给长字节整型变量的低位数据 而长字节整型变量的每一位高位数据被赋给短字节整型数据的符号值 19 赋值语句 作用 使变量获得具体的运算值 语句形式变量名 表达式 常量 变量 函数 算式及其混合 lower 0 变量lower赋初值 s sin x 求sin x 注意 函数sin 在头文件math h中定义 所以程序开头处必须加上一行所谓 文件包含 include变量赋初值亦可在数据类型定义时进行 intlower 0 x 把变量声明语句与赋值结合在一起的语句 术语上称为 初始化语句 20 2 复合赋值运算符 凡是有两个运算对象的运算符都可以与赋值运算符 一起组成复合运算符 复合赋值运算符有以下10种 例如 a b等价于a a b a 4等价于a a 4 21 6 4C51数据与运算 6 4 1数据类型 22 80C51单片机采用哈佛结构 RAM与ROM分开 SFR与片内RAM统一编址 KEILCX51编译器将变量 常量定义成不同的存储类型 data bdata idata pdata xdata code 的方法 将它们定位在不同的存储区中 8051的变量的存储类型定义为 存储类别 变量类型 存储类型 变量名其中存储种类与存储类型为可选项 存储类别主要有四种 自动 auto 默认的存储种类 外部 extern 静态 static 和寄存器 register 存储类型主要有 data bdata idata pdata xdata code等 23 6 4 2变量及其数据类型 1 变量的说明 变量的格式如下 存储类说明 类型说明符 修饰符 标识符 初值 其中 部分可有可无 1 类型说明符 char int long 2 标识符 3 变量初始化 4 存储类说明符 a auto 自动存储类 堆栈 默认存储类 b register 寄存器存储类 c extern 外部存储器类 d static 静态存储类 24 5 修饰符由于8051存储空间的多样性 C51提供了修饰存储空间类型的修饰符 用于指明定义的变量应分配在什么存储空间中 C51存储空间类型的修饰符有data idata pdata xdata code bdata 无修饰符时 取决于编译时选用的存储方式 25 存储类别决定变量的 寿命 何时 生 何时 灭 一个完整的变量说明格式如下 存储类别数据类型存储类型变量名如staticintdatax y C51程序的存储类别有 26 register型 寄存器型 存取速度快 一般只允许2 3个 且限于char型和int型 通常用于循环变量 auto型 自动变量型 优点 同一内存区可被不同变量反复使用 以上两种变量均属于 动态存储型 即调用函数时才为这些变量分配单元 函数调用结束其值自动消失 static型 静态变量型 程序执行开始至结束 始终占用该存储空间 extern型 外部变量型 同上 其值可供其他源文件使用以上两种均属于 静态存储 性质 即从变量定义处开始 在整个程序执行期间其值都存在 27 从变量的存在时间来看 可分为静态存储变量和动态存储变量 静态存储变量是指该变量在程序运行期间其存储空间不变 全局变量为静态存储变量 动态存储变量是指该变量的存储空间不确定 在程序运行期间需要动态地为该变量分配存储空间 局部变量为动态变量 变量的生存期静态存储变量 与程序 共存亡 动态存储变量 与函数 共存亡 寄存器变量 同动态变量 未说明存储类别时 函数内定义的变量默认为auto型函数外定义的变量默认为extern型 28 2 变量的数据类型 对于FranklinC51编译器 只有bit和Unsignedchar两种数据类型可以直接支持机器指令 为了提高单片机的数据处理速度 在编制C51程序时一定要对变量和数据类型进行慎重的选择 1 位变量 bit bit是C51特有的数据类型 其值为 1 ture 或0 false bit类型可用的修饰符有bdata data idata 但最好是bdata修饰符例如 bdatabitmark1databitmark2idatabitmark3 29 2 字符变量 char 字符变量的长度为一个字节 标识符为char 128 127 或unsignedchar 0 255 3 整型变量 int 整型变量 int 的长度为二个字节 标识符为int unsignedint 整型变量值0 x5678 30 4 长整型变量 longint 长整型变量的长度为四个字节 标识符为unsignedlong long 5 浮点型变量 float 浮点型变量长度为四个字节 C51的浮点变量数据类型格式具有24位精度 尾数的高位始终为1 位的分布为 1位符号位 8位指数位 23位尾数位 例如 浮点型变量值 12 5的十六进制表示为0 xC1480000 31 6 4 4数据的存储 1 存储类型与存储空间 32 片内数据存储区 data bdata与idata当使用data与bdata存储类型定义时 CX51将它们定位在片内RAM 它存取数据快 但资源有限 片内RAM存放临时性变量或使用频率较高的变量 片外数据存储区 pdata与xdatapdata能访问1页 256字节 的外部RAM 主要用于紧凑模式 CompactMode 当使用xdata存储定义类型 其最大可寻址范围为64K 程序存储区 code当使用code存储类型定义数据时 编译器会将其定义在代码空间 ROM或EPROM 33 如 defineucharunsignedchar 定义符号常量uchar uchardataa1 字符变量a1定位在8051的片内数据存储区中 bitbdataflag 位变量flag定位在8051的片内数据存储区中的可位寻址区 floatidatax y 浮点变量x y定位在8051的片内数据存储区并只能通过间接寻址来访问 ucharxdatas 3 4 7 2 12 8 无符号字符数组s定位在片外RAM ucharcodetable 10 0 x3f 0 x06 0 x5b 0 x4f 0 x66 0 x6d 0 x7d 0 x07 0 x7f 0 x6f 无符号字符数组table定位在片外ROM 34 2 存储模式 35 6 4 5MCS 51结构的C51定义 1 特殊功能寄存器 SFR 的C51定义 sfr特殊功能寄存器名 该特殊功能寄存器的地址常数 例如 sfrSCON ox98 串口控制寄存器地址98H sfrTMOD ox89 定时 计数器控制寄存器地址89H 2 I 0口的C51定义 1 片内I O口用关键字sfr定义 例如 sfrP1 0 x90 定义P1口 地址90H 36 2 片外扩展I O口的硬件译码地址 看作片外数据存储单元 用 define语句定义 例如 include definePORTAXBYTE 0 xffc0 将PORTA定义为外部I O口 地址为0 xffc0 长度为8位 3 特殊位 sbit 的C51定义 1 已定义的特殊寄存器名 基地址上特殊位的位置 0 7 当特殊寄存器的地址为字节 8位 时 可使用这种方法 例如 sfrPSW 0 xd0 定义PSW寄存器地址为0 xD0 sbitOV PSW 2 定义OV位为PSW 2地址为0 xD2 sbitCY PSW 7 定义CY位为PSW 7地址为0 xD7 37 2 寄存器基地址 基地址上特殊位的位置 0 7 以0 x80 0 xFF之间 并能被8整除的整常数作为基地址 例如 sbitOV 0 xD0 2 OV位地址为0 xD2 sbitCY 0 xD0 7 CY位地址为0 xD7 3 0 x80到0 xFF之间的位绝对地址例如 sbitOV OxD2 sbitCY OxD7 在主程序前只要加上 include 即包含对上述特殊寄存器的定义 38 4 对存储器和外部扩展I O的绝对地址访问 利用库函数中的绝对地址访问的头文件absacc h可对不同区域的存储器和外部扩展I O口进行访问 该头文件中的函数有 CBYTE 地址 访问code区字符型 DBYTE 地址 访问data区字符型 PBYTE 地址 访问pdata区或I O口字符型 XBYTE 地址 访问xdata区或I O字符型 例如 若有宏定义 defineDAC0832XBYTE 0 x7FFF 那么程序中DAC0832出现的地方 就是对地址为7FFFH的外部RAM单元或I O口进行访问 39 还有访问数据类型为int型的4个函数 CWORD DWORD PWORD和XWORD 它们的访问区域同上 例如赋值语句 XWORD 0 0 x9988 例如 将内部RAM30H单元的内容送20H单元的程序如下 includevoidmain DBYTE 0X20 DBYTE 0X30 40 例如 CPU片外RAM清零 ORG0000HLJMPMAIN 跳转到主程序ORG0030HMAIN MOVDPTR 0000H 送RAM地址LOOP MOVA 00H MOVX DPTR A 往RAM存00HINCDPTR 地址加1MOVA DPL 判断RAM地址是否已经到达尾地址CJNEA 00H LOOPMOVA DPHCJNEA 20H LOOPWAIT NOP 循环等待JMPWAITEND 41 C程序 include include defineucharunsignedchar defineuintunsignedintvoidmain uinti for i 0 i 0 x2000 i XBYTE i 0 42 6 4 6C51的指针 6 4 6 1指针的基本概念 1 变量的地址 变量包含变量名和变量的值两个含义 前者为数据的标识 内存地址 后者为数据的内容 即为它们所占连续的内存单元的最低字节单元的地址 例如 Longa 0 x12345678 单元地址a的单元200178200256200334200412变量a的地址为2001H 43 对于内存中变量的存取有两种方式 1 直接存取例如 inta 10根据变量名与内存单元地址的对应关系 找到变量a在内存中的位置 44 2 间接存取 例如要存取变量a时 要以将变量a的地址放入内存单元 假设放在2000 2001两个字节中 然后从地址1000 1001的两字节内存单元中存取变量的值10 在这里 存放在地址2000和2001内存中的 实际就是指向变量a的指针变量a pointer 45 2 指针变量的概念 变量的指针 简而言之即是变量的地址 对上面的变量a 它的指针就是内存中存储地址1000h 指针变量 是指专门用来存放另一个变量地址 指针 的变量 它的值是指针 提到的地址2000h 2001h两字节中存放的变量a pointer就是一个指针变量 它的值就是变量a的地址1000h 46 1 指针变量的定义指针变量定义的一般形式为 存储类说明符 类型说明符 修饰符 指针定位修饰符 标识符 地址初始值 中的部分可有可无 存储类说明符 类型说明符 与一般变量的说明相同 修饰符是 为指针指向的对象定位存储空间的说明 指针定位修饰符 是给指针本身定位所在存储空间 一般不予以指定 例如 int a类型说明符标识符Unsignedchardata xdataxx 外部RAM指针指向内部RAM数据区 类型说明符修饰符指针定位修饰符 47 2 指针变量的使用 1 取地址运算符当把某变量的地址赋给一个指针变量后 就是说该指针变量指向该变量例如 inta pointer b pointer a 执行了pointer a语句后 指针pointer指向变量a 即指针变量pointer对应的内存单元中装入变量a对应的内存单元地址 例如pointer 300 是非法的 2 取指向运算符即取指针变量所指向的变量的值 例如 b pointer 相当于b a 48 和 都是单目运算符 优先级相同 且结合顺序是自右至左的 如 pointer 等价于 pointer 而不是 pointer 实际编程和运算中 变量地址和指针变量的地址是不可见的 变量 指针变量和内存单元地址三者间的对应关系是由编译器决定的 程序设计人员只是通过 和 运算符来使指针变量与变量建立起联系 6 6 6 4指针与数组 1 数组指针和指向数组的指针变量 一般把数组的起始地址放到一个指针变量中去 因此 我们把数组的起始地址称为数组指针 而把一个存放数组起始地址的变量称作指向数组的指针变量 简称数组指针变量 49 其定义格式如下 类型说明符 标识符 或 类型说明符 标识符 例如 inta 20 包含20个整型元素的数组 int p 指向整型数据的指针 把指针变量指向数组 表示方法为 p a 0 或p a 此时p为数组指针变量 2 指针和一维数组 1 一维数组的地址 50 一维数组在内存中的存放 从下标为0的元素开始 连续存放 下标为0的元素的地址即为整个数组的地址 例如 inta 4 0 x5678 0 x1234 0 x5678 0 x1234 数组a的地址为a 0 的地址 200A 51 2 指针的使用 要用指针变量来处理一维数组只需将一维数组的地址赋给一个指针变量即可 例如 int p a 4 p a 数组a的地址赋给指针变量p 即p指向了数组a 则 p a 0 对指针变量 其算术运算的特殊性表现在 1 只能加减 不能乘除 2 当某指针变量指向一个数组时 对该指针变量加l则不管这个数组是什么数据类型 这个指针变量都指向数组的下一个元素 只要没越界 如 做完p 运算后 p就指向数组a的下一个元素 即a 1 52 数组元素的引用可以采用两种方法 下标法和指针法 下标法 例如 inta 10 p p a 数组的第n个元素可表示为 a n 或p n 指针法 数组的第n个元素可表示为 a n 或 p n 注意 数组名可看成是一个指针常量 其值不能改变 例6 2用选择法对数组进行排序 从小到大 方法思路 设数组长度为5 令i 0 1 寻找a i 及后面的元素中最小元素 a k 2 若k i 转 4 3 若k i 交换a i 与a k 的值 4 i 若i 4 转 1 否则结束 53 main inta 5 15 10 2 78 5 i k j temp for i 0 i 4 i k i for j k 1 j 5 j 1 步 if a j a k k j if k i 3 步 temp a i a i a k a k temp for i 0 i 5 i printf 5d a i 54 3 指针与二维数组 设有一个二维数组a 它有3行4列 定义为 staticinta 3 4 1 3 5 7 9 11 13 15 17 19 21 23 对这个数组理解如下 a是数组名 数组包含3个元素 a 0 a 1 和a 2 每个元素又是一个一维数组 包含4个元素 4列 如a 0 代表的一维数组又包含4个元素即 a 0 0 a 0 1 a 0 2 和a 0 3 55 a 0 代表第0行中第0列的地址 即 a 0 0 相应地 a 1 a 1 0 a 2 a 2 0 a 2 3 a 2 3表示 a 0 1 a 0 1 a 1 3 a 1 3 既然a 2 3和 a 2 3是元素a 2 3 的地址 a 2 3 或者 a 2 3 也就是元素a 2 3 的值 56 例6 3 用指针变量输出数组元素的值 程序如下 main inta 2 2 3 4 5 6 p for p a 0 p a 0 4 p printf 5d p 4 指针数组和指向指针的指针变量 1 指针数组 其定义的一般形式是 类型说明符 数组名 元素个数 57 例6 4用选择法对10个字符串排序 程序如下 include stdio h main charch 10 81 p 10 p1 p指针数组 包含10个指针元素 inti i k printf Enter10strings n for i 0 i l0 i 输入10个字符串 gets ch i for n 0 n 10 n 使p的10个指针元素分别指向上面10个字符串 p n ch n for i 0 i 9 i k i for j i 1 j 10 j if strcmp p j p k 0 k j if k i p1 p k p k p i p i p1 for i 0 i 10 i puts p i 58 2 指向指针变量的指针 如果一个指针变量用来存放另一个指针变量的地址 这个变量就称为指向指针变量的指针变量 其定义的一般形式是 类型说明符 变量名 其中 类型说明符是指被指向的指针变量的类型 如 char p p1 p 5 指向结构类型数据的指针 指向结构变量的指针变量的定义形式为 struct结构原型名 指针变量名或struct 结构原型名 结构成员说明 指针变量名 59 例如 有一个描述学生自然情况的结构体structstudent charname 10 charsex Unsignedlongnum inteng intmath intphys 定义一个指针变量 指向结构体变量stul 可表示为structstudent p stul 这里变量p就是一个指向结构体变量的指针变量 例如 p p指向结构体变量stul 即 p就是stul 60 取结构体变量stul的成员可有三种方法 1 stul num stul eng2 p num p eng3 利用运算符 p num p eng 2 指向结构体数组的指针变量结构体指针除了可以指向结构体变量 还可以指向结构体数组 例如 structstudent p stu2 20 p stu2 p指向结构体数组stu2 这样p指向数组stu2的第一个元素stu2 0 即 p stu2 0 此时若p 则p指向数组stu2的第二个元素 即 p stu2 1 61 6 4 6 4C51的指针类型 C51的指针类型 若未指定它所指向的对象的存储类型 则该指针变量被认为是一般指针 需占用3个字节 若指定了它所指对象的存储类型 则该指针变量被认为是基于存储器的指针 这种指针只需1 2个字节 1 基于存储器的指针 基于存储器的指针是在说明一个指针变量时 指定它所指向的对象的存储类型 例如 charxdata px 2 一般指针在函数调用中 函数的指针参数需要用 一般 指针 一般指针的说明形式为 char pz 62 这里没有指定指针变量pz所指向的变量的存储类型 pz处于编译模式默认的存储区 长度为3个字节 格式为 其中 存储类型由编译模式决定 不同的存储区域的编码如下 63 例如 要将数值0 x41写入地址为0 x8000的外部数据存储器 则这样写即可 includeXBYTE 0 x8000 0 x41 其中XBYTE是一个指针 它是在头文件absacc h中定义的 定义如下 defineXBYTE unsignedchar 0 x20000L XBYTE被定义为 unsignedchar 0 x20000L 为一般指针 其存储类型为2 即为xdata类型 偏移量是0000 这样 XBYTE成为指向外部数据存储器的零地址单元的指针 而XBYTE 0 x8000 则表示外部数据存储器的0 x8000单元 64 6 5C51函数 普通函数分为库函数和用户定义函数 6 5 1函数的定义 1 无参数函数的定义方法返回值类型标识符函数名 函数体 无参数函数一般不带返回值给调用函数 返回值类型设为void 即无类型 65 例6 5 设计一程序 延迟一段时间 再顺序地将P1 0 P1 7 置1 includevoiddelay inta 10000 while a voidmain chara 1 do P1 a a a 1if a 0 a 1 delay while 1 66 2 有参数函数的定义方法返回值类型标识符函数名 形式参数列表 形式参数说明 函数体 例6 6 编写函数求三个整数中的最大值intmax x y z intx y z inta x if y x a y if z a a z return a 67 形式参数也可以用下面的形式进行说明intmax intx inty intz inta x if y x a y if z a a z return a 6 5 2函数的说明 1 函数说明格式 在C51程序中 除主函数和库函数外 用户自定义的函数在被调用前都要进行说明 作为规范化的C51程序 在主函数main 之前 应对自定义的函数要作原型说明 而在main 函数后进行被调用函数的定义性说明 68 函数原型说明格式如下 extern类型说明符标识符 形参表 reentrant usingn 存储模式 函数定义性说明格式如下 存储类说明符 类型说明符标识符 形参表 reentrant interruptm usingn 存储模式 函数体 在上面格式中 的内容不是必需的 2 函数说明 1 存储类说明符 extern 使用extern说明符的函数作用域是全程序存在的 在定义性说明时 在不加存储说明的情况下 函数的默认存储类特性为extern 69 全局变量 有效作用范围 从定义变量位置开始直到本源文件结束如果需要将全局变量的作用范围扩展至整个源文件 法1全部在源文件开头处定义法2在引用函数内 用extern说明法3在源文件开头处 用extern说明 例三 求程序运行结果externintx y voidmain void unsigendinti j i x j y intx 100 y 200 结果 i 100 j 200 去掉第一行试试 如果要将全局变量作用范围扩展到其他源文件 只需在使用这些变量的文件中对变量用extern加以说明 70 file2 cexternfun1 intx 定义外部函数fun1 file3 cexternfun2 inty 例6 7 外部函数file1 cexternfun1 fun2 说明本文件要用到main 其他文件中的函数 fun1 a fun2 b 71 2 类型说明符所谓类型是指函数返回值的类型unsignedchar 字符型char 字符型unsignedint 整型int 整型unsignedlong 长整型long 长整型float 浮点型struct 结构体union 共用体void 无返回值bit 位变量 72 3 函数标识符函数标识符即函数名 函数名 带或不带返回值的函数 函数名 返回指针的函数 函数名 void 定义带或不带返回值的无参数函数指针 函数名 形参表 定义带或不带返回值的有参数函数指针 函数名 void 定义返回指针的无参函数指针 函数名 形参表 定义返回指针的有参函数指针 73 4 形参表形参表是传入函数的形式参数表 5 附加修饰符部分a reentrant使用这个修饰符说明该函数为再入函数 所谓再入函数就是允许被嵌套调用的函数 调用可发生在任何时候 即使是在中断过程中 在实时处理的应用问题中常常需要再入函数 由于MCS一51缺乏合适的寻址方法 使用栈结构相对来说是必要的 因而应尽量少用再入函数 定义一再入函数的语法如下 返回值函数名 参数 模式 reentrant interruptn usingn 例如 intcalc chari intb reentrant intx x table i return x b 74 b interruptn interrupt 后接一个0 31的常整数 不允许使用表达式 中断不允许用于外部函数 它对函数目标代码的影响下 当调用函数时 SFR中的ACC B DPH DPL和PSW 当需要时 入栈 自动完成 如不使用寄存器组切换 甚至中断函数所需的所有工作寄存器 Rn 都入栈 函数退出前 所有的寄存器内容出栈 函数由8051控制命令 RETI 终止 75 externbitalarm intalarm count voidfalarm void interrupt1using3 alarm count 2 alarm 1 76 FUNCTIONfalarm BEGIN 0000COEOPUSHACC0002CODOPUSHPSW SOURCELINE 5 SOURCELINE 60004E500RMOVA alarm count 01H000625E0ADDA ACC0008F500RMOValarm count 01H A000AE500RMOVA alarm count000C33RLCA000DF500RMOValarm count A SOURCELINE 7000FD200ESETBalarm SOURCELINE 80011D0D0POPPSW0013D0E0POPACC001532RETI FUNCTIONfaiarm END 77 开发中断过程时有下列规则 不能进行参数传送 无返回值 如果想定义一个返回值将产生错误 然而 如果返回整型值编译器将不产生错误信息 编译器会识别对中断过程的直接调用并拒绝它们 编译器从绝对地址8n 3处产生一个中断向量 其中n为中断号 该向量包括一个到中断过程的跳转 78 C 51编译器允许0 31个中断 究竟允许哪些中断依赖于使用的8051系列芯片 编译器不能检查 下列中断及其相关地址为8051控制器所知 0 EXTERNAL 00003H1 TIMER COUNTER一0000BH2 EXTERNAL 10013H3 TIMER COUNTER一1001BH4 SERIALPORT 0023H 中断过程调用的函数所使用的寄存器组必须与中断过程相同 当没有使用 using 指令时 编译器会选择一个寄存器组作绝对寄存器访问 当子程序使用另一寄存器组时会发生错误 用户必须保证按要求使用相应寄存器组 C编译器不会对此检查 79 usingn8051有4个寄存器组 每组有8个寄存器R0 R7 使用修饰符usingn可以指定在本函数内部使用的寄存器组 其中n的取值为0 3 表示通用寄存器组号 using 不允许用于外部函数 它对函数的目标代码影响下 函数入口处将当前寄存器保存入栈 指定的寄存器不会改变 函数退出前寄存器组被恢复 using 定义对于返回一个寄存器内的值的函数是无用的 编程者必须十分小心以保证任何寄存器组切换都只在仔细控制的区域发生 80 存储模式函数的存贮模式决定了函数的参数和局部变量所处的地址空间 处于SMALL模式下的函数的参数和局部变量位于内部RAM中 LARGE和COMPACT模式下的函数则使用外部RAM 没有明确指定存贮器模式的函数使用当前编译时的模式 另外 也可为每个函数明确指定一个存贮模式 而不依赖于编译模式 例如 pragmalarge 按大模式编译 externintcalc chart intb smallreentrant 修饰为小模式 externintfunc inti floatf large 修饰为大模式 intfun1 intI inty 因编译取得大模式 return calc i y 2 81 6 5 3函数的调用 函数调用的一般形式为 函数名 实参列表 对于有参数类型函数 若实参列表包含多个实参 则各参数之间用逗号隔开 对于形参与实参需注意 1 实参与形参在数量 类型和顺序上要一致 2 实参可以是常量 变量或表达式 3 实参对形参的数据传递是单向的值传逆 即只能实参形参 而不能由形参实参 函数的调用方式即 把被调函数作为主调函数的一个语句 如 printf 其中被调函数printf 作为一个语句 只是完成一个固定的操作 而无返回值 82 以函数表达部分的调用方式即把函数放在一个表达式中 被调函数以一个运算对象的身份出现在一个表达式中 例如 m 5 min n k 此时要求被调函数中要带有return语句 以返回一个明确类型的数值 参与表达式的运算 83 3 被调用函数的说明 程序中调用了库函数 include include 程序中调用了本文件外的自定义函数 如果不是在本文件中定义的 就要在程序开始用extern修饰符进行原型声明 例入 include externvoiddefine1 void 即在头文件intin h中定义了一个函数define1 在源程序中如果使用这个函数 除了用include命令包含头文件intin h外 还要在程序开始用extern进行原型声明 84 程序中调用了本文件的函数如果自定义函数与调用它的函数在同一个文件中 则要在主程序中对被调函数返回值的类型作说明 例6 8 main intsub 对被调函数返回值的类型说明 inta b c a 15 b 10 c sub a b intsub x y intx y intz z x y return z 85 4 函数的参数 1 普通变量作函数参数 例6 9 voidchange intm intn intk k m m n n k main inta 5 b 8 printf a d b d n a b change a b printf a d b n a b 程序运行结果 a 5 b 8 该程序的初衷 是希望交换变量a和b的值 但由于函数参数的传递是单向的 即实参 形参 而形参不能回传给实参 故形参m n的改变不能影响主函数的变量a b 86 2 指针变量作为函数参数 change p1 p2 int p1 p2 intp p p1 p1 p2 p2 p main inta 5 b 8 int point1 point2 point1 程序运行结果 a 8 b 5 例6 10 87 3 数组作函数参数 例6 11 求一数组中的最小值intmin inty intm intn k y 0 for n 1 n m n if y n k k y n returnk main intx 5 i printf input5 number n for i 0 i 5 i scanf d 88 6 5 4 4函数的嵌套调用与递归调用 例6 12 intfun1 intx1 return3 x1 2 intfun2 intx2 intz z x2 5 x2 5 return z intfun3 inta intb intresult result fun1 a fun2 b returnresult main intadd number add number fun3 7 5 printf d add number 89 2 函数的递归调用 例6 13 求n 设函数fac n n 则 fac n n fac n 1 n 1 1 n 0 1 90 源程序如下 intfac n reentrant intn intresult if n 0 n 1 return1 elseresult n fac n 1 returnresult main intatul result atul result fac 10 printf d atul result 91 6 5 5用函数指针变量调用函数 例6 14 intfun1 x y intx inty return x y intfun2 x y intx intyreturn x y main int p int int 函数指针变量定义 inta b scanf d 92 在使用指针变量调用函数时应注意 对指针变量 p int int 若不对其赋值时 它便不固定指向某一个函数 在程序中把哪个函数的入口地址赋值给它 它就指向哪个函数 因此使用指针变量调用函数可以做到 通过不同的赋值来调用不同的函数 用指针变量调用不同的函数 函数参数的个数 类型 顺序都应相同 用指针变量调用函数时 指针变量进行的数学运算 P P 等 是没有意义的 93 6 6库函数简介 6 6 1MATH H数学函数 函数名 abs原型 extornintabs intval externcharabs charval externfloatabs floatval externlongabs longval 函数名 exp log log10原型 externfloatexp floatx externfloatlog floatx externfloatlog10 floatx 94 函数名 sqrt原型 externfloatsqrt floatx 功能 sqrt返回x的正平方根 函数名 cos sin tan原型 externfloatcos floatx externfloatsin floatx externfloattan floatx 95 6 6 2ABSACC H 绝对地址访问 函数名 CBYTE DBYTE PBYTE XBYTE原型 defineCBYTE unsignedchar 0 x50000L defineDBYTE unsignedchar 0 x40000L definePBYTE unsignedchar 0 x30000L defineXBYTE unsignedchar 0 x20000L 例如 下列指令在外存区访问地址0 x1000 xval XBYTE 0 x1000 XBYTE 0 x1000 20 函数名 CWORD DWORD XWORD PWORD原型 defineCWORD unsignedint 0 x50000L defineDWORD unsignedint 0 x40000L definePWORD unsignedint 0 x30000L defineXWORD unsignedint 0 x20000L 96 6 6 3INTRINS H内部函数 函数名 crol irol lrol 原型 unsignedchar crol unsignedcharval unsignedcharn unsignedint irol unsignedintval unsignedcharn unsignedlong lrol unsignedlongval unsignedcharn 功能 crol irol lrol 以位形式将val左移n位 该函数与8051 RLA 指令相关 例如 includemain unsignedinty y 0 x00ff y irol y 4 y值为0 x0ff0 97 函数名 cror iror lror 原型 unsignedchar cror unsignedcharval unsignedcharn unsignedint iror unsignedintval unsignedcharn unsignedlong lror unsignedlongval unsignedcharn 功能 这几个函数都将val右移n位 它们与8051指令 RRA 相关 例如 includemain unsignedinty y 0 xff00y iror y 4 y值为0 x0ff0 98 函数名 nop 原型 void nop void 功能 nop 产生一个NOP指令 该函数可用作C程序的时间比较 C 5l编译器在 nop 函数工作期间不产生函数调用 即在程序中直接执行了NOP指令 例 P0 1 nop 等待一个时钟周期 P0 0 99 函数名 testbit 原型 bit testbit bitx 功能 testbit 产生一个JBC指令 该函数测试 个位 当置位时返回1 否则返回0 如果该位置为l 则将该位复位为0 8051的JBC指令即用作此目的 testbit 只能用于直接寻址的位 在表达式中使用是不允许的 例 1 include23charval 4bitflag 56main 7if testbit flag val 8 100 6 6 4REGxxx H文件REG51 H REG52 H REG51F H和REG515 H允许访问8051系列的SFR和SFR bit的地址 这些文件中都包含 include指令 并定义了所需的所有SFR名以寻址8051系列的外围电路地址 对于8051系列中其它一些器件 用户可用文本编辑器容易地产生一个 h 文件 例如 下例表明了对8051PORT0和PORT1的访问 include reg51 h main if P0 0 x10 P1 0 x50 101 6
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年德保紧缺人才模拟试题(含答案)
- 2026年全国中小学语文教学案例研究模拟试卷及参考答案
- 2026年口腔麻醉模拟试卷型带答案
- 2026年保育员考题(含答案)
- 2026年兽医压力测试模拟试卷及答案
- 2026年机械工程师招聘考试模拟试卷带答案
- 2026年ccf计算机软件能力认证模拟试卷目带答案
- 2026年内科护士考试模拟试卷及参考答案
- 2026年医疗器械质量管理专业技术资格考试模拟试卷及答案
- 2026年单数和复数模拟试题(含答案)
- 山东省济南市2025-2026学年七年级上册期末复习:文言文阅读(课外阅读)练习题与答案
- 江苏省泰州市泰州中学2026-2027学年高二上学期10月第一次质量检测生物试卷(无答案)
- 恶性胸腔积液诊断与治疗教学课件
- 2026年宁波市文化旅游投资集团有限公司人员招聘笔试备考试题及详细答案解析
- 中医科医院感染管理制度-001
- 2026年传承红色薪火 勇担少年使命 - 纪念长征胜利90周年校长主题讲话
- 会议音视频系统维护保养手册
- GB/T 8334-2026液化石油气和液化二甲醚钢瓶定期检验与评定
- 动力配电系统施工方案-技术交底
- 2025青岛水务集团有限公司招聘(89人)笔试历年备考题库附带答案详解
- 修订一单一库质量手册和程序文件参考文件
评论
0/150
提交评论