51单片机学习笔记2 -- 单灯控制及流水灯
Posted GenCoder
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51单片机学习笔记2 -- 单灯控制及流水灯相关的知识,希望对你有一定的参考价值。
学习了最小系统电路后,从最基本的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 -- 单灯控制及流水灯的主要内容,如果未能解决你的问题,请参考以下文章