51单片机入门_江协科技_1~10_OB记录的笔记

1. 课程简介

  • 1.1. Kail5安装
  • 1.2. STC烧录工具
  • 1.3. 资料下载
  • 1.4. 软件装入Win7 x64虚拟机并测试通过
  • 1.5. 开发板准备就绪

2. 开发工具介绍与软件安装

  • 2.1. Kail5安装破解
  • 2.2. STC-ISP安装,USB驱动安装

3. 单片机及开发板介绍

  • 3.1. 单片机介绍
  • 3.2. 开发板介绍

4. 点亮一个LED

  • 4.1. LED的介绍
  • 4.2. Kail5 新建项目,新建.c程序文件,准备编程,程序编译生成.h格式
  • 4.3. Kail5 字体调整,中文显示改UT-8码.
  • 4.4. LED限流电阻500欧姆左右(5V/500=10mA)
  • 4.5. 电阻标识104表示10后4个零,200k欧姆;473表示47k欧姆;
  • 4.6. 开发板LED点亮原理;
  • 4.7. 进制转换,二进制转十六进制,0xff;
  • 4.8. 【#include<REGX51.H> 】头文件介绍,端口定义;
\\点亮一个LED的示例程序;
#include <REGX51.H>
void main()
{
	P2=0xfe;\\1111 1110;
}
  • 4.9. STC-ISP程序烧录需要重启开发板;

5. LED 闪烁

  • 5.1. LED闪烁,思路,P2=0xfe;P2=0xff;反复执行
  • 5.2. 因为CPU运行频率过高,实际肉眼无法察觉差别,引入STP-ISP的延时示例程序,选择12MHz频率;
  • 5.3. LED每隔500ms闪烁程序示例;
\\LED每隔500ms闪烁程序;
#include <REGX51.H>
void delay500ms()
{
	unsigned char i,j,k;
	_nop_();
	i=4;
	j=205;
	k=187;
	do
	{
		do
		{
			while (--k);
			}
		while (--j);
	}
	while (--i);		
}

void main()
{
	while(1)
	{
		P2=0xfe;
		delay500ms();
		P2=0xff;
		delay500ms();
	}
}

6. LED 流水灯

  • 6.1. delay函数中的_nop_空执行命令导致程序头文件需要增加【#include <INSTRANS.H> 】
  • 6.2. 程序的数据类型介绍:
类型存储大小值范围
char1 字节-128 到 127 或 0 到 255
unsigned char1 字节0 到 255
signed char1 字节-128 到 127
int2 或 4 字节-32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647
unsigned int2 或 4 字节0 到 65,535 或 0 到 4,294,967,295
short2 字节-32,768 到 32,767
unsigned short2 字节0 到 65,535
long4 字节-2,147,483,648 到 2,147,483,647
unsigned long4 字节0 到 4,294,967,295
float4 字节3.4e-38 ~ 3.7e38
double8 字节1.7e-308 ~ 1.7e308
  • 6.3. LED流水灯示例程序并未采用移位命令实现,用的是端口赋值-延时-端口赋值-延时…的方式实现,因此不做示例演示。
  • 6.4. 延时xxxms子函数程序示例:
void delayxms(unsigned int xms)
{
	unsigned char i,j;
	while (xms)
	{
		i=2;
		j=239;
		do
		{
			while (--j);
		}
		while (--i);
		--xms;	
	}
}

7. 独立按键控制LED亮灭

  • 7.1. 独立按键(轻触微动按钮)原理介绍
    在这里插入图片描述

  • 7.2. 开发板上面按键的原理图;
    在这里插入图片描述

  • 7.3. 参考< regx52.h>中对于单片机端口的定义,单独对一个LED进行操作,则独立一个按键控制一个LED亮灭的程序如下:

#include <REGX52.H>
void main()
{
		while(1)
	{
		if (P3_1==0)
		{
			P2_0=0;
		}
		else
		{
			P2_0=1;
		}
	}
}
  • 7.4. 需要注意如果程序变成如下样式,while(1)出现在尾部,则程序只能执行一遍,没法循环执行;
#include <REGX52.H>
void main()
{
	if (P3_1==0)
		{
			P2_0=0;
		}
		else
		{
			P2_0=1;
		}
	while(1) //程序只能执行一遍
	{
	
	}
	
}
  • 7.5. C51各种运算符汇总:
1.  赋值运算符

赋值运算符“=”,在C51中,它的功能是将一个数据的值赋给一个变量,如x=10。利用赋值运算符将一个变量与一个表达式连接起来的式子称为赋值表达式,在赋值表达式的后面加一个分号“;”就构成了赋值语句,一个赋值语句的格式如下:

        变量=表达式;

执行时先计算出右边表达式的值,然后赋给左边的变量。例如:

     x=8+9;   /*将8+9的值赋绐变量x*/

     x=y=5;   /*将常数5同时赋给变量x和y*/

在C51中,允许在一个语句中同时给多个变量赋值,赋值顺序自右向左。

2.  算术运算符

C51中支持的算术运算符有:

+    加或取正值运算符

-    减或取负值运算符

*    乘运算符

/    除运算符

%    取余运算符

加、减、乘运算相对比较简单,而对于除运算,如相除的两个数为浮点数,则运算的结果也为浮点数,如相除的两个数为整数,则运算的结果也为整数,即为整除。如25.0/20.0结果为1.25,而25/20结果为1。对于取余运算,则要求参加运算的两个数必须为整数,运算结果为它们的余数。例如:x=5%3,结果x的值为2。

3.  关系运算符

C51中有6种关系运算符:

>    大于

<    小于

>=   大于等于

<=   小于等于

==  等于

!=   不等于

关系运算用于比较两个数的大小,用关系运算符将两个表达式连接起来形成的式子称为关系表达式。关系表达式通常用来作为判别条件构造分支或循环程序。关系表达式的一般形式如下:

     表达式1  关系运算符  表达式2

关系运算的结果为逻辑量,成立为真(1),不成立为假(0)。其结果可以作为一个逻辑量参与逻辑运算。例如:5>3,结果为真(1),而10==100,结果为假(0)。

注意:关系运算符等于“==”是由两个“=”组成。

4.  逻辑运算符

C51有3种逻辑运算符:

||    逻辑或

&&    逻辑与

!    逻辑非

关系运算符用于反映两个表达式之间的大小关系,逻辑运算符则用于求条件式的逻辑值,用逻辑运算符将关系表达式或逻辑量连接起来的式子就是逻辑表达式。

逻辑与,格式:

       条件式1 && 条件式2

当条件式1与条件式2都为真时结果为真(非0值),否则为假(0值)。

逻辑或,格式:

       条件式1 || 条件式2

当条件式1与条件式2都为假时结果为假(0值),否则为真(非0值)。

逻辑非,格式:

        !条件式

当条件式原来为真(非0值),逻辑非后结果为假(0值)。当条件式原来为假(0值),逻辑非后结果为真(非0值)。

例如:若a=8,b=3,c=0,则!a为假,a && b为真,b && c为假。

C51语言能对运算对象按位进行操作,它与汇编语言使用一样方便。位运算是按位对变量进行运算,但并不改变参与运算的变量的值。如果要求按位改变变量的值,则要利用相应的赋值运算。C51中位运算符只能对整数进行操作,不能对浮点数进行操作。C51中的位运算符有:

5.  位运算符

&    按位与(全1为1,有0出0)

|    按位或(全0为0,有1出1)

^    按位异或(一样为0,不一样为1)

~    按位取反

<<    左移

>>    右移

【例】设a=0x45=01010100B,b=0x3b=00111011B,则a&b、a|b、a^b、~a、a<<2、b>>2分别为多少?

a&b=00010000b=0x10。

a|b=01111111B=0x7f。

a^b=01101111B=0x6f。

~a=10101011B=0xab。

a<<2=01010000B=0x50。

b>>2=00001110B=0x0e。

6.  复合赋值运算符

C51语言中支持在赋值运算符“=”的前面加上其它运算符,组成复合赋值运算符。下面是C51中支持的复合赋值运算符

 +=    加法赋值             -+    减法赋值

 *=    乘法赋值            /=     除法赋值

 %=    取模赋值           &=    逻辑与赋值

 |=    逻辑或赋值           ^=    逻辑异或赋值

 ~=    逻辑非赋值         >>=    右移位赋值

 <<=    左移位赋值

复合赋值运算的一般格式如下:

变量  复合运算赋值符  表达式

它的处理过程:先把变量与后面的表达式进行某种运算,然后将运算的结果赋给前面的变量。其实这是C51语言中简化程序的一种方法,大多数二目运算都可以用复合赋值运算符简化表示。例如:a+=6相当于a=a+6;a*=5相当于a=a*5;b&=0x55相当于b=b&0x55;x>>=2相当于x=x>>2。

7.  逗号运算符

在C51语言中,逗号“,”是一个特殊的运算符,可以用它将两个或两个以上的表达式连接起来,称为逗号表达式。逗号表达式的一般格式为:

         表达式1,表达式2,……,表达式n

程序执行时对逗号表达式的处理:按从左至右的顺序依次计算出各个表达式的值,而整个逗号表达式的值是最右边的表达式(表达式n)的值。例如:x=(a=3,6*3)结果x的值为18。

8. 条件运算符

条件运算符“?:”是C51语言中唯一的一个三目运算符,它要求有三个运算对象,用它可以将三个表达式连接在一起构成一个条件表达式。条件表达式的一般格式为:

            逻辑表达式?表达式1:表达式2

其功能是先计算逻辑表达式的值,当逻辑表达式的值为真(非0值)时,将计算的表达式1的值作为整个条件表达式的值;当逻辑表达式的值为假(0值)时,将计算的表达式2的值作为整个条件表达式的值。例如:条件表达式max=(a>b)?a:b的执行结果是将a和b中较大的数赋值给变量max。

9.  指针与地址运算符

指针是C51语言中的一个十分重要的概念,在C51中的数据类型中专门有一种指针类型。指针为变量的访问提供了另一种方式,变量的指针就是该变量的地址,还可以定义一个专门指向某个变量的地址的指针变量。

为了表示指针变量和它所指向的变量地址之间的关系,C51中提供了两个专门的运算符:

  *    指针运算符

  &    取地址运算符

指针运算符“*”放在指针变量前面,通过它实现访问以指针变量的内容为地址所指向的存储单元。例如:指针变量p中的地址为2000H,则*p所访问的是地址为2000H的存储单元,x=*p,实现把地址为2000H的存储单元的内容送给变量x。

取地址运算符“&”放在变量的前面,通过它取得变量的地址,变量的地址通常送给指针变量。例如:设变量x的内容为12H,地址为2000H,则&x的值为2000H,如有一指针变量p,则通常用p=&x,实现将x变量的地址送给指针变量p,指针变量p指向变量x,以后可以通过*p访问变量x。
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/wangjiaweiwei/article/details/105254103
  • 7.6. C51基本语句
1.  if语句

if语句是C51中的一个基本条件选择语句,它通常有三种格式:

(1)if (逻辑表达式) {语句;}

(2)if (逻辑表达式) {语句1;}  else  {语句2;}

(3)if (逻辑表达式1) {语句1;}

	else  if (逻辑表达式2) (语句2;)

	else  if (逻辑表达式3) (语句3;)

	……

	else  if (逻辑表达式n-1) (语句n-1;)

	else  {语句n}

【例】  if语句的用法。

(1)if  (x!=y)  printf(“x=%d,y=%d\n”,x,y);

执行上面语句时,如果x不等于y,则输出x的值和y的值。

(2)if  (x>y)  max=x;

else  max=y;

     执行上面语句时,如x大于y成立,则把x送给最大值变量max,如x大于y不成立,则把y送给最大值变量max。使max变量得到x、y中的大数。

(3)if  (score>=90)  printf(“Your result is an A\n”);

else  if  (score>=80)  printf(“Your result is an B\n”);

else  if  (score>=70)  printf(“Your result is an C\n”);

else  if  (score>=60)  printf(“Your result is an D\n”);

else  printf(“Your result is an E\n”);

执行上面语句后,能够根据分数score分别打出A、B、C、D、E五个等级。

2.   switch/case语句

if语句通过嵌套可以实现多分支结构,但结构复杂。switch是C51中提供的专门处理多分支结构的多分支选择语句。它的格式如下:

switch (表达式)

{case  常量表达式1:{语句1;}break;

case  常量表达式2:{语句2;}break;

……

case  常量表达式n:{语句n;}break;

default:{语句n+1;}

说明如下:

(1)switch后面括号内的表达式,可以是整型或字符型表达式。

(2)当该表达式的值与某一“case”后面的常量表达式的值相等时,就执行该“case”后面的语句,然后遇到break语句退出switch语句。若表达式的值与所有case后的常量表达式的值都不相同,则执行default后面的语句,然后退出switch结构。

(3)每一个case常量表达式的值必须不同否则会出现自相矛盾的现象。

(4)case语句和default语句的出现次序对执行过程没有影响。

(5)每个case语句后面可以有“break”,也可以没有。有break语句,执行到break则退出switch结构,若没有,则会顺次执行后面的语句,直到遇到break或结束。

(6)每一个case语句后面可以带一个语句,也可以带多个语句,还可以不带。语句可以用花括号括起,也可以不括。

(7)多个case可以共用一组执行语句。

【例】 switch/case语句的用法。

对学生成绩划分为A~D,对应不同的百分制分数,要求根据不同的等级打印出它的对应百分数。可以通过下面的switch/case语句实现。

……

switch(grade)

{

case  ‘A’;printf(”90~100\n”);break;

case  ‘B’;printf(”80~90\n”);break;

case  ‘C’;printf(”70~80\n”);break;

case  ‘D’;printf(”60~70\n”);break;

case  ‘E’;printf(”<60\n”);break;

default;printf(”error”\n)

}

3.  while语句

while语句在C51中用于实现当型循环结构,它的格式如下:

       while(表达式)

           {语句;}  /*循环体*/

       while语句后面的表达式是能否循环的条件,后面的语句是循环体。当表达式为非0(真)时,就重复执行循环体内的语句;当表达式为0(假),则中止while循环,程序将执行循环结构之外的下一条语句。它的特点是:先判断条件,后执行循环体。在循环体中对条件进行改变,然后再判断条件,如条件成立,则再执行循环体,如条件不成立,则退出循环。如条件第一次就不成立,则循环体一次也不执行。

【例】  下面程序是通过while语句实现计算并输出1~100的累加和。

#include  <reg52.h>   //包含特殊功能寄存器库

#include  <stdio.h>   //包含I/O函数库

void main(void)     //主函数

{

int  i,s=0;       //定义整型变量x和y

i=1;

SCON=0x52;       //串口初始化

TMOD=0x20;

TH1=0XF3;

TR1=1;

while  (i<=100)     //累加1~100之和在s中

{

s=s+i;

i++;

}

printf(“1+2+3……+100=%d\n”,s);

while(1);

}

程序执行的结果:

1+2+3……+100=5050

4.  do  while语句

do  while语句在C51中用于实现直到型循环结构,它的格式如下:

           do

                 {语句;}           /*循环体*/

           while(表达式);

它的特点是:先执行循环体中的语句,后判断表达式。如表达式成立(真),则再执行循环体,然后又判断,直到有表达式不成立(假)时,退出循环,执行do  while结构的下一条语句。do  while语句在执行时,循环体内的语句至少会被执行一次。

【例】 通过do  while语句实现计算并输出1~100的累加和。

#include  <reg52.h>  //包含特殊功能寄存器库

#include  <stdio.h>   //包含I/O函数库

void main(void)       //主函数

{

int  i,s=0;           //定义整型变量x和y

i=1;

SCON=0x52;       //串口初始化

TMOD=0x20;

TH1=0XF3;

TR1=1;

do                  //累加1~100之和在s中

{

s=s+i;

i++;

}

while  (i<=100);

printf(“1+2+3……+100=%d\n”,s);

while(1);

}

5.  for语句

for(表达式1;表达式2;表达式3)

{语句;}  /*循环体*/

for语句后面带三个表达式,它的执行过程如下:

(1)先求解表达式1的值。

(2)求解表达式2的值,如表达式2的值为真,则执行循环休中的语句,然后执行下一步(3)的操作,如表达式2的值为假,则结束for循环,转到最后一步。

(3)若表达式2的值为真,则执行完循环体中的语句后,求解表达式3,然后转到第四步。

(4)转到(2)继续执行。

(5)退出for循环,执行下面的一条语句。

    在for循环中,一般表达式1为初值表达式,用于给循环变量赋初值;表达式2为条件表达式,对循环变量进行判断;表达式3为循环变量更新表达式,用于对循环变量的值进行更新,使循环变量能不满足条件而退出循环。

【例】 用for语句实现计算并输出1~100的累加和。

#include  <reg52.h>    //包含特殊功能寄存器库

#include  <stdio.h>     //包含I/O函数库

void main(void)           //主函数

{

int  i,s=0;                      //定义整型变量x和y

SCON=0x52;                //串口初始化

TMOD=0x20;

TH1=0XF3;

TR1=1;

for (i=1;i<=100;i++)  s=s+i;     //累加1~100之和在s中

printf(“1+2+3……+100=%d\n”,s);

while(1);

}

6.  循环的嵌套

在一个循环的循环体中允许又包含一个完整的循环结构,这种结构称为循环的嵌套。外面的循环称为外循环,里面的循环称为内循环,如果在内循环的循环体内又包含循环结构,就构成了多重循环。在C51中,允许三种循环结构相互嵌套。

【例】用嵌套结构构造一个延时程序。

void  delay(unsigned  int  x)

{

unsigned  char j;

while(x--)

{for (j=0;j<125;j++);}

}

这里,用内循环构造一个基准的延时,调用时通过参数设置外循环的次数,这样就可以形成各种延时关系。

7.  break和continue语句

break和continue语句通常用于循环结构中,用来跳出循环结构。但是二者又有所不同,下面分别介绍。

1).break语句

前面已介绍过用break语句可以跳出switch结构,使程序继续执行switch结构后面的一个语句。使用break语句还可以从循环体中跳出循环,提前结束循环而接着执行循环结构下面的语句。它不能用在除了循环语句和switch语句之外的任何其它语句中。

【例19】下面一段程序用于计算圆的面积,当计算到面积大于100时,由break语句跳出循环。

for (r=1;r<=10;r++)

{

area=pi*r*r;

if (area>100) break;

printf(“%f\n”,area);

}

2).continue语句

continue语句用在循环结构中,用于结束本次循环,跳过循环体中continue下面尚未执行的语句,直接进行下一次是否执行循环的判定。

continue语句和break语句的区别在于:continue语句只是结束本次循环而不是终止整个循环;break语句则是结束循环,不再进行条件判断。

【例20】  输出100~200间不能被3整除的数。

for (i=100;i<=200;i++)

{

if  (i%3= =0)  continue;

printf(“%d  ”;i);

}

在程序中,当i能被3整除时,执行continue语句,结束本次循环,跳过printf()函数,只有能被3整除时才执行printf()函数。

8.  return语句

return语句一般放在函数的最后位置,用于终止函数的执行,并控制程序返回调用该函数时所处的位置。返回时还可以通过return语句带回返回值。return语句格式有两种:

(1)return;

(2)return (表达式);

如果return语句后面带有表达式,则要计算表达式的值,并将表达式的值作为函数的返回值。若不带表达式,则函数返回时将返回一个不确定的值。通常我们用return语句把调用函数取得的值返回给主调用函数。
————————————————

 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
 
原文链接:https://blog.csdn.net/wangjiaweiwei/article/details/105311367

8. 独立按键控制LED状态,每按一次按键LED灯状态取反

  • 8.1. 按键的抖动问题(程序消抖)
    在这里插入图片描述

在没有增加按键消抖程序的时候,程序如下,开发板的现象是:按下K1按钮,有的时候LED灯的状态会变化,有的时候按下两三下才发生变化,灯变化的状态不稳定;

#include <REGX52.H> //没有加入按键消抖的程序
void main()
{
		P2_0=1;
		while(1)
	{
		if (P3_1==0)
		{
			P2_0=!P2_0;
		}
		
	}
}
  • 8.2. 程序消抖的原理,当按键按下后延时10ms左右再对按键的状态进行判断;
    对于机械开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动
    在这里插入图片描述

  • 8.3.加入消抖程序的程序如下,需要加入延时函数进行延时控制,同时函数在主函数前面进行声明,同时延时函数写在主函数末尾;

#include <REGX52.H> //加入按键消抖的程序
void delayxms(unsigned int xms);
void main()
{
		P2_0=1;
		while(1)
	{
		if (P3_1==0)
		{
			delayxms(20);
			while(P3_1==0);//如果while判断执行空语句,则可以省略大括号,便于编程
			delayxms(20);
			P2_0=~P2_0;
		}
		
	}
}

void delayxms(unsigned int xms)
{
	unsigned char i,j;
	while (xms)
	{
		i=2;
		j=239;
		do
		{
			while (--j);
		}
		while (--i);
		--xms;	
	}
}

9. 独立按键控制LED显示二进制

  • 9.1. 如果程序如下,则会出现无论怎么按按键,LED始终是不亮的,具体原因见程序中的注释:
#include <REGX52.H> 
void delayxms(unsigned int xms);
void main()
{
		P2=0xff;//P2赋予初始值1111 1111
		unsigned char LED_Num;
		while(1)
	{
		if (P3_1==0)
		{
			delayxms(20);
			while(P3_1==0);
			delayxms(20);
			P2++;//P2加1后赋值给P2,因为数值溢出,P2此时值为0;
			P2=~P2;//P2取反后再赋予P2,则此时P2口的值又变为0xff,LED灯灭;不断循                    //环,据此分析如果开始的时候P2=0x00;初始值为0的情况,则P2口
				   //是只有LED1不断的亮灭,其他LED灯灭;
		}			
	}
}

void delayxms(unsigned int xms)
{
	unsigned char i,j;
	while (xms)
	{
		i=2;
		j=239;
		do
		{
			while (--j);
		}
		while (--i);
		--xms;	
	}
}
  • 9.2. 正确的程序应该使用一个中间变量作为中转,让中转变量先进行累加和取反运算,然后将中转变量赋值给P2;
#include <REGX52.H> 
void delayxms(unsigned int xms);
void main()
{
		unsigned char LED_Num;//初始值为0;
		while(1)
	{
		if (P3_1==0)
		{
			delayxms(20);
			while(P3_1==0);
			delayxms(20);
			LED_Num++;//LED_Num此时为1;
			P2=~LED_Num;//取反后LED_Num为0xfe赋予P2;
		}			
	}
}

void delayxms(unsigned int xms)
{
	unsigned char i,j;
	while (xms)
	{
		i=2;
		j=239;
		do
		{
			while (--j);
		}
		while (--i);
		--xms;	
	}
}

Proteus中测试没有问题,程序通过;

在这里插入图片描述

10. 独立按键控制LED移位

  • 10.1. 如果定义全局变量,可以不对全局变量进行赋值,默认为0,如果定义局部变量,需要对局部变量赋予初始值,有可能不是0,独立按键控制LED灯左右移动程序先分解为一个独立按键控制LED灯左移,然后再加上另一个独立按键控制LED灯右移两个程序;
#include <REGX52.H> //独立按键控制LED灯左移程序;
void delayxms(unsigned int xms);
void main()
{
		unsigned char LED_Num=0;//局部变量LED_Num赋值0;
		P2=0xfe;//P2端口初始最低为LED灯亮起;
		while(1)
	{
		if (P3_1==0)
		{
			delayxms(20);
			while(P3_1==0);
			delayxms(20);//按键按下并消抖;
			LED_Num++;
			if(LED_Num>=8)//判断LED灯移动到最高位的情况,写为LED_Num==8也可以;
			{
				LED_Num=0;//LED_Num=重新归零计数;
			}
			P2=~(0x01<<LED_Num);//LED_Num=0, P2=0000 0001B
								//LED_Num=1, P2=0000 0010B
								//LED_Num=2, P2=0000 0100B
								//LED_Num=3, P2=0000 1000B
								//LED_Num=4, P2=0001 0000B
								//LED_Num=5, P2=0010 0000B
								//LED_Num=6, P2=0100 0000B
								//LED_Num=7, P2=1000 0000B
		}                        //LED灯需要什么位亮就移动几位;
		
	}
}

void delayxms(unsigned int xms)
{
	unsigned char i,j;
	while (xms)
	{
		i=2;
		j=239;
		do
		{
			while (--j);
		}
		while (--i);
		--xms;	
	}
}
  • 10.2. 加上右移程序后的完整程序
#include <REGX52.H> 
void delayxms(unsigned int xms);
void main()
{
		unsigned char LED_Num=0;
		P2=0xfe;
		while(1)
	{
		if (P3_1==0)
		{
			delayxms(20);
			while(P3_1==0);
			delayxms(20);
			LED_Num++;			
			if(LED_Num>=8)
			{
				LED_Num=0;
			}
			P2=~(0x01<<LED_Num);
		}
		if (P3_0==0)
		{
			delayxms(20);
			while(P3_0==0);
			delayxms(20);
		
			if(LED_Num==0)//由于LED_Num定义为无符号字节,不能有小于1的数出现,
						  //所以用LED_Num==0来判断已经到了最低位;
			{
				LED_Num=8;//配合下面LED_Num--,先减掉1再赋值的时候LED_Num=7;
			}             //此时配合0x01<<LED_Num:1000 0000B,取反后最高位 
			LED_Num--;	  //LED灯亮起;
			P2=~(0x01<<LED_Num);
		}			
	}
}

void delayxms(unsigned int xms)
{
	unsigned char i,j;
	while (xms)
	{
		i=2;
		j=239;
		do
		{
			while (--j);
		}
		while (--i);
		--xms;	
	}
}
  • 24
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值