




已阅读5页,还剩52页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第10章单片机c51语言程序设计基础 学习目标 掌握c51程序设计的基本方法及特点制 掌握c语言在单片机开发中程序的语法规则 了解c语言在单片机开发中程序的结构特点 学习重点 c语言在单片机应用系统中程序设计实例的分析和讨论 c51 程序设计的特点 c语言程序设计的基本方法 主要内容 任务1 学习c51程序的结构 10单片机c51语言程序设计基础 任务2 c51数据类型 常量和变量的定义 任务3 c51程序的运算符及其语法规则 任务4 掌握c51程序设计特点 任务5 理解c51程序设计举例 10 1c51程序的结构 c51与标准c的区别 c51在语法规则 程序结构及程序设计方法等与标准的c语言程序设计相同 主要区别在于 1 c51语言编写单片机应用程序时 需根据单片机存储结构及内部资源定义相应的数据类型和变量 而标准的c语言程序不需要考虑这些问题 2 c51中变量的存储模式是与mcs 51单片机的存储器紧密相关 3 c51中的数据类型与标准c的数据类型也有一定的区别 在c51中还增加了几种针对mcs 51单片机特有的数据类型 4 c51与标准c的输入输出处理不一样 c51中的输入输出是通过mcs 51串行口来完成的 输入输出指令执行前必须要对串行口进行初始化 5 c51与标准c在函数使用方面也有一定的区别 c51中有专门的中断函数 10 1c51程序的结构 10 1 1c51程序的结构特点 c51语言与标准c语言的不同之处在于 c51语言根据单片机存储结构及内部资源定义了相应的c语言中的数据类型和变量 c51程序结构与一般c语言没有什么差别 一个c51程序大体上是一个函数定义的集合 在这个集合中有且仅有一个名为main 函数 主函数 主函数是程序的入口 主函数中的所有语句执行完毕 则程序执行结束 在c51中 函数定义由类型 函数名 参数表和函数体四部分组合而成函数名是一个标识符 标识符是大小写可区别的 最长为255个字符 参数表是用圆括号括起来的若干参数 项与项之间用逗号隔开 函数体是用大括号括起来的若干c语句 语句与语句之间用分号隔开 最后一个语句一般是return 在主函数中可以省略 每一个函数都返回一个值 该值由return语句中的表达式指定 省略时为零 函数的类型就是返回值的类型 函数类型 除整型外 均需在函数名前加以指定 2 1c51程序的结构 以87c51单片机最小系统的p1 0口控制一个led发光管的亮和灭为例来介绍c51程序的一般格式 图10 1为其控制电路图 图10 187c51p1 0口控制led灯电路图 10 1c51程序的结构 include 包括一个51标准内核的头文件sbitp10 p1 0 头文件中没有定义的i o口就要自己来定义voidmain 主程序 unsignedintn do for n 0 n 20000 n 延时p10 0 设p1 0口为低电平 点亮ledfor n 0 n 20000 n 延时p10 1 设p1 0口为高电平 熄灭led while 1 程序循环 对应的c51控制程序如下 c51函数的一般格式如下 函数类型 函数名 函数形式参数表 函数说明部分 数据说明部分 函数体部分执行语句部分 其中加 时 表示其中的内容可以省略 一个函数在程序中可以以三种形态出现 函数定义 函数调用和函数说明 函数定义相当于汇编中的一般子程序 函数调用相当于汇编中调用子程序的call语句 在c语言中 更普遍地规定函数调用可以出现在表达式中 函数定义和函数调用不分先后 但若调用在定义之前 那么在调用前必须先进行函数说明 函数说明是一个没有函数体的函数定义 而函数调用则要求有函数名和实参数表 c51中函数分为两大类 一类是库函数 一类是用户定义的函数 库函数是c51在库文件中已定义的函数 其函数说明在相关的头文件中 对于这类函数 用户在编程时只要用include预处理指令将头文件包含在用户文件中 直接调用即可 用户函数是用户自己定义 自己调用的一类函数 从某种意义上来看 c编程实际上是对一系列用户函数的定义 10 1c51程序的结构 10 1 2c51函数的一般格式 10 2c51数据类型 常量和变量的定义 10 2 1c51数据类型 用c51编写程序 虽不像用汇编语言那样具体地组织 分配存储器资源和处理端口数据 但对数据类型与变量的定义必须要与单片机的存储结构相关联 否则编译器不能正确地映射定位 每写一个程序 总离不开数据的应用 在学习c51语言的过程中掌握理解数据类型也是很关键的 c51的数据类型分为基本数据类型和组合数据类型 情况与标准c中的数据类型基本相同 float型与double型相同 另外 c51中还有专门针对于mcs 51单片机的特殊功能寄存器型和位类型 表10 1keiluvision2c51编译器所支持的数据类型 常量是指在程序执行过程中其值不能改变的量 在c51中支持整型常量 浮点型常量 字符型常量和字符串型常量 整型常量也就是整型常数 根据其值范围在计算机中分配不同的字节数来存放 在c51中它可以表示成以下几种形式 十进制整数 如234 56 0等 十六进制整数 以0 x开头表示 如0 x12表示十六进制数12h 长整数 在c51中当一个整数的值达到长整型的范围 则该数按长整型存放 在存储器中占四个字节 另外 如一个整数后面加一个字母l 这个数在存储器中也按长整型存放 如123l在存储器中占四个字节 10 2c51数据类型 常量和变量的定义 10 2 2常量的定义 浮点型常量也就是实型常数 有十进制表示形式和指数表示形式 十进制表示形式 由数字和小数点组成 如0 123 34 645等都是十进制数表示形式的浮点型常量 整数或小数部分为0 能省略但必须有小数点 指数表示形式为 数字 数字 e 数字例如 123 456e 3 3 123e2等都是指数形式的浮点型常量 中的内容为可选项 其中内容根据具体情况可有可无 但其余部分必须有 字符型常量是用单引号引起的字符 如 a 1 f 等 可以是可显示的ascii字符 也可以是不可显示的控制字符 对不可显示的控制字符须在前面加上反斜杠 组成转义字符 利用它可以完成一些特殊功能和输出时的格式控制 10 2c51数据类型 常量和变量的定义 字符串型常量由双引号内的字符组成 如 test ok 等 当引号内没有字符时 为空字符串 在使用特殊字符时同样要使用转义字符如双引号 在c中字符串常量是做为字符类型数组来处理的 在存储字符串时系统会在字符串尾部加上 0转义字符以作为该字符串的结束符 字符串常量 a 和字符常量 a 是不同的 前者在存储时多占用一个字节的空间 它的值是一个二进制数 10 2c51数据类型 常量和变量的定义 常量可用在不必改变值的场合 如固定的数据表 字库等 常量的定义方式有几种 下面加以说明 difinefalse0 x0 用预定义语句可以定义常量 difinetrue0 x1 这里定义false为0 true为1在程序中用到 false编译时自动用0替换 同理true替换为1unsignedintcodea 100 这一句用code把a定义在程序存储器中并赋值constunsignedintc 100 用const定义c为无符号int常量并赋值以上代码中常量的值都保存在程序存储器中 而程序存储器在运行中是不允许被修改的 所以如果在这两句后面用了类似a 110 a 这样的赋值语句 编译时将会出错 10 2c51数据类型 常量和变量的定义 10 2c51数据类型 常量和变量的定义 10 2 3变量的定义 变量是一种在程序执行过程中其值能不断变化的量 要在程序中使用变量必须先用标识符作为变量名 并指出所用的数据类型和存储模式 这样编译系统才能为变量分配相应的存储空间 在c51中规定变量名可以由字母 数字和下划线三种字符组成 且第一个字母必须为字母或下划线 定义一个变量的格式如下 存储种类 数据类型 存储器类型 变量名表在定义格式中除了数据类型和变量名表是必要的 其他都是可选项 存储种类有四种 自动 auto 作用范围 在定义它的函数内或复合语句内部 当定义它的函数或复合语句执行时 c51才为变量分配存储空间 结束时所占用的存储空间释放 外部 externad 用extern声明的变量为外部变量 是在其它文件定义过的全局变量 用extern声明后 便可以在所声明的文件中使用 静态 static 在函数内可以任意使用和修改 函数运行结束后会一直存在 但在函数外不可见 即在函数体外得到保护 不能被访问 寄存器 register 用register定义的变量为寄存器变量 告诉编译器他所定义的变量使用率较高 寄存器变量存放在cpu的寄存器中 这种变量处理速度快 但数目少 缺省类型为自动 auto 而这里的数据类型则是和前面学习到的各种数据类型的定义是一样的 说明了一个变量的数据类型后 还可选择说明该变量的存储器类型 存储器类型的说明就是指定该变量在c51硬件系统中所使用的存储区域 并在编译时准确的定位 表10 2列出了keiluvision2所能识别的存储器类型 注意 在87c51芯片中ram只有低128位 位于80h到ffh的高128位则在52芯片中才有用 并和特殊寄存器地址重叠 表10 2keilc51能识别的存储器类型 10 2c51数据类型 常量和变量的定义 10 2c51数据类型 常量和变量的定义 10 2 4c51定义sfr字节和位单元 1 对特殊功能寄存器sfr的定义 sfr和sfr16可以直接对51单片机的特殊功能寄存器sfr进行定义 定义方法如下 sfr特殊功能寄存器名 功能寄存器地址常数 sfr用于定义8位的特殊功能寄存器 sfr关键字后面是一个要定义的名字 可任意选取 但要符合标识符的命名规则 名字最好有一定的含义如p1口可以用p1为名 这样便于程序读写 等号后面必须是常数 不允许有带运算符的表达式 而且该常数必须在特殊功能寄存器的地址范围之内 80h ffh 例如 sfrp1 0 x90 定义p1i o口 其口地址为90hsfr16特殊功能寄存器名 殊功能寄存器地址常数 sfr16是用来定义16位特殊功能寄存器 例如 sfr16t2 0 xcc 这里定义8052定时器t2 地址为 t2l cch t2h cdh用sfr16定义16位特殊功能寄存器时 等号后面是它的低位地址 高位地址一定要位于物理低位地址之上 2 对位地址单元的定义 sbit定义可位寻址对象 如访问特殊功能寄存器中的某位 如要访问p1口中的第2个引脚p1 1 定义方法有三种 第一种方法 sbit位变量名 位地址 例如 sbitp11 0 x91 这种方法是把位的绝对地址赋给位变量 同sfr一样sbit的位地址必须位于80h ffh之间第二种方法 sbit位变量名 特殊功能寄存器名 位位置 例如 sfrp1 0 x90 sbitp11 p1 1 先定义一个特殊功能寄存器名再指定位变量名所在的位置当可寻址位位于特殊功能寄存器中时可采用这种方法 第三种方法 sbit位变量名 字节地址 位位置例如 sbitp11 0 x90 1 第三种种方法其实和第二种是一样的 只是把特殊功能寄存器的地址直接用常数表示 通常这些可以直接使用 系统提供的预处理文件里面已定义好各特殊功能寄存器的简单名字 直接引用可以省去一点时间 没有定义的可以自己定义 在c51存储器类型中提供有一个bdata的存储器类型 这个是指可位寻址的数据存储器 位于单片机的可位寻址区中 可以将要求可位寻址的数据定义为bdata 例如 unsignedcharbdataib 在可位寻址区定义unsignedchar类型的变量ib 10 2c51数据类型 常量和变量的定义 10 3c51程序的运算符 表达式及其语法规则 10 3 1c51算术运算符及其表达式 赋值运算符 在c51中 它的功能是将一个数据的值赋给一个变量 如x 10 利用赋值运算符将一个变量与一个表达式连接起来的式子称为赋值表达式 在赋值表达式的后面加一个分号 就构成了赋值语句 一个赋值语句的格式如下 变量 表达式 执行时先计算出右边表达式的值 然后赋给左边的变量 例如 x 8 9 将8 9的值赋绐变量x x y 5 将常数5同时赋给变量x和y 在c51中 允许在一个语句中同时给多个变量赋值 赋值顺序自右向左 1 运算符 1 赋值运算符 2 算术运算符 c51中支持的算术运算符有 加或取正值运算符 减或取负值运算符 乘运算符 除运算符 取余运算符 定时器赋初值 1 加 减 乘运算相对比较简单 而对于除运算 如相除的两个数为浮点数 则运算的结果也为浮点数 如相除的两个数为整数 则运算的结果也为整数 即为整除 如25 0 20 0结果为1 25 而25 20结果为1 2 对于取余运算 则要求参加运算的两个数必须为整数 运算结果为它们的余数 例如 x 5 3 结果x的值为2 3 算术运算符 算术表达式 用算术运算符和括号将运算对象连接起来的式子称为算术表达式 其中的运算对象包括常量 变量 函数 数组 结构等等 例如 a b a b c d a b c d e f a b c 2 5 b 10 3c51程序的运算符 表达式及其语法规则 4 算术运算符的优先级和结合性 优先级 指当运算对象两侧都有运算符时 执行运算的先后次序 按运算符优先级别的高低顺序执行运算 结合性 指一个运算对象两侧的运算符优先级别相同时的运算顺序 算术运算符的优先级规定为 先乘除模 后加减 括号优先 即在算术运算符中 乘 除 模运算符的优先级相同 并高于加减运算符 在表达式中若出现括号 则括号中的内容优先级最高 例如 a b c 这个表达式中除号的优先级高于加号 故先运算b c所得的结果再与a相加 例如 a b c d e 在这个表达式中括号的优先级最高 次之 减号优先级最低 故先运算 a b 和 c d 然后再将两者的结果相乘 最后再与e相减 算术运算符的结合性规定为自左至右方向 又称为 左结合性 即当一个运算对象两侧的算术运算符优先级别相同时 运算对象先与左面的运算符结合 例如 a b c b两边是 运算符优先级别相同 故按左结合性先执行a b再与c相减 10 3c51程序的运算符 表达式及其语法规则 10 3c51程序的运算符 表达式及其语法规则 10 3 2c51关系运算符 表达式及优先级 1 关系运算符 c51中有6种关系运算符 大于 大于等于3 结果为真 1 而10 100 结果为假 0 注意 关系运算符等于 是由两个 组成 10 3c51程序的运算符 表达式及其语法规则 2 关系运算符的优先级 图10 4各种运算符优先级规则图 前四种关系运算符 优先级相同 后两种也相同 前四种优先级高于后两种 关系运算符的优先级低于算术运算符 关系运算符的优先级高于赋值运算符 各种运算符的优先级规则如图10 4所示 例10 1 c a b等效于c a b a b c等效于 a b ca bc等效于a b c 关系运算符的结合性为左结合 关系表达式 用关系运算符将两个表达式 算术表达式 关系表达式 逻辑表达式及字符表达式等 连接起来的式子 称为关系表达式 关系表达式的结果 由于关系运算符总是二目运算符 它作用在运算对象上产生的结果为一个逻辑值 即真或假 c语言以 1 代表真 以 0 代表假 10 3c51程序的运算符 表达式及其语法规则 10 3 3c51逻辑运算符 表达式及优先级 1 逻辑运算符 逻辑与 and 逻辑或 or 逻辑非 not 和 是双目运算符 要求有两个运算对象 而 是单目运算符 只要求一个运算对象 c51逻辑运算符与算术运算符 关系运算符 赋值运算符之间的关系 其中 运算符优先级最高 算术运算符次之 关系运算符再次之 之后是 和 赋值运算符最低 2 逻辑表达式 用逻辑运算符将关系表达式或逻辑量连接起来的式子称为逻辑表达式 逻辑表达式的值应该是一个逻辑量 真 或 假 逻辑表达式的结合性为自左向右 逻辑表达式的值与关系表达式的值相同 以0代表假 以1代表真 10 3c51程序的运算符 表达式及其语法规则 例10 2 若a 4 b 5 则 因为a 4为真 所以 a为假 0 因为a b为真 两者相或也为真 a b为真 1 a b为假 0 因为 优先级高于 故先执行 a 值为假 0 而0 b为0 故结果为假 0 通过上面的例子可以看出 系统给出的逻辑运算结果不是0就是1 不可能是其他值 这与后面讲到的位逻辑运算是截然不同的 应该注意区别逻辑运算与位逻辑运算这两个不同的概念 在由多个逻辑运算符构成的逻辑表达式中 并不是所有逻辑运算符都被执行 只是在必须执行下一个逻辑运算符后才能求出表达式的值时 才执行该运算符 由于逻辑运算符的结合性为自左向右 所以对于 逻辑与 运算符来说 只有左边的值不为假 0 才继续执行右边的运算 对于 逻辑或 运算符来说只有左边的值为假才继续进行右边的运算 例10 3 若a 1 b 2 c 3 d 4 m n原值为1 则求表达式 m a b n c d 由于a b为假 0 即m 0 故无须再执行右边的 n c d 运算 即可确定表达式值为假 0 而表达式 m a b n c d 由于a d为假 0 即m 0 故需继续向右执行 又由于c d为假 0 即n 0 两者相或 结果为0 故表达式值为0 10 3c51程序的运算符 表达式及其语法规则 10 3 4c51位操作及其表达式 1 位操作运算符 按位与 按位或 按位异或 按位取反 位右移 除了按位取反运算符 以外 以上位操作运算符都是两目运算符 即要求运算符两侧各一个运算对象 位运算对象只能是整型或字符型数 不能为实型数据 例10 4 若a 54h 01010100b b 3bh 00111011b则表达式c a b的值为10h 例10 5 若a a5h 10100101 b 37h 00110111 则表达式c a b的值为92h 10 3c51程序的运算符 表达式及其语法规则 2 位左移 和 位右移 运算符 位左移 位右移运算符 用来将一个数各二进制位的全部左移或右移若干位 移位后 空白位补0 而溢出的位舍弃 移位运算并不能改变原变量本身 除非我们将移的结果赋给另一变量 例10 6 若a 11000011b 0c3h 将a值右循环位移两位 其实现过程分析如下 a右循环n位 即将a中原来左面 8 n 位右移n位 而将原来右端的n位移到最左面n位 上述问题可以由下列步骤来实现 1 将a的右端n位先放到b的高n位中b a n 3 将b c进行或运算a c b 故对a进行循环右移2位的程序可这样编写 main unsignedchara 0 xc3 b c intn 2 b a n a c b 结果 循环右移前a 11000011 循环右移后a 11110000 对于二进制数来说 左移1位相当于对该数乘2 而右移1位相当于该数除以2 利用这一性质我们可以用移位来做快速乘除法 例如 假如要对某数乘10 使用这种方法将比直接做乘法效率更高 先将该数右移2位再与该数本身相加 然后再左移1位 10 3c51程序的运算符 表达式及其语法规则 10 3c51程序的运算符 表达式及其语法规则 例10 7 对片外i o接口的位操作 在控制系统中 位操作方式比算术方式更频繁地被使用 以8051片外i o接口为例 这种i o接口的字长为1b 8位 在实际控制应用中 人们常常想要改变i o接口中某一位的值而不影响其他位 当这个口的其他位正在点亮报警灯 或命令a d转换器开始转换的时候 用这一位可以启动或关闭一部电动机 正像前面已经提过的那样 有些i o接口是可以位寻址的 例如8051片内i o接口 但大多数片外附加i o接口只能对整个字节作出响应 因此要想在这些地方实现单独位控制 或线控制 就要采用位操作 单片机内部端口用sfr定义 外部并行口用指针定义 指针的定义在absacc h头文件中 例如 include defineportaxbyte 0 xffc0 voidmain porta porta 0 xbf 0 x04 在上面的程序片段中 定义了一个片外i o接口变量porta 其地址在片外数据存储区的0 xffc0上 在main 函数中 porta porta 0 xbf 0 x04 作用是先用 运算符将porta 6位置成低电平 然后使用 0 x04运算将porta 2位置成高电平 10 3c51程序的运算符 表达式及其语法规则 10 3 5自增减运算符 复合运算符及其表达式 1 自增减运算符 自增减运算符的作用是使变量值自动加1或减1 例如 i i在使用i之前 先使i值加 减 1 i i 在使用i之后 再使i值加 减 1 粗略地看 i和i 的作用都相当于i i 1 但不同之处在于 i先执行i i 1 再使用i的值 而i 则是先使用i的值 再执行i i 1 例10 8 若i值原来为5 则j i j值为6 i值也为6 j i j值为5 i值为6 例10 9 若i原值为3 则表达式k i i i 的值为18 这是因为 i最先执行 先对表达式进行扫描 对i进行三次自加 i 则此时i 6 然后执行k 6 6 6 18 故k值为18 而表达式k i i i 其结果是 k值为9 而i值为6 因为先对i进行三次相加 再执行三次i的自加 注意 1 自增运算 和自减运算 只能用于变量而不能用于常量表达式 2 和 的结合方向是 自右向左 10 3c51程序的运算符 表达式及其语法规则 2 复合运算符及其表达式 凡是二目运算符 都可以与赋值运算符 一起组成复合赋值运算符 c51共提供了10种复合赋值运算符 即 采用这种复合赋值运算的目的 是为了简化程序 提高c程序编译效率 如 a b相当于a a ba b相当于a a ba b相当于a a ba 8相当于a a 8a b相当于a a b porta 0 xf7相当于porta porta 0 xf7 其作用是使用 位运算 将porta 3位置0 例10 7 使用p1口控制八路led流水灯 电路图如10 6所示 这里87c51的p1引脚为低电平才会点亮led灯 p1口的八个引脚刚好对应p1口特殊寄存器的八个二进制位 如向p1口送数据0 xfe 转换成二进制就是11111110 最低位d0为0这里p1 0引脚输出低电平 led1被点亮 以此类推 根据自己想要做的效果就可以给端口送对应的值了 现在要求八个led灯依次从p1 0到p1 7点亮 然后又从p1 7到p1 0依次点亮 循环往复 10 3c51程序的运算符 表达式及其语法规则 参考程序如下 includevoiddelay1ms unsignedintcount 延时程序 unsignedinti j for i 0 i count i for j 0 j 120 j main unsignedcharledindex 0 bitleddirection 1 点亮led灯的方向标志while 1 if leddirection p1 0 x01 ledindex 方向标志为0时 从p1 7到p1 0点亮if ledindex 7 leddirection leddirection ledindex ledindex 1 8 delay1ms 100 10 3c51程序的运算符 表达式及其语法规则 10 3c51程序的运算符 表达式及其语法规则 图10 6八路led流水灯电路图 10 4c51程序设计特点 10 4 1c51函数的分类 1 c51库函数 c51编译器提供了丰富的库函数 使用这些库函数可大大提高编程效率 用户可根据自己程序的需要随时调用编译器提供的库函数 每个库函数都在相应的头文件中给出了函数原型 使用时只需在源程序的开头用编译预处理命令 include将相关的头文件包含进来即可 例如 要进行绝对地址访问 只需要在程序开头使用 include 将头文件包含即可 要访问sfr或sfr的位 则只需要在程序开头使用 include 或 include 将头文件包含即可 c语言函数分为主函数main 和普通函数两类 对于普通函数 从用户的角度又划分为标准库函数和用户自定义函数 用户自定义函数是根据需要编写的函数 从其定义形式上划分为三种形式 无参数函数 有参数函数和空函数 无参数函数 此种函数被调用时 既无参数输入 也不返回结果给调用函数 它是为完成某种操作过程而编写的 有参数函数 在定义此类函数时 必须定义与实际参数一一对应的形式参数 并在函数结束时返回结果给调用该函数的程序使用 函数的返回值是通过函数中的return语句获得的 调用时必须提供实际的输入参数 空函数 此种函数体内无语句 是空白的 调用此种空函数时 什么工作也不做 不起任何作用 定义此种函数的目的并不是为了执行某种操作 而是为了以后程序功能的扩充 在程序的设计过程中 往往根据需要确定若干模块 分别由一些函数来实现 而在程序设计的第一阶段 往往只设计最基本的功能模块函数 而将其他非基本模块的功能函数定义为空函数 留待以后完善 2 用户自定义函数 10 4c51程序设计特点 10 4c51程序设计特点 10 4 2中断子程序的设计 1 中断函数的定义与使用举例 c51语言扩展了函数的定义使它可以直接编写中断服务函数 扩展的关键字是interrupt和using 用于定义中断服务程序 具体格式如下 函数类型函数名 形式参数 interruptn usingn interrupt关键字是不可缺少的 由它告诉编译器该函数是中断服务函数 并由后面的n指明所使用的中断号 n的取值范围为0 31 但具体的中断号要取决于芯片的型号 像87c51实际上就使用0 4号中断 每个中断号都对应一个中断向量 具体地址为8n 3 中断源响应后处理器会跳转到中断向量所处的地址执行程序 一般会在这地址上安排一个无条件跳转语句 以保证转到中断服务函数所在的地址执行程序 using这个选项是指定选用51芯片内部4组工作寄存器中的那个组 初学者可以不必去做工作寄存器设定 而由编译器自动选择 避免产生不必要的错误 表10 3所示为51芯片的中断向量和中断号 表10 387c51芯片中断号和中断向量 10 4c51程序设计特点 例10 8 在图10 6所示的8路led流水灯电路中多加一个按键 接在p3 2 12引脚外部中断 和地线之间 当接在p3 2引脚的按键接下时 就可以触发一个中断 也就会执行相应的中断服务程序 includesbitk1 p3 2 unsignedcharn 0 voidmain void 主程序 it0 1 设置外中断0跳变产生中断ex0 1 开外部中断0ea 1 打开cpu中断while 1 主程序循环 外中断0程序voidint0 interrupt0 在中断里点亮led p1 0 x01 n n n 1 8 每按一下k1 p3 2 之后 就会触发一次中断 就会点亮一个led灯 如果连 续按 键 就会依次循环点亮led灯 10 4c51程序设计特点 中断函数不能进行参数传递 中断函数没有返回值 在任何情况下 都不能直接调用中断函数 如果中断函数调用了其他函数 则被调用函数所使用的寄存器组必须与中断函数相同 2 使用中断函数的注意事项 10 4c51程序设计特点 10 4c51程序设计特点 10 4 3c51与汇编混合编程 1 在c51中直接嵌入汇编语句 一般情况下 由c51具有很强的数据处理能力 编程中对51单片机寄存器和存储器的分配由编译器自动完成 因此常用c51编写主程序及一些运算较复杂的程序 而汇编语言对硬件的控制较强 运行速度快 灵活性更强 因此常用汇编语言实现与硬件接口及对时间要求高的子程序设计 由此导致某些时候需要进行c51语言和汇编语言的混合编程 在此以keilc51为例 简单介绍c51与汇编语言混合编程的方法 在c51中可以通过直接插入 prapmaasm endasm 预处理指令 实现汇编语言程序的内嵌 具体步骤如下 在c文件中要嵌入汇编代码片以如下方式加入汇编代码 pragmaasm汇编语句 pragmaendasm 在project窗口中包含汇编代码的c文件上右击 选择 optionsfor 命令 单击右边的 generateassemblersrcfile 和 assemblesrcfile 选项 使检查框由灰色变成黑色 有效 状态 根据选择的编译模式 把相应的库文件 small模式时是keil c51 lib c51s lib 加入工程中 该文件必须作为工程的最后文件 编译 即可生成目标代码 例如 include 包括一个51标准内核的头文件sbitp10 p1 0 头文件中没有定义的io就要自己来定义了voidmain 主程序 unsignedintn do 程序循环 pragmaasm 加入汇编指令延时movr7 250del movr6 250djnzr6 djnzr6 del pragmaendasmp10 0 设p1 0口为低电平 点亮ledfor n 0 n 20000 n 延时p10 1 设p1 0口为高电平 熄灭led while 1 10 4c51程序设计特点 10 5c51程序设计举例 1 求和 的c51程序设计 例10 9 已知x 10 y 20 计算z x y的结果 includemain 主函数名 主函数体开始intx y z 主函数的内部变量类型说明x 10 变量赋值y 20 z x y 计算z x y的值printf z d z 输出变量z的值 程序结束本例的程序是很简单的 它只有一个主函数main 在更一般情况下 一个c语言程序除了必须有一个主函数之外 还可能有若干个其他的功能函数 10 5c51程序设计举例 2求最大值的c51程序设计 例10 10 求两个数中的最大值 并输出 include 预处理命令 includemain 主函数名 主函数体开始inta a c 主函数的内部变量类型说明intmax intx inty 功能函数max及其形式参数说明scon 0 x52 8051单片机串行口初始化tmod 0 x20 tcon 0 x69 thl 0 x0f3 scanf d d a a 输入变量a和a的值c max a a 调用max函数printf max d c 输出变量c的值 主程序结束 10 5c51程序设计举例 intmax intx inty 定义max函数 x y为形式参数 max函数体开始intz max函数内部变量类型说明if x y z x 计算最大值elsez y return z 将计算得到的最大值z返回到调用处 max函数结束本例在main 函数中调用了库函数 各种子程序 scanf 和printf 它们分别是输入库函数和输出库函数 c语言本身没有输入输出功能 输入输出是通过函数调用来实现的 需要说明一点的是 c51提供的输人输出库函数是通过8051系列单片机的串行口来实现输入输出的 因此在调用库函数scanf 和printf 之前 必须先对8051单片机的串行口进行初始化 另外 我们在程序中还可以看到小写字母a和大写字母a 它们分别是两种变量 c语言规定同一个字母由于其大小写不同可以代表两个不同的变量 这也是c语言的一个特点 一般的习惯是在普通情况下采用小写字母 对于一些具有特殊意义的变量或常数采用大写字母 如本例中所用到的8051单片机特殊功能寄存器scon tmod tcon和th1等 但是必须注意 在c语言程序中同一字母的大小写是有区别的 例如scon和scon在c语言程序中会被认为是两个完全不同的变量 10 5c51程序设计举例 3按秒进行led闪烁 例10 11 p1 7驱动led按秒进行闪烁 时钟频率为6mhz 分析 时钟频率为6mhz 则一个机器周期t 2 s 而定时时间x为5 105个t 而定时器最大只能为65536个t 不能满足要求 必须借助硬件计数器或软件循环 本题采用硬件方式 如图10 7所示 t0定时 定时10ms t1计数t0的定时跳变信号p1 0的负跳变次数 计满50个跳变为1s t0定时初值 方式1 t 10ms x 5000dt 216 t0初值 机器周期tt1计数初值 方式2 x 50d 图10 7led灯按秒闪烁电路图 程序如下 includesbitp1 0 p1 0 sbitp1 7 p1 7 voidtimer0 interrupt1using1 t c0中断服务程序p1 0 p1 0 10ms定时时间到 p1 0反相th0 65536 5000 256 计数初值重装载tl0 65536 5000 256 voidtimer1 interrupt3using2 t c1中断服务程序入口p1 7 p1 7 1s定时时间到 灯改变状态 10 5c51程序设计举例 main p1 7 0 置灯初始灭p1 0 1 保证第一次反相便开始计数tmod 0 x61 定时器0工作在方式1定时 定时器1工作在方式2计数th0 65536 5000 256 预置计数初值tl0 65536 5000 256 th1 256 50 tl1 256 50 ip 0 x08 置优先级寄存器ea 1 cpu开中断et0 1 开t c0中断et1 1 开t c1中断tr0 1 启动t c0tr1 1 启动t c1for 10 5c51程序设计举例 10 5c51程序设计举例 4直流电机的控制 例10 20 按照开环控制方式实现对直流电机的控制此例中直流电机采用pwm控制 pwm pulsewidthmodulation 即脉冲宽度调制 脉冲宽度调制波通常由一列占空比不同的矩形脉冲构成 占空比就是输出的pwm波中 高电平保持的时间与该pwm的时钟周期的时间之比 通过改变pwm的占空比可以调节直流电机的速度 产生pwm信号可以由硬件方法和软件方法实现 传统的硬件模拟方法是把调制信号和载波 一般是三角波 同时接入运算放大器的两个输入端作比较而得到 而软件的实现 特别是基于单片机的软件实现方法 主要是利用其内部提供的定时器 通过改变定时器的定时初值获得不同的脉冲持续时间 函数声明 变
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 吹填砂施工方案下载
- 酶制剂提取工技能巩固考核试卷及答案
- 婴童店龙抬头营销方案
- 长春商业建筑方案设计公司
- 地矿修复材料成本分析报告
- 工艺染织品制作工主管竞选考核试卷及答案
- 人行木栈道拆除施工方案
- 书店建筑方案设计图
- 理财产品的营销方案
- 交通工程系汽车营销方案
- 癫痫的小讲课
- 零星维修工程项目方案投标文件(技术方案)
- 第七讲社会主义现代化建设的教育科技人才战略习概论2024优化版教学课件
- 海龟汤题目和答案(100题)
- 全新模具转让协议书
- 学习进阶理论指导下的美国科学课程体系整合研究
- 2025年法院书记员考试试题及答案
- 车队车辆保养维护方案
- 【教学评一体化】第五单元 观世间万物悟人生哲思【大单元公开课一等奖创新教学设计】新统编版语文七年级下册名师备课
- 《婴幼儿健康管理》课件-项目一 婴幼儿健康管理基础
- 医院法律法规专题培训课件
评论
0/150
提交评论