当前位置:首页 » 《我的小黑屋》 » 正文

51单片机编程应用(C语言):LED灯

2 人参与  2024年10月10日 10:01  分类 : 《我的小黑屋》  评论

点击全文阅读


目录

1.点亮一个LED灯

 2.LED灯闪烁

3.LED流水灯

3.1.最基础最原始的流水灯实现办法

3.2 移位法实现LED流水灯 

左循环:

右循环 :

3.3 数组法 :

3.4 库函数法 :

1.define和sbit的区别


1.点亮一个LED灯

 在keil中创建工程

遇到这个窗口是提示我们“是否把启动代码添加到工程中”,我们选择是。 

右击source Group 1 

选择c file,学C++的用C++,第三个汇编语言,第四个汇编与C合在一起的。 

代码输入代码, 

#include <reg52.h>sbit led0 = P2^0;sbit led1 = P2^1;sbit led2 = P2^2;sbit led3 = P1^7;sbit led4 = P3^1;void main(){while(1){led0 = 0;led1= 0;led2= 0;led3= 0;led4= 0;}}

编译:

看有无错误:0 Error说明程序是正确的

点击:(与上面步骤交换,先打√再编译)

勾选上如下东西

打开proteus,双击芯片,在Program file打开自己保存项目的文件夹,找到上一步生成的HEX文件

  

proteus我就不介绍了,左下角的一排控制按钮意思分别是运行 单步 暂停 结束,我们点击运行就可以看到led灯被点亮

现象:

有单片机就在自己单片机烧录看看现象,不过要注意LED模块接的是51单片机的哪个I/O口,比如

所以只能用P2口,不能像上面的代码一样去用其他口子,否则会报错。 

 2.LED灯闪烁

我们要闪烁的话是不是要给个延迟,所以我们要写一个延迟函数

#include <reg52.h> //定义单片机的一些特殊功能寄存器sbit led=P2^0;//定义指定LED灯的管脚 void delay(unsigned int i)//延时函数。unsigned int定义无符号整型,范围0-655535{while(i--);//i=1时,大约延时10us} void main()       //主函数,程序从这里开始执行{while(1){led=0;        //0表示低电平,共阳极二极管点亮delay(50000); //大约延时450msled=1;        //1表示高电平,LED熄灭delay(50000); //大约延时450ms}}
#include<reg52.h>和#include"reg52.h"区别两者来说区别不大,< >的引用是C51库函数里面的文件,而" "是引用我们自己创建的库函数里面的文件

在单片机中有两种延时方式,一种是软件延时,一种是硬件延时(计时器/计数器)。本知识点主要介绍软件延时函数。

我们发现其中多了_nop_()指令,该指令包含在头文件#include<intrins.h>中,所以我们需要专门调用一个文件#include <intrins.h>。_nop_()的作用是产生下一条指令,对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数的作用是使程序执行完成后延时几微秒。nop指令为单周期指令,可由晶振频率算出延时时间,对于12M晶振,延时1us。

最后代码如下:

​#include <REGX51.H>#include <intrins.h>sbit LED=P2^0;void Delay500ms()//@11.0592MHz{unsigned char i, j, k;_nop_();i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);}int main(){while(1){LED=1;Delay500ms();LED=0;Delay500ms();}}​

3.LED流水灯

3.1.最基础最原始的流水灯实现办法

8个LED灯的定义,让某一个灯点亮就是让这个LED灯为低电平。从左到右依次为01111111、10111111、11011111、11101111、11110111、11111011、11111101、11111110。其中1就是高电平、0位低电平,为低电平时LED点亮。

#include <reg52.h> sbit led1=P2^0;sbit led2=P2^1;sbit led3=P2^2;sbit led4=P2^3;sbit led5=P2^4;sbit led6=P2^5;sbit led7=P2^6;sbit led8=P2^7; void delay(unsigned int i){while(i--);//执行一次大约10us} void main()      {while(1){led1=0;       delay(5000); //5000*10us=50ms左右led1=1;       delay(5000); led2=0;       delay(5000); led2=1;        delay(5000); led3=0;       delay(5000); led3=1;        delay(5000); led4=0;        delay(5000); led4=1;        delay(5000); led5=0;        delay(5000); led5=1;        delay(5000);led6=0;        delay(5000); led6=1;        delay(5000); led7=0;       delay(5000); led7=1;        delay(5000); led8=0;        delay(5000); led8=1;        delay(5000); }}

 上面讲到了软件专门提供了delay函数,下面是1s的闪烁的代码,记住,8051指令集选STY_Y1

下面代码是多了,是因为我把P2口八个端口分开了,但是P2口可以整体赋值的,用16进制表示。

代码就会大大缩短,自己可以写一下。

#include <reg52.h>#include <intrins.h>sbit led1=P2^0;sbit led2=P2^1;sbit led3=P2^2;sbit led4=P2^3;sbit led5=P2^4;sbit led6=P2^5;sbit led7=P2^6;sbit led8=P2^7;void Delay500ms()//@11.0592MHz{unsigned char i, j, k;_nop_();i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);}void main()      {while(1){led1=0;       Delay500ms();//亮灭500ms合起来一秒。led1=1;       Delay500ms();led2=0;       Delay500ms(); led2=1;        Delay500ms(); led3=0;       Delay500ms(); led3=1;        Delay500ms(); led4=0;        Delay500ms(); led4=1;        Delay500ms(); led5=0;        Delay500ms(); led5=1;        Delay500ms();led6=0;        Delay500ms(); led6=1;        Delay500ms(); led7=0;       Delay500ms(); led7=1;        Delay500ms(); led8=0;        Delay500ms(); led8=1;        Delay500ms(); }}

3.2 移位法实现LED流水灯 

左循环:
#include <reg51.h>#include <intrins.h>void Delay500ms()//@11.0592MHz{unsigned char i, j, k;_nop_();i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);}void main(void)    {     int j;        while(1)    {        P2=0xfe;   //11111110,         Delay500ms();   for(j=0;j<8;j++)           {            P2=P2<<1 | 0x01; //左移一位,变成1111 1100,与0000 0001或运算,得到1111 1101,                             //1111 1101左移一位 得到1111 1010,或运算后1111 1011            Delay500ms();         }     } }

或运算应用场合, 某位置置1,其余为不变,左移时最后一位总产生0,所以或运算,使最后一位变1.

但是我们总是用软件生成延时函数是不是很不方便,每次还要让我们自己选择多少秒,生成后复制粘贴,很繁琐,能不能我们想延迟多少毫秒就是多少毫秒,而不是去软件重新生成一个新代码。所以我们写一个delay函数,

用软件先生成一个1ms的函数,

void Delay1ms(unsigned int xms)//@12.000MHz{unsigned char i, j;  while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;  }}

这样的话我每次想改成多少毫秒就直接改x的数值就OK了,比如,我不想500ms,用100ms 就可以如下程序:

#include <reg51.h>void Delay1ms(unsigned int xms)//@12.000MHz{unsigned char i, j;  while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;  }}void main(void)    {     int j;        while(1)    {        P2=0xfe;   //11111110,        Delay1ms(100);   for(j=0;j<8;j++)           {            P2=P2<<1 | 0x01;             Delay1ms(100);         }     }}
右循环 :
#include <reg51.h>void Delay1ms(unsigned int xms)//@12.000MHz{unsigned char i, j;  while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;  }}void main(void)   {     int j;        while(1)    {        P2=0x7f;   //0111 1111        Delay1ms(500);      for(j=0;j<8;j++)           {                P2=P2>>1 | 0x80; //右移一位0011 1111,或1000 0000 变成1011 1111            Delay1ms(500);         }     } }

右移第一位总是0,或上1000 0000 让第一位变成1.

3.3 数组法 :

#include <reg51.h> unsigned char LED [8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //??8?LED??? void Delay1ms(unsigned int xms)//@12.000MHz{unsigned char i, j;  while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;  }} void main(void)   {     int j;     for(j=0; j<8; j++)  {P2 = LED[j];   Delay1ms(500);P2 = 0xff;  Delay1ms(500); }    }

3.4 库函数法 :

移位函数(最快实现流水灯程序)

需要添加#include<intrins.h>库函数,其中_crol_表示左移(字符循环左移),_cror_表示右移(字符循环右移)。具体应用中_crol_(LED,1)表示把LED左移1位(例如:11111110执行完后为11111101),_cror_(LED,2)表示右移2位等(例如:10111111执行完后为11101111)。

_crol_循环左移

<<仅左移,后面补0;

比如

P1=0xfe;

P1=_crol_(P1,1) ; // 1111 1110、1111 1101、1111 1011,如同一条圆形纸带一样循环P1<<=1 ; // 1111 1110、 1111 1100、1111 1000 注意后面补0

代码如下

#include <reg51.h>#include <intrins.h> #define LED P2   //把P2口整体定义为LED,后面可以直接引用 void Delay1ms(unsigned int xms)//@12.000MHz{unsigned char i, j;  while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;  }} void main()   //主函数,程序从这里开始执行{int i;LED = 0xfe;for(i=0;i<7;i++) //LED左移一位{LED=_crol_(LED,1);Delay1ms(100); }for(i=0;i<7;i++)//LED右移一位{LED=_cror_(LED,1);Delay1ms(100); }   }

#define LED P2  此句话意思为将P2口整体定义为LED,增加了程序的可读性。

1.define和sbit的区别

#define 就是通常说的宏定义,它可以将一个资源命名。

第一:将IO口换一个名字,如:#define LED P2 意思就是将P2口重新命名为LED;
第二:宏定义,将一个语句集合命名,例如:#define goto {ML1=1;ML2=0;MR1=1;MR2=0}

sbit特殊功能寄存器的一个位的声明,如:sbit LED0=P2^0;

#define是宏定义,是一个预编译指令。
如#define PI 3.14 在预编译阶段,会将PI替换为3.14

sbit是C51扩展的变量类型,一个在编译期替换,一个在运行期生效

首先,sbit led= P2,这个写法是错误的,虽然编译时不报错,但编译后执行程序时却是错误的。
sbit 是定义一个引脚的,注意,只是定义一个引脚,而 P2是一个并行口,有8个引脚,是不能sbit 来定义,可以用 sfr 定义。
#define 并不是定义引脚的,也不是定义并行口,只是一个宏替换,就是程序中的led 换成P2后再编译。

首先,sbit led= P2,这个写法是错误的,虽然编译时不报错,但编译后执行程序时却是错误的。
sbit 是定义一个引脚的,注意,只是定义一个引脚,而 P2是一个并行口,有8个引脚,是不能sbit 来定义,可以用 sfr 定义。
#define 并不是定义引脚的,也不是定义并行口,只是一个宏替换,就是程序中的led 换成P2后再编译。
 


点击全文阅读


本文链接:http://zhangshiyu.com/post/169869.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1