51单片机学习笔记2 -- 单灯控制及流水灯

Posted GenCoder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51单片机学习笔记2 -- 单灯控制及流水灯相关的知识,希望对你有一定的参考价值。

学习了最小系统电路后,从最基本的LED控制开始入手,也就是输出控制


LED控制和流水灯

1.LED仿真电路绘制

LED就不展开介绍了,二极管单向导通电能转换光能,直接上原理图,可以看到LED灯D1连接在51单片机P1.0引脚

在Protues元器件查找输入关键词LED,在详细列表下拉找到几个颜色的LED,分别是蓝、绿、红、黄,随便找一个颜色的LED即可

单个LED的接线按照原理图如下进行仿真电路绘制,注意LED的朝向(LED阳极接限流电阻R2,阴极接芯片引脚P1.0)

2.Keil 51工程创建

打开Keil软件,先关掉当前打开的工程,菜单栏 Project -> Close Project

新建一个文件夹以存放工程文件,Keil新建工程

选择新建的文件夹存放工程,并给工程命名

选择工程对应的处理芯片,找到Atmel的AT89C52,除了和STC89C52复位电平不同外,其他基本一样

拷贝51单片机相关启动文件,是

创建好的工程列表如下

新建文件并命名为main.c保存在工程路径下

右键工程目录,添加main.c到工程目录中(添加方式可双击main.c直接添加或选中main.c点add添加)

3.LED单灯编程

在main.c添加51单片机头文件 reg52.h ,编写延时函数,延时函数参数为1时刚好延时1ms,先写好框架代码,如下

#include <reg52.h>

void delay_ms(unsigned int nms)

	 unsigned int i,j;

	 for(i=nms;i>0;i--)
	 	for(j=113;j>0;j--);


void main()

	while(1);

进行工程编译检查代码是否有误,只要error不出现错误,工程就没问题,这里出现一个警告是因为定义了延时函数没有被调用

sbit 位寄存器定义LED引脚变量名,在main函数中对LED赋值高低电平进行点亮LED和关闭LED的操作

#include <reg52.h>

sbit LED1 = P1^0;

void delay_ms(unsigned int nms)

	 unsigned int i,j;

	 for(i=nms;i>0;i--)
	 	for(j=113;j>0;j--);


void main()

	LED1 = 0;
	delay_ms(500);
	LED1 = 1;
	delay_ms(500);
	
	while(1);

勾选工程编译输出hex文件,不管是仿真电路运行,还是将程序下载到开发板上,都需要hex文件,勾选后重新编译一次工程,会发现工程文件夹多了个hex文件

4.LED单灯仿真

回到LED仿真电路,双击51芯片,选择工程生成的hex文件(除了hex文件其他文件不识别),ok

开启电路仿真,可以发现LED点亮一会儿就灭了(如果把仿真电路LED的限流电阻改小,LED亮起的时候亮度会更亮,仿真电路可以将电阻改小以加强视觉效果,但现实电路不建议这么做,还是需要串联1个1k左右的电阻做限流)

5.LED流水灯编写

流水灯需要把开发板上的8个LED灯都用上,按原理图进行仿真电路连接,原理图上面有,仿真电路画完是这样的,4个颜色的LED都用上了,是不是觉得有点花里胡哨呢,其实我也这么觉得哈哈哈哈哈哈哈哈哈

1.位输出操作

最偷懒式的流水灯程序编写,其实也就是将单灯点亮代码copy成8个灯,一直在while(1)里面循环(8个灯都需要单独定义位寄存器变量名),如下

#include <reg52.h>

sbit LED1 = P1^0;
sbit LED2 = P1^1;
sbit LED3 = P1^2;
sbit LED4 = P1^3;
sbit LED5 = P1^4;
sbit LED6 = P1^5;
sbit LED7 = P1^6;
sbit LED8 = P1^7;

void delay_ms(unsigned int nms)

	 unsigned int i,j;

	 for(i=nms;i>0;i--)
	 	for(j=113;j>0;j--);


void main()
	
	while(1)
	
		LED1 = 0;
		delay_ms(200);
		LED1 = 1;
		
		LED2 = 0;
		delay_ms(200);
		LED2 = 1;

		LED3 = 0;
		delay_ms(200);
		LED3 = 1;

		LED4 = 0;
		delay_ms(200);
		LED4 = 1;

		LED5 = 0;
		delay_ms(200);
		LED5 = 1;

		LED6 = 0;
		delay_ms(200);
		LED6 = 1;

		LED7 = 0;
		delay_ms(200);
		LED7 = 1;

		LED8 = 0;
		delay_ms(200);
		LED8 = 1;
	

仿真现象如下

2.移位方式

移位方式为流水灯代码编写的另一种方式,比第一种方式要简便点,参考代码如下,主要是针对P1端口进行16进制赋值,每次左移后将补位置1让流水灯同时只亮一个灯

#include<reg52.h>

void delay(unsigned int xms); //延迟函数的声明 

void main()

    unsigned char i;		//0-255
    while(1)
	
	    P1=0xfe;			//1111 1110
	    for(i=0;i<8;i++)
		
		    delay(200);
			P1<<=1;			//P1=P1<<1	 
			P1=P1|0X01;		//0000 0001 
		
	


void delay(unsigned int xms)		 //延迟函数		

	unsigned int i,j;
	for(i=xms;i>0;i--)		         //i=xms即延时约xms毫秒
		for(j=113;j>0;j--);

3.循环移位

在51的函数库中,还有这么一个函数,能令一个16进制数一直旋转左移,如果让这个一直旋转左移的16进制数赋值给P1端口,那么也能让LED灯带产生流水灯效果,先来看看代码是怎么写的

#include<reg52.h>
#include<intrins.h>
#include"delay.h"

void main()

    P1=0Xfe;				 //1111 1110
    while(1)
	
	    delay(200);
		P1=_crol_(P1,1);     //循环移位函数 把P1寄存器内的数向左移1位
	

是不是觉得代码量少了很多,其实只是因为调用了_crol_函数,函数手册中对这个函数的介绍是这样的

_crol_

Summary    #include <intrins.h>

                   unsigned char _crol_ (
                       unsigned char c,        /* character to rotate left */
                       unsigned char b);       /* bit positions to rotate */

 
Description        The _crol_ routine rotates the bit pattern for the character c left b bits. This routine is implemented as an intrinsic function.  
Return Value      The _crol_ routine returns the rotated value of c.  
See Also             _cror_, _irol_, _iror_, _lrol_, _lror_ 
 

并给出了函数使用demo

//Example   
#include <intrins.h>

void test_crol (void) 
      char a;
      char b;

      a = 0xA5;
      b = _crol_(a,3); /* b now is 0x2D */

unsigned char crol ( unsigned char c, unsigned char b)
头文件:
intrins.h
参数:
参数1 - 要向左旋转的字符
参数2 - 要旋转的位数(2进制位)
返回值:
向左旋转b(参数2)位后的c(参数1)值

_crol_ 函数对于流水灯而言,将参数1的16进制数左移参数2位,1次左移多少位就将左移出去的位都拼在原16进制数的低位,形成新的16进制数
如果参数2的值为1,也就将参数1的16进制数每调用1次就旋转左移1位,当参数1的初值恰好是0xfe时,在每次调用 _crol_ 函数时加个延时,就直接是流水灯效果了,不明白的小伙伴可以动手操作一遍加深理解,参数2也可以改成2或3或其他数,每次左移2位或3位或**位


哦对了,_crol_ 函数其实也可以做成流水灯旋转右移的效果,可以稍微动动脑筋想想怎么实现的 ~

以上是关于51单片机学习笔记2 -- 单灯控制及流水灯的主要内容,如果未能解决你的问题,请参考以下文章

51单片机学习笔记5 流水灯实现及蜂鸣器控制

51单片机学习笔记5 流水灯实现及蜂鸣器控制

51单片机自定义串口通讯协议控制流水灯+Proteus仿真

流水灯实训报告

51单片机学习笔记3 -- 按键输入检测

51单片机学习笔记3 -- 按键输入检测