一、实例目的
- 熟悉Protues电路原理图绘制
- 熟悉Keil程序编写编译方法
- 熟悉Keil C51 延时程序的用法
- 熟悉Keil C51 位移的方法
- 熟悉单片机引脚的控制方法
二、程序示例图
三、绘制原理图
略,本节可以继续使用上节用的原理图,具体参考:
Proteus + Keil单片机仿真教程(二)炫彩灯_爱折腾的博客-CSDN博客
四、程序代码:
-
传统方式
这里可以继续沿用上节的方法,每个LED发光二极管点亮并熄灭,间隔为100ms,代码如下:
//添加头文件,C51必要文件,主要定义的是51/52系列单片机
#include "reg52.h"
//引用延时函数
void Delay1MS(unsigned int t);
//定义引脚,这里定义P0引脚
sbit P00 = P0^0;
sbit P01 = P0^1;
sbit P02 = P0^2;
sbit P03 = P0^3;
sbit P04 = P0^4;
sbit P05 = P0^5;
sbit P06 = P0^6;
sbit P07 = P0^7;
int main(void){
//进入循环
while(1){
//点亮并熄灭P00,P00点亮0.5s
P00 = 0;
Delay1MS(500);
P00 = 1;
Delay1MS(100);
//点亮并熄灭P01
P01 = 0;
Delay1MS(100);
P01 = 1;
Delay1MS(100);
//点亮并熄灭P02
P02 = 0;
Delay1MS(100);
P02 = 1;
Delay1MS(100);
//点亮并熄灭P03
P03 = 0;
Delay1MS(100);
P03 = 1;
Delay1MS(100);
//点亮并熄灭P04
P04 = 0;
Delay1MS(100);
P04 = 1;
Delay1MS(100);
//点亮并熄灭P05
P05 = 0;
Delay1MS(100);
P05 = 1;
Delay1MS(100);
//点亮并熄灭P06
P06 = 0;
Delay1MS(100);
P06 = 1;
Delay1MS(100);
//点亮并熄灭P07
P07 = 0;
Delay1MS(100);
P07 = 1;
Delay1MS(100);
//所有LED点亮并熄灭
P00 = 0;
P01 = 0;
P02 = 0;
P03 = 0;
P04 = 0;
P05 = 0;
P06 = 0;
P07 = 0;
Delay1MS(500);
P00 = 1;
P01 = 1;
P02 = 1;
P03 = 1;
P04 = 1;
P05 = 1;
P06 = 1;
P07 = 1;
Delay1MS(500);
}
}
//1m延时程序
void Delay1MS(unsigned int t){
unsigned char i;
while(--t != 0){
for(i = 0; i < 125; i++);
}
}
效果如下:
到此,这个程序就结束了,如果需要单片机引脚进行批量且复杂控制的时候,这种程序方法显然是不合适的,这里我们可以使用位移的方式进行控制。
2.位移方式
位移是源自二进制的位移,8051单片机的P0~P3每个接口都对应着八个引脚,就是八位的二进制,将上面的程序转换一下就是:
0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0x7F |
1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0xBF |
1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 0xDF |
1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0xEF |
1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 0xF7 |
1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0xFB |
1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0xFD |
1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0xFE |
LED发光二极管点亮顺序就是每次都是位移一个位,那么在程序里面就可以使用位移方式进行控制,在这里可以调用“intrains.h”函数快速实现这个功能,关于“intrins.h”的具体说明如下所示:
intrins.h函数说明:应用于程序设计,一般出C51单片机编程中,一般程序中需要使用到空指令_nop_();字符循环移位指令_crol_等时使用,内部函数:
_crol_ 字符循环左移
_cror_ 字符循环右移
_irol_ 整数循环左移
_iror_ 整数循环右移
_lrol_ 长整数循环左移
_lror_ 长整数循环右移
_nop_ 空操作 (相当于8051 NOP 指令)
_testbit_ 测试并清零位 (相当于8051 JBC 指令)
函数名: _crol_,_irol_,_lrol_
举例:
_crol_,_cror_:将char型变量循环向左(右)移动指定位数后返回
_testbit_: 相当于JBC bitvar测试该位变量并跳转同时清除。
_chkfloat_: 测试并返回源点数状态。
就是汇编中的子函数。
_crol_,_cror_:如果二进制数为01010101 那么_crol_(1) 左移1位后将高位补低位。
结果10101010。
功 能:_crol_,_irol_,_lrol_以位形式将val 左移n 位,该函数与8051“RLA”指令相关,上面几个函数不同于参数类型。
例:
#include <intrins.h>
main()
{
unsigned int y;
y=0x00ff;
y=_irol_(y,4);
}
参照上面的方法,重新编写代码如下所示:
//添加头文件,C51必要文件,主要定义的是51/52系列单片机
#include "reg52.h"
#include "intrins.h"
//引用延时函数
void Delay1MS(unsigned int t);
unsigned char tmp,i;
int main(void){
//进入循环
while(1){
//点亮并熄灭P00,P00点亮0.5s
tmp = 0xfe; //对应的二进制为0111 1111
Delay1MS(500);
for(i=0;i<8;i++){
P0 = tmp;
tmp = _crol_(tmp,1);//每隔0.2s向左位移一位
Delay1MS(200);
}
//所有LED发光二极管闪烁两次
P0 = 0xFF;
Delay1MS(200);
P0 = 0x00;
Delay1MS(200);
P0 = 0xFF;
Delay1MS(200);
P0 = 0x00;
Delay1MS(200);
}
}
//1m延时程序
void Delay1MS(unsigned int t){
unsigned char i;
while(--t != 0){
for(i = 0; i < 125; i++);
}
}
效果如下所示:
思考:通过本节的内容优化上一节“炫彩灯”程序。