C51的基本运算
-
C51语言的基本运算与标准C类似,主要包括算术运算、关系运算、逻辑运算、位运算和赋值运算及其表达式等。
算术运算符
算术运算的算术运算符及其说明如下
符号 说明 举例(设x=10,y=3) + 加法运算 z=x+y; //z=13 - 减法运算 z=x-y; //z=7 * 乘法运算 z=x*y; //z=30 / 除法运算 z=x/y; //z=3 % 取余数运算 z=x%y; //z=1 ++ 自增1 -- 自减1 自增运算符与自减运算符
运算符 说明 举例(设x初值为4) x++ 先用x的值,再让x加1 y=x++; //y为4,x为5 ++x 先让x+1,再用x的值 y=++x; //y为5,x为5 x-- 先用x的值,再让x-1 y=x--; //y为4,x为3 --x 先让x-1,再用x的值 y=--x; //y为3,x为3 逻辑运算符
逻辑运算符及其说明
运算符 说明 举例(设a=2,b=3) && 逻辑与 a&&b; //返回值为0 || 逻辑或 a||b; //返回值为1 ! 逻辑非 !a; //返回值为0 例如:条件“10>20”为假,“2<6”为真,则逻辑与运算为:
(10>20)&&(2<6)=0&&1=0
关系运算符
关系运算符及其说明
符号 说明 举例(设a=2,b=3) > 大于 a>b; //返回值为0 < 小于 a<b; //返回值为1 >= 大于等于 a>=b; // 返回值为0 <= 小于等于 a<=b; //返回值为1 == 等于 a==b; //返回值为0 != 不等于 a!=0; //返回值为1 位运算
位运算及其说明
符号 说明 举例 & 按位逻辑与 0x19&0x4d=0x09 | 按位逻辑或 0x19|0x4d=0x5d ^ 按位异或 0x19^0x4d=0x54 ~ 按位取反 x=0x0f,则~x=0xf0 << 按位左移(高位丢弃,低位补0) y=0x3a,若y<<2,则y=0xe8 >> 按位右移(高位补0,低位丢弃) w=0x0f,若w>>2,则w=0x03 - 0x19=19H=00011001,0x4d=01001101
00011001
相与 01001101 (上下相同就是该数,不同都是0)
= 00001001=09
00011001
相或 01001101 (上下相同是该数,不同为1)
= 01011101=5d
00011001
异或 01001101 (上下相同为0,不同为1)
= 01010100=54
x=0x0f,则~x=0xf0 按位取反
按位左移 00111010 (按位左移或右移后,空余的位补0)
左移两位 11101000
按位右移 00001111
右移两位 00000011
- 在实际应用中,常想改变I/O口某一位的值,而不影响其他位,如果I/O口可位寻址的,这个问题就很简单,但有时外扩的I/O口只能进行字节操作,要想实现单独位控,就要采用位操作
例:编写程序将扩展的某I/O口PORTA(只能字节操作)的PORTA.5清0,PORTA.1置为1.
/*要想使其第五位清0而其他位不动,那么使用与逻辑运算,使其与11011111相与*/
/*要想使其第一位置1而其他位不变,那么使用或逻辑运算,使其与00000001相或*/
#define<absacc.h>
#define PORTA XBYTE[0xffc0]/*以字节形式去访问片外的地址0ffc0*/
void main(void)
{
……
PORTA=(PORTA&0xdf)|0X02
……
}
指针和取地址运算符
-
指针变量用于存储某个变量的地址
-
C51用''和'&'运算符来提取变量内容和变量地址*
符号 | 说明 |
---|---|
* | 提取变量的内容 |
& | 提取变量的地址 |
- 提取变量的内容和变量的地址的一般的形式分别为:
*目标变量=指针变量 //将指针变量所指的存储单元内容赋值给目标变量。
指针变量=&目标变量 //将目标变量的地址赋值给指针变量。
注意:指针变量中只能存放地址(也就是指针型数据),一般情况下不要将非指针类型的数据赋值给一个指针变量。
例如: a=&b; //定义指向b的地址
c=*b; //定义指向b地址的内容
int i; //定义整型变量i
int*b; //定义指向整数的指针变量b
b=&i; //定义指向i的地址
错误写法:b=i,整型变量的值不可以等于指针变量
C51的分支与循环程序结构
- 在C51的程序结构上可以把程序分为三类,即顺序、分支和循环结构。
分支控制语句
-
分为if语句和switch语句
- if语句:if语句是用来判定所给定的条件是否满足,根据判定结果执行两种操作之一。if语句的基本结构if(表达式){语句}
- 形式1:if(表达式){语句}
if(x>y){max=x;min=y};/*若表达式为真就执行后面的语句*/
- 形式2:if(表达式){语句1;} else{语句2;}
if(x>y)/*if后表达式为真执行语句1,否则执行语句2*/ {max=x;} else{min=y;}
- if语句的嵌套格式
if,else if
if(表达式1){语句1;}/*依次向下判定,是否符合表达式1,执行或往下递推,直到是否符合表达式n-1,符合就是语句n-1,不符合就是语句n*/ else if(表达式2){语句2;} else if(表达式3){语句3;} ...... else{语句n;}
例如:
if(x>100){y=1;} else if{x>50}{y=2;} else if(x>30){y=3;} else if(x>20){y=4;} else {y=5;}
- switch语句:switch语句是多分支选择语句,一般形式如下
switch(表达式1)/*当表达式1和常量表达式1相同时,就执行后面的语句1,之后遇到break就退出switch语句,以此类推,当所有常量表达式没有与表达式相对应的值,那么就执行default后面的语句n+1*/ { case 常量表达式1:{语句1;}break; case 常量表达式2:{语句2;}break; …… case 常量表达式n:{语句n;}break; default:{语句n+1;} /*每一case常量表达式需互不相同,否则将混乱*/ /*各个case和default出现次序,不影响程序执行的结果*/ /*如果在case中遗忘了break语句,则程序执行了本行之后,不会按规定退出switch语句,而是将执行后续的case语句。在执行一个case分支后,使流程跳出switch结构,即终止switch语句的执行,可以用一条break语句完成*/ }
例如:在单片机程序设计中,常用switch语句作为键盘中按键按下的判别,并根据按下键的键号跳向各自的分支处理程序。
input: keynum=keyscan()/*keyscan是键盘扫描函数*/ switch(keynum) { case 1:key1();break;//如果按下键为1键,则执行函数key1() case 2:key2();break;//如果按下键为2键,则执行函数key2() case 3:key3();break;//如果按下键为3键,则执行函数key3() case 4:key4();break;//如果按下键为4键,则执行函数key4() …… default:goto input }
循环结构流程控制语句
-
实现循环结构的语句有以下三种:while语句、do-while语句和for语句。
- while语句:语法形式如下
while(表达式) { 循环体语句; } /*while是先判断表达式真假,若为假程序不会执行,为真才执行*/
例如:
while((P1&0x80))= =0) {}
while中的条件语句对AT89S52单片机的P1口第七位进行测试,如果P1 7为低(0),则由循环体无实际操作语句,故继续测试下去(等待),一旦P1 7变为高电平(1),则循环终止
- do while语句:语法形式如下
do { 循环体语句; } while(表达式); /*do while 先执行循环体语句,再判断表达式真假,若为假则停止程序,但前提数据已经录入,即程序已经运行了。*/
例:实型数组SAMPLE存有10个采样值,编写程序段,要求返回其平均值(平均值滤波)
float avg(float *sample) { float sum=0; char n=0; do { sum+=sample[n];/*sum+=sample与sum=sum+sample等价*/ n++; }while(n<10); return(sum/10); }
- 基于for语句的循环:for循环的一般格式如下:
for(表达式1;表达式2;表达式3) { 循环体语句; }
例:编写一个延时1ms程序
void delayms(unsigned char int j)/*delayms延时函数*/ { unsigned char i; while{j- -} { for(i=0;i<125;i++)/*执行一个for语句大概要延时8us,要执行125次,共延时1ms,利用for语句来延时*/ {;}/*等待*/ } }
例:求1+2+3+...+100的累加和
#include<reg51.h> #include<stdio.h> main() { int nvar1,nsum; for(nvarl=0,nsum=1;nsum<=100;nsum++) nvar1+=nsum; //累加求和 while(1); }
- break语句
例:
void main(void) { int i,sum; sum=0; for(i=1;i<=10;i++) { sum=sum+i; if(sum>5)break; print("sum=%d\n",sum);/*通过串口向计算机屏幕输出显示sum值*/ } }
- continue语句
例:输出整数1~100的累加值,但要求跳过所有个位为3的数。
void main(void) { int i,sum=0; for(i=1;i<=100;i++) { if(i%10= =3) continue; sum=sum+i; } print("sum=%d\n",sum);/*在计算机屏幕显示sum值,了解本语句的功能即可*/ }
- goto语句:基本格式如下:goto 标号
例:计算整数1~100的累加值,存放到sum中。
void main(void) { unsigned char i int sum; sumadd; sum=sum+i; i++; if(i<101) { goto sumadd/*无条件跳转到sumadd*/ } }