51单片机C语言学习之道(语法函数Keil工具及项目实战)/清华开发者书库

51单片机C语言学习之道(语法函数Keil工具及项目实战)/清华开发者书库
作者: 编者:孙鹏
出版社: 清华大学
原售价: 49.00
折扣价: 37.24
折扣购买: 51单片机C语言学习之道(语法函数Keil工具及项目实战)/清华开发者书库
ISBN: 9787302490890

作者简介

内容简介

第3章单片机C语言开发基础 1.7节已经介绍了C语言的结构、数据类型、运算符、函数,本章将主要通过C语言编程控制学习板上的流水灯,学习如何灵活运用C语言中的运算符、控制语句、数组、指针、预处理。本章内容可以说是对C51知识点的一个完整总结,内容较多,初学者全面掌握有一定难度。初学者对其中一些知识点可做简单了解,在后续章节的学习中再结合具体应用,以加深理解。 3.1运算符的应用 C语言中的运算符主要包括: 算术运算符、关系运算符、逻辑运算符、赋值运算符等。以下就是几个应用运算符来编程的实例。 【例31】用单片机实现乘法78×18的运算,并通过P2口的发光二极管分时显示结果的高八位和低八位状态。 分析: 先设置两个字符型变量i和j,将它们分别赋值为78和18,可以先计算它们相乘的结果为1404,等于十六进制数0x057C,在程序中用变量s保存它们相乘的这个结果。因为i和j的值小于255,所以用字符型变量保存即可; 变量s的值大于255并小于65535,所以必须保存为整型变量。相乘的十六位结果在八位并口P2上显示,只能把它拆成高八位和低八位分别显示,显示时,为区别高八位和低八位,它们中间让发光二极管全灭,并停顿1s。变量s高八位的二进制数是0000 0101B,因为发光二极管的状态是并口为高时熄灭,所以高八位送显示时,将有最低位、倒数第二位的灯熄灭,其他灯亮; 变量s低八位的二进制数是0111 1100B,当高八位送显示时,将有最高位、最低位两位灯亮,其他灯熄灭。我们可以把以下程序下载到学习板,观察显示状态是否正确。 #include #define uint unsigned int   //宏定义 #define uchar unsigned char delay() { uint m,n; for(m=1000;m>0;m--) for(n=110;n>0;n--); } void main() { uint s;//保存乘法结果 uchar i,j;   //保存相乘的因数 i=78; j=18; s=i*j; while(1) { P2=s/256;   //取乘积的高八位送P2口显示 delay(); P2=0xff; delay(); P2=s%256;   //取乘积的低八位送P2口显示 delay(); } } 程序中用指令“P2=s/256”取变量s的高八位送显示,指令右面的算式变量s除以256后取整,所以P2得到的是乘积的高八位。而用指令P2=s%256取变量s的低八位送显示,符号“%”表示取s和256相除的余数,即变量s的低八位。通过这个例子,我们练习了除法和取余运算的用法。如果修改程序中i和j所赋的初值,还可以得到其他情况下乘法运算的结果。 这个程序里用到了宏定义,宏定义的格式为: #define 新名称 原内容 #define命令的作用是: 用“新名称”代替后面的“原内容”,一般用于“原内容”比较长,又在程序里反复用到的情况。这样如果在程序中出现“原内容”,就可以用一个比较简短的“新名称”代替,使程序的书写更加简化。例如,本例在程序开始已经做了宏定义“#define uint unsigned int”,在此宏定义的后面,所有应该写unsigned int的地方,都用uint代替了。同一个程序中,宏定义对一个内容只能定义一次。 【例32】用16个发光二极管显示除法运算结果。 在学习板上除了P2口接的8个发光二极管以外,P3口利用串并转换接口芯片74HC595也扩展了8个发光二极管。电路如图31所示。 其中,芯片74HC595是八位串行输入转并行输出移位寄存器。引脚SER(14)是串行移位输入引脚,串行数据从低位到高位在该引脚输入; 引脚SRCLK(11)移位时钟输入引脚,该引脚的上升沿可以使14脚的数据输入芯片内,即该引脚的上升沿控制数据串行移入; 引脚RCLK(12)并行输出时钟端,通常情况下该引脚保持低电平,当串行数据移入完成时, 图31发光二极管硬件驱动电路图注: 接地符号与软件界面截图保持一致,全书同。 该引脚产生一个上升沿,将刚才移入的数据在QA~QH端并行输出。由74HC595的工作原理可见,仅用了这一个芯片,就可以只占用单片机的3个I/O口(即P3.4~P3.6)来驱动8个发光二极管,大大节约了硬件资源。感兴趣的读者可以把例31中乘法运算的程序修改一下,结果在图31的16位发光二极管上显示出来。 假设本例中除法运算为“10÷6”结果只保留一位小数,结果中整数部分可以在P2口的发光二极管上显示,结果中,小数部分在74HC595扩展的发光二极管上显示。程序如下: #include #define uint unsigned int #define uchar unsigned char sbit data1=P3^4;   //定义74HC595中用到的几个口 sbit iclk=P3^6; sbit oclk=P3^5; uchar i,j,k,m; void delay() { uint a,b; for(a=10;a>0;a--) for(b=110;b>0;b--); } void xianshi(uchar m)   //74HC595显示子程序 { uchar n; n=m;   //要显示的数存放在n里 oclk=0; iclk=0; for(j=8;j>0;j--)   //要显示的数左移串行输入 { n=n<<1; data1=CY; iclk=1; delay(); iclk=0; } oclk=1;//移位完成并行输出 delay(); oclk=0; } void main() { i=10;   //被除数和除数赋给i和j j=6; P2=i/j; k=((i%j)*10)/j;   //小数位保存在k中 xianshi(k);//调用显示子程序 while(1); } 这个程序主要用到了74HC595的显示驱动函数,命名为“xianshi()”,它的形参为m,即要送D9~D16显示的数据。在这个子函数里,首先定义了一个无符号字符型变量n,用来存放要显示的数,然后将74HC595的串行输入时钟和并行输出时钟都置为低电平。再开始串行输入: n左移一位,移出的位移到了CY里,再把CY的值(第一次移位是显示数据最高位)给74HC595串行数据输入端,再将串行输入时钟置高电平,该时钟原来为低电平,因此在该引脚形成了一个上升沿,将串行数据输入端的当前值移入74HC595,再延时将时钟端置低。串行数据输入的过程要反复移位8次,才能将要显示的八位二进制数全部移入,这里用了一个for循环,控制移位一共进行8次。当跳出循环时移位完成,此时需要将八位二进制数并行输出,输出通过并行输出时钟控制: 并行输出时钟原值为低电平,现在置为高电平,形成一个上升沿,这个上升沿控制74HC595将刚才移入的数据并行由QA~QH输出。输出完成后,再将输出时钟端置为低电平,为下一次显示做准备。 主程序里先将被除数和除数分别赋值给i和j,然后将i和j相除的结果取整后直接赋值给P2口,这是商的整数部分。小数部分的计算方法为: 先将i和j相除后取余数,再扩大10倍,再用除数除后取整,这样计算得到的小数部分只有小数点后的第一位,再调用74HC595的显示子函数,在发光二极管D9~D16显示这个小数位。发光二极管熄灭表示1,点亮表示0,通过观察学习板上发光二极管的亮灭状态,即可知道除数运算的结果。 上述方法在单片机控制小数点的显示时非常有用。也可以把本例中被除数和除数的值变化一下,观察发光二极管的状态有什么变化。另外,读者也可以考虑: 如果想显示更多的小数位时,程序应如何编写。 【例33】用自增、自减运算控制P2口的流水灯。 如果对变量i执行自增运算时写成“i++”,执行完i的值被加1; 对变量i执行自减运算时写成“i--”,执行完变量i的值被减1。这两个运算符主要用在for循环的表达式里,用来修改循环指针。 #include void delay() //延时1s子程序 { unsigned int i,j; for(i=1000;i>0;i--) for(j=110;j>0;j--); } void main() { unsigned char m,n; while(1) { for(m=0;m<10;m++)   //m从0到9自增1,状态从P2输出 { P2=m; delay(); } for(n=10;n>0;n--)   //n从10到1自减1,状态从P2输出 { P2=n; delay(); } } } 这个程序可以实现P2口的流水灯按一定规律变化。端口P2驱动的发光二极管在端口数据为1时,灯灭,在数据为0时,灯亮,亮灭规律都是按照二进制数的形式变化。程序中两个for循环使P2口输出数据按从0到10、再从10到0的规则循环变化,相应的发光二极管也按这个规律点亮或熄灭。从观察P2口灯亮灭状态的变化,就可以知道自增和自减指令的功能了。 3.2C语言的语句 一个完整的C程序是由若干条C语句按一定的方式组合而成的。按C语句执行方式的不同,C程序可分为顺序结构、选择结构和循环结构。  顺序结构: 指程序按语句的顺序逐条执行。  选择结构: 指程序根据条件选择相应的执行顺序。  循环结构: 指程序根据某条件的存在重复执行一段程序,直到这个条件不满足为止。如果这个条件永远存在,就会形成死循环。 一般的C程序都是由上述三种结构混合而成的。但要保证C程序能够按照预期的意图运行,还要用到以下5类语句来对程序进行控制。 1. 控制语句 控制语句完成一定的控制功能,C语言中有9种控制语句。  if…else: 条件语句;  for: 循环语句;  while: 循环语句;  do…while: 循环语句;  continue: 结束本次循环语句;  break: 终止执行循环语句;  switch: 多分支选择语句;  goto: 跳转语句;  return: 从函数返回语句。 2. 函数调用语句 调用已定义过的函数,例如延时函数。 3. 表达式语句 由一个表达式和一个分号构成,示例如下: z=x+y; 《51单片机C语言学习之道》体系完善、循序渐进、深入浅出,从最简单的编程实例入手,通过大量具有代表性的实例讲述了51单片机C语言编程方法、硬件结构及应用。共分三篇:入门篇、应用篇、综合篇。入门篇主要讲解单片机的基础知识、C语言调试软件Keil的使用方法、C51函数的用法。应用篇讲解了定时计数器和中断的用法,并介绍了一些常用器件的驱动。综合篇则结合一些生产和生活的实例,介绍了一些实际应用中的单片机系统软硬件设计方法。