1 Star 0 Fork 1

RYMCU/30-days-of-nebula-pi

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
5-单片机C语言基础.md 38.86 KB
一键复制 编辑 原始数据 按行查看 历史

第5章 单片机C语言基础

5.1进制转换基础知识

进制实际是一个非常简单易懂的概念,对于初学者来说也很容易上手。我们接触最多的就是十进制了,它的特点为逢十进一,包含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 的十进制与二进制、十六进制之间的转换关系,对程序的编写有很大的好处。

5.2字节表示法

我们通常用下图所示的方式来表示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 进制转换实例

打开电脑计算器,选择程序员模式,输入数字可以在各个进制之间自由转换。

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

5.4数据存储方式

上一章的单片机内部结构讲到过程序存储器 Flash,他数据存储方式按照下面讲的方式存储。

图 5-4 单片机存储结构

如上图所示,存储器就是一个个字节叠加起来,类似于盖楼房。每一层表示一个字节,每一层给一个地址,相当于楼层号码一样。如上图所示,第一、二、三层的地址分别是 0x00, 0x01, 0x02,一般情况下地址都是连续增加的。

因此,我们只要知道地址,就能找到指定的字节了,单片机正是通过地址来实现对存储器的读写的。例如,我们 STC89C52 单片机的程序存储器的大小为 8K 字节,也就是8*1024=8192 个字节,每一个字节有一个地址,而且从0开始的话,那么它的地址范围为08191,转换为十六进制的话,地址范围为 0x000x1FFF。

现实中的硬盘,内存条的硬件内部的结构就如上图所示,只不过每一个方框就是一个晶体管,一个晶体管可以存储0或者1,也就是 1bit。

接着上面的讲,一个晶体管能存储 1bit 的数据,也就是说芯片上集成的晶体管越多,能存储的数据就更大,运行的程序可以更复杂,某种意义上也就是芯片的运算能力越强了。所以,许多芯片或者手机厂商经常宣传说他的芯片有多少亿个晶体管,比同行性能强多少倍,就是这个道理。

另外一个就是芯片制造工艺,有的是 16 纳米,有的是5纳米,3纳米,这里的纳米指的就是能把晶体管做的多小,所以在相同面积的芯片上,3纳米工艺自然能比5纳米工艺多集成晶体管数量了。那5纳米工艺制造的手机芯片自然没有3纳米工艺制造的有竞争力了。

5.5 第一个C语言程序

C 语言是一种通用的、面向过程式的计算机程序设计语言。 1972 年,丹尼斯·里奇在贝尔电话实验室设计开发了 C 语言。

我们的第一个C语言程序的功能为:编写一个能够在桌面上显示 "Hello,World!"的程序,通过这例子掌握C语言程序的基本结构。

5.5.1 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 版本检查

5.5.2 编写第一段C代码

新建文本 hello.txt,并输入如下代码,存储为 hello.c,务必要将后缀改成.c '''c

include <stdio.h>

void main()

{

/* 第一段C语言代码 */

printf("Hello, World! \n");

// 返回

return;

} ''' 图 5-8 第一行C代码

代码很简单,总共只有8行,下面逐行进行解释:

a) 程序的第1行 #include <stdio.h> 是预处理器指令,告诉 C 编译器在实际编译之前要包含 stdio.h 文件。

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) 代码编写完成,下面编译并执行。

5.5.3 编译执行C代码

操作步骤如下:

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代码执行结果

5.6 C语言语法

通过上一节掌握C语言程序的基本结构,本节开始讲解C语言的基本语法。

5.6.1标识符与关键字

标识符其实就是一个代号,就像人的名字一样。在C语言中,常量、变量、函数的名称都是标识符。

标识符可以根据你个人的喜好来决定,前提条件是必须遵守C语言的一些规则:

  1. 标识符只能是由英文字母(A-Z, a-z),数字(0-9),下划线(_)组成的字符串,并且第一个字符不能是数字。除此之外的特殊字符如@,$等不能出现在标识符中,例子如下:
<!-- -->

int LED_0 ; // 定义了一个标识符,即名称为 LED_0 的整型变量

<!-- -->
  1. C语言区分大小写,下面表示两个不同的变量:
<!-- -->

int LED_0; //LED_0、led_0 为两个不同的变量

int led_0;

<!-- -->
  1. 关键字不能作为标识符使用。

关键字是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 | 说明变量在程序执行中可被隐含地改变 |

5.6.2常量与变量

在程序中有些数据是不需要改变的,我们把这些不需要改变的固定值称为常量。例如,我们前面程序用到的 "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.6.3数据类型

前面我们定义了变量,那么变量在内存实际占用了多大空间呢?数据类型指定变量占用空间的大小。常用数据类型以及所占内存大小如下表所示:

表 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=ab,将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值取反,即原来为"真",结果为"假",原来为 "假",结果为"真" | | 位运算符 | | | | | 23. | >> | 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

1 1 1 1 0

假设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 || 从左到右

条件 ?: 从右到左

赋值 = += -= *= /= %=>>= <<= &= ^= |= 从右到左

逗号 , 从左到右

5.6.5流程控制

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 语句运行结果

5.6.6函数

函数是一组一起执行一个任务的语句,通常我们会让函数来执行一个特定的任务。如果我们在程序的不同地方需要多次执行这个任务,我们只需要调用这个函数即可,而不需要每次都重复写这段代码。

我们前面用到过得 prinf(),就是标准的C语言库函数,它的功能就是打印显示指定的数据。定义函数:

返回值类型 函数名称(参数1,参数2,参数3,...)

{

函数主体;

}

语法:

**返回值类型:一个函数可以返回一个值或者不返回。"返回值类型"**就指这个值的数据类型。如果函数没有返回值,那么,"返回值类型就是"关键字 void。

**函数名称:**这是函数标识符,也就是这个函数的名字。

**参数:**参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。

**函数主体:**函数主体包含一组定义函数执行任务的语句。

举例说明:

/********************************************************
* 程序功能:
*比较两个数的值,并显示较小的值
* 循环打印变量值
*********************************************************/
#include <stdio.h>  

void main ()
{
    int a = 1b=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 函数代码运行结果

5.7本章小结

为了方便我们后续的单片机开发,本章介绍了C语言的基础知识,基本都是点到为止。更多的内容请参考专业的C语言书籍。本章中涉及的代码均放入了资料包中,如下图所示。

图 5-29 C语言代码路径

马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
其他
1
https://gitee.com/rymcu/thirty-days-of-nebula-pi.git
git@gitee.com:rymcu/thirty-days-of-nebula-pi.git
rymcu
thirty-days-of-nebula-pi
30-days-of-nebula-pi
main

搜索帮助

A270a887 8829481 3d7a4017 8829481