二单片机C语言入门之判断语句
C语言中一个相当常用的语句结构就是判断语句,判断语句结构要求程序员指定一个或者多个需要判断的条件,以及条件满足或者不满足时程序需要执行的动作(可选)。
C语言中常用的判断语句如下:
判断语句
单片机按键状态读取图
if语句的格式及用法
第一种形式
if(条件表达式)
{
条件表达式为真时需要执行的语句1;
}
语句解释:当条件表达式为真时,程序将执行语句1,如果if条件表达式不为真,将跳转到大括号外继续执行后续的语句。
举个简单的例子,单片机中一般采用IO口来读取按键的状态(硬件如上图),需要实现的是按键每按下一次,自定义变量seft_count值自加1。
按上面要求,采用判断语句的程序如下:
Unsigned int seft_count //自定义变量
if(P3^0==0) //判断按键按下
{
seft_count = seft_count+1; //变量自加1
}
第二种形式
if(条件表达式)
{
条件表达式为真时需要执行的语句1;
}
else
{
上述if条件不满足,执行语句2;
}
语句解释:当if条件表达式为真时,程序将执行语句1,如果if条件表达式不为真时,将执行语句2。
同样上面硬件,需要实现的是按键每按下一次,自定义变量seft_count值自加1,如果按键没有按下,自定义变量值seft_count值自减1。
Unsigned int seft_count //自定义变量
if(P3^0==0) //按键按下
{
seft_count = seft_count+1; //变量自加1
}
else //按键没有按下
{
seft_count = seft_count-1; //变量自减1
}
第三种形式
if(条件表达式1)
{
条件表达式1为真时需要执行的语句1;
}
else if(条件表达式2)
{
条件1不为真,条件表达式2为真时需要 执行的语句2;
}
语句解释:当if条件表达式1为真时,程序将执行语句1,如果if条件表达式1不为真时,转而判断if表达式2是否为真,如果为真则将执行语句2。如果两个条件表达式都不为真,则执行if判断后续的语句。
同样上面硬件,需要实现的是按键每按下一次,自定义变量seft_count值自加1,按键没有按下的情况下,如果自定义的变量值seft_count大于0,则自定义变量值seft_count值自减1。
Unsigned int seft_count //自定义变量
if(P3^0==0)
{
seft_count = seft_count+1;
}
else if(seft_count>0) //变量值大于0为真
{
seft_count = seft_count-1; //变量自减1
}
第四种形式
if(条件表达式1)
{
条件表达式为真时需要执行的语句1;
}
else if(条件表达式2)
{
条件1不为真,条件表达式2为真时需要执行的语句2;
}
else
{
上述条件都不满足,则执行语句3;
}
语句解释:当if条件表达式1为真时,程序将执行语句1,如果if条件表达式1不为真时,转而判断if表达式2是否为真,如果条件2为真则将执行语句2。如果两个条件表达式都不为真,则执行语句3.
同样上面硬件,需要实现的是按键每按下一次,自定义变量seft_count值自加1,按键没有按下的情况下,如果自定义的变量值seft_count大于0,则自定义变量值seft_count值自减1,如果按键没有按下,并且seft_coun也不满足大于0的情况下,清除自定义变量seft_count的值。
Unsigned int seft_count //自定义变量
if(P3^0==0)
{
seft_count = seft_count+1;
}
else if(seft_count>0)
{
seft_count = seft_count-1;
}
else
{
seft_count = 0; //变量清零
}
switch语句的格式及用法
与if判断语句非此即彼的判断不一样,switch判断的条件可以选择很多分支,简单来说,if可以看作不是甲就是乙,而switch判断的分支可以是甲乙丙丁...等等分成很细致的条件,其格式及形式如下:
switch(表达式) //也可以是变量
{
case 常量表达式1://表达式必须是常量
{语句1;}break;
case 常量表达式2://表达式必须是常量
{语句2;}break;
case 常量表达式3://表达式必须是常量
{语句3;}break;
...
default://如果上述条件都不满足
{语句n;}break;
}
语句解释:switch判断语句,直观来说就是匹配语句,语句执行时,将switch(表达式)括号里的表达式运算的结果或变量,一个个跟case的常量去匹配,当两者相等时,相等的那个case满足判断条件,如果所有case的常量都跟表达式的结果不相等,那就执行default;
同样上面硬件,需要实现的是按键每按下一次,自定义变量seft_count值自加1,当按键按10次后,自定义变量值a加10,按键按20次后,变量值a加20,按键按30次后,变量值a加30。
unsigned int seft_count;
unsigned int a;
if(P3^0==0)
{
seft_count = seft_count+1;
Switch(seft_count)
{
case 10:{a = a+10;}break;
case 20: {a = a+20;}break;
case 30:{a = a+30;}break;
default:{;}break;
}
}
注意:举例只为了直观阐明判断语句用法,不代表单片机按键扫描的现实函数就是如此,别的不说,首先按键扫描读的端口状态就不能直接作为判断按键是否按下的直接条件,单片机应用后续再介绍,此处只介绍c语言。
另外,上述阐述的是判断语句的独立用法,判断语句还可以嵌套使用,大家可以自行理解[机智]
单片机C语言之函数
函数定义
函数是一个自我包含的完成一定相关功能的执行代码段。通常C语言的编译器会自带标准的函数库,这些都是一些常用的函数。标准函数已由编译器软件商编写定义,使用者直接调用就能了,而无需定义。但是标准的函数不足以满足使用者的特殊要求,因此C语言允许使用者根据需要编写特定功能的函数,要调用它必须要先对其进行定义。
定义的模式如下:
函数类型 函数名称(形式参数表)
函数类型是说明所定义函数返回值的类型。返回值其实就是一个变量,只要按变量类型来定义函数类型就行了。如函数不需要返回值函数类型能写作“void”表示该函数没有返回值。注意的是函数体返回值的类型一定要和函数类型一致,不然会造成错误。
函数名称的定义在遵循C语言变量命名规则的同时,不能在同一程序中定义同名的函数,这将会造成编译错误(同一程序中是允许有同名变量的,因为变量有全局和局部变量之分)。
形式参数是指调用函数时要传入到函数体内参与运算的变量,它可以是一个、几个或没有。当函数不需要形式参数时(即无参函数),括号内为空或写入“void”表示,但括号不能少。
函数体中能包含有局部变量的定义和程序语句,如函数要返回运算值则要使用return语句进行返回。若在函数的{}号中也能什么也不写,这就成了空函数。在一个程序项目中可以写一些空函数,在以后的修改和升级中能方便的在这些空函数中进行功能扩充。
函数的调用
(一)函数调用的一般说明
函数定义好以后,要被其它函数调用了才能被执行。C语言的函数是能相互调用的,但在调用函数前,必须对函数的类型进行说明,就算是标准库函数也不例外。
标准库函数的说明会被按功能分别写在不一样的头文件中,使用时只要在文件最前面用#include预处理语句引入相应的头文件。如前面使用的printf函数的说明是放在文件名为stdio.h的头文件中。
调用就是指一个函数体中引用另一个已定义的函数来实现所需要的功能,这个时候函数体称为主调用函数,函数体中所引用的函数称为被调用函数。主函数只是相对于被调用函数而言。
一个函数体中能调用数个其它的函数,这些被调用的函数同样也能调用其它函数,也能嵌套调用。但是在c51语言中有一个函数是不能被其它函数所调用的,它就是main主函数。
标准库函数只要用#include引入已写好说明的头文件,在程序就能直接调用函数了。如调用的是自定义的函数则要用如下形式编写函数类型说明:
类型标识符 函数的名称(形式参数表);
这样的说明方式是用在被调函数定义和主调函数是在同一文件中。也能把这些写到文件名.h的文件中用#include“文件名.h”引入。
如果被调函数的定义和主调函数不是在同一文件中的,则要用如下的方式进行说明,说明被调函数的定义在同一项目的不一样文件之上,这样说明的函数也能称为外部函数,定义如下:
extern类型标识符 函数的名称(形式参数表);
函数的定义和说明是完全不一样的,在编译的角度上看函数的定义是把函数编译存放在ROM的某一段地址上,而函数说明是告诉编译器要在程序中使用那些函数并确定函数的地址。如果在同一文件中被调函数的定义在主调函数之前,这个时候能不用说明函数类型。也就是说在main函数之前定义的函数,在程序中就能不用写函数类型说明了。能在一个函数体调用另一个函数(嵌套调用),但不允许在一个函数定义中定义另一个函数。还要注意的是函数定义和说明中的“类型、形参表、名称”等都要相一致。
(二)函数调用的一般形式
调用函数的一般形式如下:
函数名 (实际参数表)
“函数名”就是指被调用的函数。
实际参数表能为零或多个参数,多个参数时要用逗号隔开,每个参数的类型、位置应与函数定义时所的形式参数一一对应,它的作用就是把参数传到被调用函数中的形式参数,如果类型不对应就会产生一些错误。调用的函数是无参函数时不写参数,但不能省后面的括号。
下面我们看一下在实际应用中函数不同的调用方式:
1. 函数语句
例如printf(“Hello World!\n”);
它以“Hello World!\n”为参数调用printf这个库函数,在这里函数调用被看作了一条语句。
2. 函数参数
“函数参数”这种方式是指被调用函数的返回值当作另一个被调用函数的实际参数,如temp=StrToInt(CharB(16));CharB的返回值作为StrToInt函数的实际参数传递。
3. 函数表达式
例如temp=Count();
这个函数的调用作为一个运算对象出现在表达式中,称为函数表达式。例子中Count()返回一个int类型的返回值直接赋值给temp。注意的是这种调用方式要求被调用的函数能返回一个同类型的值,不然会出现不可预料的错误。
C51常用头文件
下面介绍一些常用的C51头文件:
absacc.h——包含允许直接访问8051不同存储区的宏定义;
assert.h——文件定义assert 宏,可以用来建立程序的测试条件;
ctype——字符转换和分类程序;
intrins.h——文件包含指示编译器产生嵌入式固有代码的程序的原型;
math.h——数学程序;
reg51.h——51的特殊寄存器;
reg52.h——52的特殊寄存器;
setjmp.h——定义jmp_buf类型和setjmp和longjmp程序的原型;
stdarg.h——可变长度参数列表程序;
stdlib.h——存储区分配程序;
stdio.h——标准输入和输出程序;
string.h——字符串操作程序、缓冲区操作程序。
对于常用的MCS-51单片机,必须包含reg51.h的头文件,因为该文件对51单片机的相关寄存器及位进行了定义,这样在程序中才可以使用这些资源。
reg51.h文件的具体内容如下:
#ifndef __REG51_H__
#define __REG51_H__
/* BYTE Register */ //单元定义
sfr P0 = 0x80;
sfr P1 = 0x90;
sfr P2 = 0xA 0 ;
sfr P3 = 0xB0;
sfr PSW = 0xD0;
sfr ACC = 0xE0;
sfr B = 0xF0;
sfr SP = 0x81;
sfr DPL = 0x82;
sfr DPH = 0x83;
sfr PCON = 0x87;
sfr TCON = 0x88;
sfr TMOD = 0x89;
sfr TL0 = 0x8A;
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;
sfr IE = 0xA8;
sfr IP = 0xB8;
sfr SCON = 0x98;
sfr SBUF = 0x99;
/* BIT Register */
/* PSW */ //位定义
sbit CY = 0xD7;
sbit AC = 0xD6;
sbit F0 = 0xD5;
sbit RS1 = 0xD4;
sbit RS0 = 0xD3;
sbit OV = 0xD2;
sbit P = 0xD0;
/* TCON */
sbit TF1 = 0x8F;
sbit TR1 = 0x8E;
sbit TF0 = 0x8D;
sbit TR0 = 0x8C;
sbit IE1 = 0x8B;
sbit IT1 = 0x8A;
sbit IE0 = 0x89;
sbit IT0 = 0x88;
/* IE */
sbit EA = 0xAF;
sbit ES = 0xAC;
sbit ET1 = 0xAB;
sbit EX1 = 0xAA;
sbit ET0 = 0xA9;
sbit EX0 = 0xA8;
/* IP */
sbit PS = 0xBC;
sbit PT1 = 0xBB;
sbit PX1 = 0xBA;
sbit PT0 = 0xB9;
sbit PX0 = 0xB8;
/* P3 */
sbit RD = 0xB7;
sbit WR = 0xB6;
sbit T1 = 0xB5;
sbit T0 = 0xB4;
sbit INT1 = 0xB3;
sbit INT0 = 0xB2;
sbit TXD = 0xB1;
sbit RXD = 0xB0;
/* SCON */
sbit SM0 = 0x9F;
sbit SM1 = 0x9E;
sbit SM2 = 0x9D;
sbit REN = 0x9C;
sbit TB8 = 0x9B;
sbit RB8 = 0x9A;
sbit TI = 0x99;
sbit RI = 0x98;
#endif
而absacc.h为对8051单片机的不同存储区的宏定义,具体如下:
#define CBYTE ((unsigned char volatile code *) 0) //定义程序存储器;
#define DBYTE ((unsigned char volatile data *) 0) //定义片内数据存储区;
#define PBYTE ((unsigned char volatile pdata *) 0) //定义页寻址空间;
#define XBYTE ((unsigned char volatile xdata *) 0) //定义片外数据存储区。
而intrins.h文件对指示编译器产生嵌入式代码,如空操作执行、位指令、栈操作指令等,该文件的具体内容如下:
extern void _nop_ (void); //空操作8051 NOP指令
extern bit _testbit_ (bit); //测试并清零位8051 JBC指令
extern unsigned char _cror_ (unsigned char,unsigned char); //字符循环左移
extern unsigned int _iror_ (unsigned int,unsigned char); //字符循环右移
extern unsigned long _lror_ (unsigned long,unsigned char); //整数循环右移
extern unsigned char _crol_ (unsigned char,unsigned char); //整数循环右移
extern unsigned int _irol_ (unsigned int,unsigned char); //整数循环左移
extern unsigned long _lrol_ (unsigned long,unsigned char); //长整数循环左移
extern unsigned char _chkfloat_(float); //测试并返回源点数状态
extern void _push_ (unsigned char _sfr); //压入堆栈
extern void _pop_ (unsigned char _sfr); //弹出堆栈
相关问答
麻烦高手帮我注释一下这段程序 51单片机 的voidt0(void)interr...[最佳回答]不知道你要怎么样的注释,它是一个定时器0,工作方式1的定时中断程序,定时器的定时时间好像是500个机器周期,其它的就是一些if条件语句和flag标志位判...
单片机 一条 IF语句 所需要的时间?还真不好确定,这与变量的数据类型有关,char,int对应的IF语句所需时间是不一样的。因为处理方式不一样。还真不好确定,这与变量的数据类型有关,char,int对应...
单片机 中 if 与switch的差异有哪些?if和switch都是C语言的判断语句一般的场合使用if或者switch都可以达到相同的效果,但其实也是有很大的差异和优缺点的。什么时候使用if?if顾名思义就...
51单片机 入门教程?1、单片机概念:在一片集成电路芯片上集成微处理器(CPU)、存储器(ROM和RAM)、I/O接口电路,从而构成了单芯片微型计算机,即单片机(singlechipMicrocomput...数字....
51单片机 c语言编程入门?1、单片机概念:在一片集成电路芯片上集成微处理器(CPU)、存储器(ROM和RAM)、I/O接口电路,从而构成了单芯片微型计算机,即单片机(singlechipMicrocomput...
单片机 新唐下面求注释.voidI2C_Ctrl(uint8_tstart,uint8_tst...[最佳回答]那个"__IO"是采用的宏定义,其原型是#define__IOvolatilevolatile的英语原意思是“易变”的,用来修饰变量,表示这个变量是要时时从内存中读取的,....
天津市近现代出过哪些女性名人?天津大学陈焱陈焱天津大学机械工程学院教授,博导。2004年毕业于英国牛津大学,获得博士学位。是英国机械工程师学会会士(FellowofIMechE,FIMechE),英国皇家...
51单片机 所有伪指令?MCS-51单片机常用伪指令一)符号定义伪指令符号定义名用法说明EQU为常量,符号名...MCS-51单片机常用伪指令一)符号定义伪指令符号定义名...
51单片机 怎么休眠 - 04535败笔 的回答 - 懂得呵呵,最近刚好研究了一下这个问题51单片机空闲和掉电模式应用我们知道单片机内部有一个电源管理寄存器PCON,这个寄存器的最低两位,IDL和PD这两位...
51单片机 秒表设计 怎么用按钮控制开始 停止和清零?-ZOL问答if(stop==0)flag_start=1;if(reset==0){flag_start=0;sec=0;}//计数程序if(flag_start){sec++;}#include...