学习了最小系统电路后,从最基本的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;
while(1)
{
P1=0xfe;
for(i=0;i<8;i++)
{
delay(200);
P1<<=1;
P1=P1|0X01;
}
}
}
void delay(unsigned int xms)
{
unsigned int i,j;
for(i=xms;i>0;i--)
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;
while(1)
{
delay(200);
P1=_crol_(P1,1);
}
}
是不是觉得代码量少了很多,其实只是因为调用了_crol_ 函数,函数手册中对这个函数的介绍是这样的
_crol_
Summary #include <intrins.h>
unsigned char _crol_ (
unsigned char c,
unsigned char b);
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
#include <intrins.h>
void test_crol (void) {
char a;
char b;
a = 0xA5;
b = _crol_(a,3);
}
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_ 函数其实也可以做成流水灯旋转右移的效果,可以稍微动动脑筋想想怎么实现的 ~
|