不想看《跟着Hugh学开发--51单片机篇》pdf版本?没关系,网页版 markdown 格式为你准好了!
进制实际是一个非常简单易懂的概念,对于初学者来说也很容易上手。我们接触最多的就是十进制了,它的特点为逢十进一,包含0,1,2,3,4,5,6,7,8,9共十个元素。
在生活中我们用到的基本都是十进制了,所以大家对它已经非常熟悉并能应用自如,但是在计算机(包括单片机)世界里,所有都是以二进制为基础的。二进制的特点为逢二进一,包含0,1共两个元素。计算机中的数据都是以二进制存储的,这就是我们所说的0,1世界。
通常我们讲的 32 位或 64 位操作系统这里的位指的就是二进制位数。因为我们实际多用十进制,那么我们在和计算机系统沟通过程中,十进制与二进制之间的转换就变得很重要了。进制之间的转换如下表所示。
表 5-1 常用进制转换表
十进制 | 二进制 | 十六进制 |
---|---|---|
0 | 0b0 | 0x00 |
1 | 0b1 | 0x01 |
2 | 0b10 | 0x02 |
3 | 0b11 | 0x03 |
4 | 0b100 | 0x04 |
5 | 0b101 | 0x05 |
6 | 0b110 | 0x06 |
7 | 0b111 | 0x07 |
8 | 0b1000 | 0x08 |
9 | 0b1001 | 0x09 |
10 | 0b1010 | 0x0A |
11 | 0b1011 | 0x0B |
12 | 0b1100 | 0x0C |
13 | 0b1101 | 0x0D |
14 | 0b1110 | 0x0E |
15 | 0b1111 | 0x0F |
16 | 0b10000 | 0x10 |
17 | 0b10001 | 0x11 |
二进制转换十进制公式如下:
其中,n表示二进制的位数。
下面我们举个例子来更加直观的说明这个公式:
例如: 0b 1101,这是一个4位的二进制数, 0b 表示二进制,计算如下:
大家可以利用这个公式计算的结果和表 4-1 进行一一对照。
十六进制也是我们常用的进制,它的特点为逢十六进一,包括0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F共十六个元素。实际上十六进制是二进制的一种特殊形式,十六进制的1位等价于二进制的4位,在C语言编程中我们常用十六进制来表示二进制数。在实际应用中我们常常在数字之前加一个前缀来表示他的进制:” 0b” 表示二进制, “0x” 表示十六进制。下面我们举例说明:
0b1001,0010 = 0x92
上面一个八位的二进制数转换为一个两位的十六进制数。二进制的前4位等于十六进制的第1位:
0b1001 = 0x9
二进制数的后4位等于十六进制的第2位:
0b0010 = 0x2
在计算机中,我们通常所说的二进制的1位也叫 1bit,8位表示1个字节,也叫 1Byte。根据二进制与十六机制的关系,一个2位的十六进制数则可表示1个字节。在运用的过程中牢记0~15 的十进制与二进制、十六进制之间的转换关系,对程序的编写有很大的好处。
我们通常用下图所示的方式来表示1个字节,也就是 1Byte。8个连续的方框,每一个方框表示1位,即 1bit,总共 8bit 组成1个字节。从左往右,第一个方框表示字节的最高位,也称为 bit7,或者叫 MSB。最后一个方框表示字节的最低位,也称为 bit0,或者叫 LSB。方框内的值要么是0,要么是1。
图 5-1 字节表示法
注:MSB:Most Significant Bit, LSB:Least Significant Bit。
下面我们举两个例子,并熟悉一下进制之间的转换。1个字节能表示的最大值,自然是每一个方框中的值都为1,转换成十进制等于 255,十六进制表示为 0xFF。最小值能表示的自然是每个方框中的值都为0,如下图所示。
图 5-2 进制转换
上面这两个算是比较特殊的值,很容易记住,其他的值靠记忆似乎不太好办,我们可以利用电脑的计算器工具快速计算。例子如下:
图 5-3 进制转换实例
打开电脑计算器,选择程序员模式,输入数字可以在各个进制之间自由转换。
记住 8 个数 128, 64, 32, 16,8,4, 2,1,分别对应 1Byte 中的 8个 位,二进制如果是 1,那么表示那个位上的值,如果为 0 那值就为 0,最后相加即是 10 进制。
例如 0b1001, 0110 转换成 十进制
1 0 0 1 0 1 1 0
128 0 0 16 0 4 2 0
最后得出 128+16+4+2 = 150
二进制转 十六 进制记住 4 个数 8,4,2,1,将 8 位拆成两个 4 位,相加然后转换成 十六进制贴在一起即可:
1 0 0 1 0 1 1 0
8 0 0 1 0 4 2 0
96
最后得出:0x96
上一章的单片机内部结构讲到过程序存储器 Flash,他数据存储方式按照下面讲的方式存储。
图 5-4 单片机存储结构
如上图所示,存储器就是一个个字节叠加起来,类似于盖楼房。每一层表示一个字节,每一层给一个地址,相当于楼层号码一样。如上图所示,第一、二、三层的地址分别是 0x00, 0x01, 0x02,一般情况下地址都是连续增加的。
因此,我们只要知道地址,就能找到指定的字节了,单片机正是通过地址来实现对存储器的读写的。例如,我们 STC89C52 单片机的程序存储器的大小为 8K 字节,也就是8*1024=8192 个字节,每一个字节有一个地址,而且从0开始的话,那么它的地址范围为0~8191,转换为十六进制的话,地址范围为 0x00~0x1FFF。
现实中的硬盘,内存条的硬件内部的结构就如上图所示,只不过每一个方框就是一个晶体管,一个晶体管可以存储0或者1,也就是 1bit。
接着上面的讲,一个晶体管能存储 1bit 的数据,也就是说芯片上集成的晶体管越多,能存储的数据就更大,运行的程序可以更复杂,某种意义上也就是芯片的运算能力越强了。所以,许多芯片或者手机厂商经常宣传说他的芯片有多少亿个晶体管,比同行性能强多少倍,就是这个道理。
另外一个就是芯片制造工艺,有的是 16 纳米,有的是5纳米,3纳米,这里的纳米指的就是能把晶体管做的多小,所以在相同面积的芯片上,3纳米工艺自然能比5纳米工艺多集成晶体管数量了。那5纳米工艺制造的手机芯片自然没有3纳米工艺制造的有竞争力了。
C 语言是一种通用的、面向过程式的计算机程序设计语言。 1972 年,丹尼斯·里奇在贝尔电话实验室设计开发了 C 语言。
我们的第一个C语言程序的功能为:编写一个能够在桌面上显示 “Hello,World!”的程序,通过这例子掌握C语言程序的基本结构。
想让C语言编写的程序能够正常运行,需要安装两种软件,分别为文本编辑器和C编译器,编译器的作用就是把我们写的C语言代码转成成计算机可识别的代码,相当于翻译员。
Window 自带文本编辑器,无需安装。 C语言编译器我们使用 GCC+MinGW,软件可以从网络上下载或者在 Nebula-Pi 资料包获得,如下图所示:
图 5-5 编译器工具路径
将工具软件解压至电脑即可,无需安装! 同时将 GCC、MinGW 的 bin 子目录到添加到您的 PATH 环境变量中,右键我的电脑,在”高级系统设置”中找到”系统属性”,添加步骤如下图所示。
图 5-6 添加环境变量
至此,工具软件准就绪了,打开 windows 系统命令提示符,输入 “ gcc -v” 如下图所示,如果出现了 gcc 版本信息表明我们上面的操作无误。接下来开始撸第一段C语言代码了。
图 5-7 GCC 版本检查
新建文本 hello.txt,并输入如下代码,存储为 hello.c,务必要将后缀改成.c ‘'’c
void main()
{
/* 第一段C语言代码 */
printf("Hello, World! \n");
// 返回
return;
} ‘’’ 图 5-8 第一行C代码
代码很简单,总共只有8行,下面逐行进行解释:
a) 程序的第1行 #include
b) 第2行 void main()为C语言的主函数,程序从这里开始执行。在整个代码中有且只能有一个 main()函数,是程序的唯一入口,和第3行,第8行的”{ }”是一体的,所有代码放在这对双括号里面。
c) 第4行为注释,放置在/.../之间的内容会被编译器忽略,这就是注释内容,方便程序员看的。
d) 第5行 printf(...) 是 C 中另一个可用的函数,会在屏幕上显示消息 “Hello, World!”。
e) 第6行也是注释,放在 // 后面的内容会被编译器忽略,这个是单行注释,下一行的内容不会注释掉。
f) 第7行 return 为C语言关键字,表示 main()函数运行结束。
g) 第5,7行语句后面都有一个分号,表明语句结束,C语言要求在每条语句之后添加”;”。
h) 代码编写完成,下面编译并执行。
操作步骤如下:
a) 新建文本文件,添加上述代码;
b) 文件保存为 hello.c,一定要确保文件格式为.c;
c) 打开系统命令提示符 CMD 窗口,并进入保存 hello.c的目录下,切换目录可以使用 “cd /d +目录地址”;
d) 输入 gcc hello.c,按回车,开始编译代码;
e) 如代码编译成功,将会在目录下生产a.exe 的可执行文件;
f) 命令行输入a.exe,执行程序;
g) 屏幕将出现 “Hello World!”字样,如下图所示。
图 5-9 第一行C代码执行结果
通过上一节掌握C语言程序的基本结构,本节开始讲解C语言的基本语法。
标识符其实就是一个代号,就像人的名字一样。在C语言中,常量、变量、函数的名称都是标识符。
标识符可以根据你个人的喜好来决定,前提条件是必须遵守C语言的一些规则:
1) 标识符只能是由英文字母(A-Z, a-z),数字(0-9),下划线(_)组成的字符串,并且第一个字符不能是数字。除此之外的特殊字符如@,$等不能出现在标识符中,例子如下:
<!-- -->
int LED_0 ; // 定义了一个标识符,即名称为 LED_0 的整型变量
<!-- -->
2) C语言区分大小写,下面表示两个不同的变量:
<!-- -->
int LED_0; //LED_0、led_0 为两个不同的变量
int led_0;
<!-- -->
3) 关键字不能作为标识符使用。
关键字是C语言程序中保留的一些字符串,有特定的用途,不能用来当做标识符。例如语句 “int for ;”是错误的,会在编译的时候报错。因为 for 是关键字,不能用来当做变量名。C语言关键字如下:
图 5-10 C语言关键字
上图为 32 个关键字,量不大,不用死记硬背,用多了自然能烂熟于胸。各个标识符功能介绍如下:
表 5-2 C语言关键字 | 序号 | 标识符 | 功能 | — | — | — | 1. | |||||||
int | 声明整型变量或函数 | 2. | float | 声明浮点型变量或函数返回值类型 | 3. | double | 声明双精度浮点型变量或函数返回值类型 | 4. | char | 声明字符型变量或函数返回值类型 | ||||
5. | short | 声明短整型变量或函数 | 6. | long | 声明长整型变量或函数返回值类型 | 7. | signed | 声明有符号类型变量或函数 | 8. | unsigned | ||||
声明无符号类型变量或函数 | 9. | if | 条件语句 | 10. | else | 条件语句否定分支(与 if 连用) | ||||||||
11. | switch | 开关语句分支 | ||||||||||||
12. | case | 开关语句分支 | ||||||||||||
13. | default | 开关语句中的”其它”分支 | ||||||||||||
14. | for | 一种循环语句 | ||||||||||||
15. | while | 循环语句的循环条件 | ||||||||||||
16. | do | 循环语句的循环体 | ||||||||||||
17. | break | 跳出当前循环 | ||||||||||||
18. | continue | 结束当前循环,开始下一轮循环 | ||||||||||||
19. | return | 子程序返回语句(可以带参数,也可不带参数) | ||||||||||||
20. | void | 声明函数无返回值或无参数,声明无类型指针 | ||||||||||||
21. | const | 定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变 | ||||||||||||
22. | sizeof | 计算数据类型或变量长度(即所占字节数) | ||||||||||||
23. | struct | 声明结构体类型 | ||||||||||||
24. | typedef | 用以给数据类型取别名 | ||||||||||||
25. | static | 声明静态变量 | ||||||||||||
26. | extern | 声明变量或函数是在其它文件或本文件的其他位置定义 | ||||||||||||
27. | auto | 声明自动变量 | ||||||||||||
28. | register | 声明寄存器变量 | ||||||||||||
29. | enum | 声明枚举类型 | ||||||||||||
30. | goto | 无条件跳转语句 | ||||||||||||
31. | union | 声明共用体类型 | ||||||||||||
32. | volatile | 说明变量在程序执行中可被隐含地改变 |
在程序中有些数据是不需要改变的,我们把这些不需要改变的固定值称为常量。例如,我们前面程序用到的 “hello world!”就是一个字符串常量。常量的类型包括:整数常量、浮点数常量、字符常量、字符串常量。下面举例说明:
int a =55 ; // 55 为整数常量
float b = 1.23 ; //1.23 为浮点数常量,即常说的小数
char mychar = 'a'; //a 为字符常量,需把字符常量需放在单引号里面
printf("hello world "); //hello world 为字符串常量,需用双引号括起来
有些特殊字符常量是无法通过字母来表示的,例如回车、换行等。C语言通过转义字符来实现,即反斜杠加字符的方式,例如’\n’,表示换行符。如果我们前面的 hello .c程序中想要把 hello 和 world 分别显示在两行,修改程序如下:
#include <stdio.h>
void main()
{
/* 第一段C语言代码 */
printf("Hello\nWorld"); // \n表示换行
// 返回
return;
}
运行结果如下:
图 5-11 运行结果
常用转义字符列表如下:
表 5-3 C转义序列
序号 | 转义序列 | 含义 |
---|---|---|
1. | \n | 换行符 |
2. | \r | 回车符 |
3. | \b | 退格符 |
4. | \ | \ 字符 |
5. | ' | ’ 字符 |
6. | " | ” 字符 |
7. | \a | 警报铃声 |
8. | \f | 换页符 |
9. | \t | 水平制表符 |
10. | \v | 垂直制表符 |
单片机C编程中最常用的转义字符为换行符(\n)和回车符(\r)。
在C语言中最常用的常量定义法为使用关键字#define,我们通过一个计算圆的周长的例子来说明,编辑代码,存储为 perimeter.c,如下所示:
/*
程序功能:计算圆的周长
*/
#include <stdio.h>
// 定义两个常量 PI,R
#define PI 3.14
#define r 10
void main()
{
float L; // 定义周长变量
L = 2 * PI * r;// 周长计算公式:L=2πr
printf("圆的周长为: %f", L);// 显示结果
return;
}
图 5-12 使用#define
运行结果如下:
图 5-13 define 使用试验
上述代码中第6、7行,我们用#define 定义了两个常量 PI 和r。定义完后,标识符 PI 就等于3.14,标识符r就等于 10,在程序中可以直接使用标识符进行运算,使用标识符能够直观的表示它具体代表什么意思,极大的减轻了程序员的负担。
程序中不能改变数据的称为常量,相对的,能改变的称为变量。变量用来存储程序运行过程产生的中间数据。这些数据实际是存储在内存当中的,变量的定义就是给这些内存取一个名字,编写程序的时候通过这个变量名就可以操作这些内存。变量定义的基本形式如下:
变量类型名 变量名;
举类说明如下:
int a;
char b;
float c;
定义了 int, char, float 三种类型的变量,变量名分别为a,b,c。
变量定义的另一种形式:
变量类型名 变量名1,变量名2,变量名3;
类型相同的变量可放在同一行,变量名之间用逗号隔开,如下:
int a,b,c;
char d,e,f;
变量定义好之后,可以进行变量的初始化,格式如下:
变量名 = 值;
举例说明:
// 变量定义
int a;
char b;
float c;
// 变量赋值
a = 1;
b = 'x';
c = 1.23;
上述语句中,第 2-4 行是变量的定义,第 6-8 行为变量赋值:将1赋值给 int 类型的变量a,执行完这条语句之后a就等于1了。字符x赋值给 char 类型变量b,3.14 赋值给了 float 类型的变量c。还可以在变量定义的时候直接赋值,即变量的初始化,格式如下:
变量类型名 变量名 = 值;
变量类型名 变量名1 = 值1,变量名2 = 值2,变量名3 = 值3……;
举例说明:
// 变量定义,并初始化
int a =1;
char b = 'x';
float c = 1.23,d=4.56,e=7.89;
值得注意的是,只有变量的数据类型相同时,才可以在同一行语句里进行初始化。
前面我们定义了变量,那么变量在内存实际占用了多大空间呢?数据类型指定变量占用空间的大小。常用数据类型以及所占内存大小如下表所示:
表 5-4 数据类型
序号 | 数据类型 | 位数 | 占内存字节数 | 十进制取值范围 |
---|---|---|---|---|
1. | bit | 1 | 0~1 | |
2. | signed char | 8 | 1 | -128~127 |
3. | unsigned char | 8 | 1 | 0~255 |
4. | enum | 16 | 2 | -32768~32767 |
5. | signed short | 16 | 2 | -32768~32767 |
6. | unsigned short | 16 | 2 | 0~65535 |
7. | signed int | 16 | 2 | -32768~32767 |
8. | unsigned int | 16 | 2 | 0~65535 |
9. | signed long | 32 | 4 | -2147483648~2147483648 |
10. | unsigned long | 32 | 4 | 0~4294967295 |
11. | float | 32 | 4 | 0.175494E-38~0.402823E+38 |
12. | sbit | 1 | 0~1 | |
13. | sfr | 8 | 1 | 0~255 |
14. | sfr16 | 16 | 2 | 0~65535 |
在单片机C语言编程中,上述代码中的 char, int 相当于表格中的 unsigned char, unsigned int 。表格中第 12-14 行为单片机特有的数据类型。 sbit 存储空间为 1bit,取值范围为0或者1。 sfr 为特殊功能寄存器类型, 8bit,即一个字节,可表示的范围为 0-255。 @@ -571,205 +544,149 @@ g) 屏幕将出现 “Hello World!”字样,如下图所示。 |—|—|—|—| | 算数运算符 | | | | | 1. | + | a+b | a变量值和b变量值相加 | | 2. | - | a-b | a变量值和b变量值相减 | | 3. | * | ab | a变量值乘以b变量值 | | 4. | / | a/b | a变量值除以b变量值 | | 5. | \% | a%b | a变量值除以b变量值的余数 | | 6. | ++ | a++ | 等同于a=a+1,a值自加1 | | 7. | – | a– | 等同于a=a-1,a值自减1 | | 赋值运算符 | | | | | 8. | = | a=1 | 将1赋值给变量a | | 9. | += | a+=b | 等同于a=a+b,将a加b的结果赋值给a | | 10. | -= | a-=b | 等同于a=a-b,将a减b的结果赋值给a | | 11. | *= | a=b | 等同于a=a*b,将a乘b的结果赋值给a | | 12. | /= | a/=b | 等同于a=a/b,将a除b的结果赋值给a | | 13. | %= | a%=b | 等同于a=a%b,将a除b的余数赋值给a | | 关系运算符 | | | | | 14. | > | a>b | 测试a是否大于b | | 15. | < | a<b | 测试a是否小于b | | 16. | == | a==b | 测试a是否等于b | | 17. | >= | a>=b | 测试a是否大于等于b | | 18. | <= | a<=b | 测试a是否小于等于b | | 19. | != | a!=b | 测试a是否不等于b | | 逻辑运算符 | | | | | 20. | && | a&&b | 变量a与变量b作逻辑”与”操作,两个变量都为”真”,结果才为”真”,否则为”假” | | 21. | || | a||b | 变量a与变量b作逻辑”或”操作,只要任何一个变量为”真”,结果为”真”,否则为”假” | | 22. | ! | !a | 将变量a值取反,即原来为”真”,结果为”假”,原来为 “假”,结果为”真” | | 位运算符 | | | | |
» | a»b | 将a变量值右移b位 | 24. | « | a«b | 将a变量值左移b位 | 25. | a | b | 将变量a和变量b按位作”或”运算 | 26. | & | |||||
a&b | 将变量a和变量b按位作”与”运算 | 27. | ^ | a^b | 将变量a和变量b按位作”异或”运算 | 28. | ~ | ~a | 将a的每一位取反 | 其他运算符 | |||||||
29. | & | a=&b | 将b变量的地址存入a变量 | 30. | * | a=*b | 将地址b中的内容赋值给a |
下面通过程序代码 operator.c,并举例介绍常用运算符的操作。
/*******************************************************************
* 运算符实例
*******************************************************************/
#include <stdio.h>
void main() // 程序主函数入口,每个C语言程序有且只有一个
{
int a = 10;
int b = 5;
int c;
/*********************************************
* 算术运算符实例
**********************************************/
printf("\-\-\--- 算术运算符实例\-\--- \n\n");
printf("初始值:a=10,b=5\n\n");
c = a + b; //a 加b,并将结果赋值个变量c
printf("a+b = %d\n",c);
c = a - b; //a 减b,并将结果赋值个变量c
printf("a-b = %d\n",c);
c = a * b; //a 乘b,并将结果赋值个变量c
printf("a*b = %d\n",c);
c = a / b; //a 除以b,并将结果赋值个变量c
printf("a/b = %d\n\n",c);
a=10;
a++;
printf("a=10,a++之后,a= %d\n",a);
a=10;
a--;
printf("a=10,a-- 之后,a= %d\n\n",a);
/*********************************************
* 关系运算符实例
**********************************************/
printf("\-\-\--- 关系运算符实例\-\--- \n\n");
a = 10;// 改变a,b的值下面语句会输出不同结果
b = 5;
printf(" == 运算符实例\n\n");
printf("初始值:a=%d,b=%d\n",a,b);
if(a==b) // 如果a等于b,执行下面{}里面的语句,否则执行 else 的{}里面的语句
{
printf("a 等于b\n");
}
else
{
printf("a 不等于b\n");
}
printf("\n < 运算符实例\n\n");
printf("初始值:a=%d,b=%d\n",a,b);
if(a<b) // 如果a小于b,执行下面{}里面的语句,否则执行 else 的{}里面的语句
{
printf("a 小于b\n");
}
else
{
printf("a 不小于b\n");
}
printf("\n其他关系运算符情况类似!\n");
return;
}
图 5-14 运算符练习代码
运行结果如下:
图 5-15 运算符练习结果
**单片机C语言编程中,位运算符用的相对较多,位的3个基本运算符,分别为:&:按位与, | :按位或,^:按位异或,真值表如下:** |
表 5-6 位运算真值表
a b a&b a|b a^b ————– ————- ————– ————– ————– 0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
假设A =55,B=21,选转换为二进制,查上表便可计算:
A = 0011 0111
B = 0001 0101
A&B = 0001 0101
A | B = 0011 0111 |
A^ B = 0010 0010
~:按位取反操作符,即0变1,1变0:
A = 0011 0111
~A = 1100 1000
:右移运算符
如A»3,将A右移动3位,并在左边补3个0
A = 0011 0111
= 0 0110 先右移动3位
A»3 = 0 0110 左边补3个0
«:左移运算符,与右移类似
如A»3,将A左移动3位,并在右边补3个0
A = 0011 0111
= 1011 1 先左移动3位
A«3 = 1011 1000 右边补3个0
上面讲解的都是在一条语句中只有一个运算符,如果有多个运算符的情况下该怎么计算呢?例如下面的赋值语句:
a = 1 + 2 * 3;
// 运算结果应该为7,即先算2*3,再加1,原因为” * “的优先级比” + “更高
各运算符的优先级如下表所示:
表 5-7 运算符优先级
类别 运算符 结合性 ————— —————————————– ——————– 后缀 () [] -> . ++ - - 从左到右
一元 + - ! ~ ++ - - (type)* & sizeof 从右到左
乘除 * / % 从左到右
加减 + - 从左到右
移位 « » 从左到右
关系 < <= > >= 从左到右
相等 == != 从左到右
位与 AND & 从左到右
位异或 XOR ^ 从左到右
位或 OR | 从左到右 |
逻辑与 AND && 从左到右
逻辑或 OR | 从左到右 |
条件 ?: 从右到左
赋值 = += -= *= /= %=»= «= &= ^= | = 从右到左 |
C语言的程序执行方式为,一条一条语句按顺序往下执行,在程序中加入流程控制语句,可以将程序跳转至指定的地方运行。下面讲解C语言常用的流程控制语句。
if 语句
表达式如下:
if(条件表达式)
{动作}
语法:
如果”条件表达式”的值为真(非零的数),则执行{ }内”动作”,如果”条件表达式”为假,则跳过该”动作”而继续往下执行。
举例说明编写, if.c文件如下:
/********************************************************
* 程序功能:
*使用 if 语句判断,按键输入的是否为数字
*********************************************************/
#include <stdio.h>
void main()
{
int number;
printf("\n请按下键盘的一个按键,并按回车键:");
scanf("%d",&number);
if(number<=9) // 先判断按的按键是否小于等于9,是的话,执行{}里的内容
{
printf("\n输入了数字:%d\n",number);
}
printf("\n程序结束!\n");
return;
}
图 5-16 if 语句代码
运行结果如下,可尝试输入非数字的按键。
图 5-17 if 语句运行结
if –else 语句
表达式如下:
if(条件表达式)
{动作1}
else
{动作2}
语法:
如果条件表达式为真,则执行动作1,跳过 else 部分的动作2,接着往下执行。如果条件表达式为假,则跳过动作1,执行动作2,然后继续往下执行。
举例说明编写, if-else.c文件如下:
/********************************************************
* 程序功能:
*使用 if-else 语句判断,按键输入的是否为数字或字符
*********************************************************/
#include <stdio.h>
void main()
{
int number;
printf("\n请按下键盘的一个按键,并按回车键:");
scanf("%d",&number);
if(number<=9) // 先判断按的按键是否小于等于9,是的话,执行{}里的内容
{
printf("\n输入了数字:%d\n",number);
}
else
{
printf("\n输入的不是数字,是一个字符!\n");
}
printf("\n程序结束!\n");
return;
}
图 5-18 if-else 语句代码
2次运行程序,输入的分别是数字1和字符e,程序执行结果如下:
图 5-19 if-else 试验结果
switch-case 语句
表达式如下:
switch(条件表达式)
{
case 条件值 1:
动作1
break;
case 条件值 2:
动作2
break;
...
default:
动作N;
break;
}
语法:
先计算”条件表达式”的值,然后逐个和 case 后面的”条件值”比较,如果不相等,则顺序往下比较,如果一直不相等,则执行 default 后面的语句。如果等于执行这个”条件值”后面的语句,并且后续所有 case 后的语句都不执行。
举例说明编写, caseswitch.c文件如下:
/********************************************************
* 程序功能:
*使用 switch-case 语句判断,根据输入的数字,显示星期几。
*1-7 分别对应星期一-星期日
*其他数字无效
*********************************************************/
#include <stdio.h>
void main()
{
int a;
printf("请输入数字,回车结束: ");
scanf("%d",&a);
switch(a) // 输入数字a,和下面 case 后面的数字对比
{
case 1:printf("\n星期一\n");
break;
case 2:printf("\n星期二\n");
break;
case 3:printf("\n星期三\n");
break;
case 4:printf("\n星期四\n");
break;
case 5:printf("\n星期五\n");
break;
case 6:printf("\n星期六\n");
break;
case 7:printf("\n星期日\n");
break;
default:printf("\n输入错误!\n");
}
return;
}
图 5-20 case 语句代码
运行3次,分别输入不同数字,结果如下图所示:
图 5-21 case 语句运行结果
while 循环语句
表达式如下:
while(条件表达式)
{动作}
语法:
先执行 while 后面的”条件表达式”,如果为真,则执行{}里面的”动作”,执行完之后,再次回去执行”条件表达式”。如此,一直循环,直到”条件表达式”不为真,才结束 while 循环。
举例说明编写, while.c文件如下:
/********************************************************
* 程序功能:
*使用 whie 语句
* 循环打印变量值
*********************************************************/
#include <stdio.h>
void main ()
{
int a = 0;// 变量定义,并初始化为0
/**********************************
1.先判断a是否小于 10,成立的话,执行{}
里面的语句,{}里面语句执行完之后,在判断
a是否小于 10,成立的话,继续执行{}内语句,
如此循环,直到a不小于 10.
2.下面程序中,{}内没执行一次a的值加1,因此,
执行 10 次之后,a不小于 10 ,循环结束。
**********************************/
while( a < 10 )
{
a=a+1;
printf("a 的值:%d\n", a);
}
printf("\n程序结束!\n", a);
return;
}
图 5-22 while 语句代码
程序运行结果如下:
图 5-23 while 运行结果
for 循环语句
表达式如下:
for(初始化;条件1;表达式2)
{ 动作 }
语法:
“初始化”首先被执行,并且只会执行一次;
判断”条件 1”,如果为真,执行后续{}中的”动作”,如果不为真,则结束 for 循环;
执行完”动作”后,执行”表达式 2” ,这里的”表达式 2” 往往会更新”条件 1” 的状态;
回到2继续执行。
举例说明编写, for.c文件如下:
/********************************************************
* 程序功能:
*使用 for 语句
* 循环打印变量值
*********************************************************/
#include <stdio.h>
void main ()
{
int a;// 变量定义
/**********************************
1.for 循环首先出初始化a=0
2.执行第二条语句判断a<10 是否成立,不成立直接结束
3.如果2成立
4.执行{}内的所有内容
5.执行a++
6.跳转到2继续执行
a每次循环都加1,因此,{}的内容将执行 10 次
**********************************/
for(a = 0;a<10;a++)
{
printf("a 的值:%d\n", a);
}
printf("\n程序结束!\n", a);
return;
}
图 5-24 for 语句代码
运行结果如下:
图 5-25 for 语句运行结果
函数是一组一起执行一个任务的语句,通常我们会让函数来执行一个特定的任务。如果我们在程序的不同地方需要多次执行这个任务,我们只需要调用这个函数即可,而不需要每次都重复写这段代码。
我们前面用到过得 prinf(),就是标准的C语言库函数,它的功能就是打印显示指定的数据。定义函数:
返回值类型 函数名称(参数1,参数2,参数3,…)
{
函数主体;
}
语法:
返回值类型:一个函数可以返回一个值或者不返回。“返回值类型”就指这个值的数据类型。如果函数没有返回值,那么,”返回值类型就是”关键字 void。
函数名称:这是函数标识符,也就是这个函数的名字。
参数:参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。
函数主体:函数主体包含一组定义函数执行任务的语句。
举例说明:
/********************************************************
* 程序功能:
*比较两个数的值,并显示较小的值
* 循环打印变量值
*********************************************************/
#include <stdio.h>
void main ()
{
int a = 1,b=2;
int c;
//a,b谁小,就把它赋值给c,然后显示c,就达到了显示较小值的目的
if(a<b)
{
c=a;
}
else
{
c=b;
}
printf("较小值的值:%d\n",c);
return;
}
图 5-26 函数代码1
如上第 14-21 行是比较a和b大小的功能代码,下面我们使用函数替代他们。编写代码 function.c,如下:
/********************************************************
* 程序功能:
*比较两个数的值,并显示较小的值
* 循环打印变量值
*********************************************************/
#include <stdio.h>
// 计算较小值得函数
int Min(int num1,int num2)
{
int result;
if(num1<num2)
{
result=num1;
}
else
{
result=num2;
}
return result;
}
// 主函数
void main()
{
int a = 1,b=2;
int c;
// 调用函数 Min(),返回较小值
c=Min(a,b);
printf("\n较小值的为:%d\n",c);
return;
}
图 5-27 函数代码2
在第 28 行,通过调用函数 Min(),即一条语句替换了最开始的多条语句。上图的第 8-21 行是我们定义的函数 int Min( int num1, int num2 ) ,函数的返回值类型为 int,函数名称为 Min,函数参数为 num1, num2 ,函数主体的功能为比较 num1, num2 的大小,并将小的值返回。在第 28 行调用函数的时候,我们使用要比较的值a,b传递到函数里面,即替换了 num1, num2 。所以,函数的返回值就是a,b中小的那个值。程序运行结果如下图所示:
图 5-28 函数代码运行结果
为了方便我们后续的单片机开发,本章介绍了C语言的基础知识,基本都是点到为止。更多的内容请参考专业的C语言书籍。本章中涉及的代码均放入了资料包中,如下图所示。
图 5-29 C语言代码路径