目录
一、Proteus部分
1、保存项目
(一)【文件】保存设计
(二)某盘Proteus(双击)
空白处右键
新建文件夹
重命名“项目”
(三)双击项目文件名输入“1.流水灯”
保存
(四)点击元件模式(左侧黄色运放按钮)点击“P”
(五)输入关键字选中器件
确定
流水灯所需器件列表
关键字 | 元件名称 | 型号 | 数量(个) |
---|---|---|---|
AT89C51 | 单片机 | AT89C51 | 1 |
CRYSTAL | 晶体振荡器 | 12MHZ | 1 |
LED-RED | 发光二极管 | 红色 | 8 |
CAP | 电容 | 22pF | 2 |
CAP-ELEC | 电解电容 | 10uF | 1 |
RES | 电阻 | 1kΩ | 9 |
RES | 电阻 | 10kΩ | 1 |
BUTTON | 复位按键 | 1 |
(六)放置元器件
先单击元件的关键字在原理图编辑窗口的合适位置再次单击即可
双击元器件的值即可修改
放置VCC
电路原理图如图所示
2、烧录程序
双击单片机点击Program File后面的文件夹标志
上传.hex文件
确定
若仿真时出现Cannot open 'C:\User\XXX\AppDate\Local\Temp\LISA4823.SDF'
步骤:右键“此电脑”-->属性-->高级系统配置-->环境变量-->将“用户变量”和“系统变量”中TEMP与TMP的变量值改为%SystemRoot%\TEMP。
二、keil部分
1、创建项目
(一)新建一个文件夹保存项目
(二)双击"keil"“项目”
“新uVision项目”
(三)将文件命名为项目名
(四)选择单片机型号
(五)单击“是(Y)”
(六)新建Text
(七)保存
(八)命名“.c”文件
(九)双击“Source Group 1”
(十)添加“.c”文件
(十一)生成.hex文件
点击“输出”勾选“创建HEX文件”
(十二)编译
编译无错误如下图所示
2、参考程序 (共阳极接法)
(一)位操法
缺点:代码冗长
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit L1=P1^0;//将P1^0赋值给变量L1
sbit L2=P1^1;
sbit L3=P1^2;
sbit L4=P1^3;
sbit L5=P1^4;
sbit L6=P1^5;
sbit L7=P1^6;
sbit L8=P1^7;
void delay(uint n)//延时函数(n)ms
{
uchar i;
uint j;
for(j=0;j<n;j++)
for(i=0;i<123;i++);
}
void flash1()//LED1亮0.5s后熄灭
{
L1=0;//LED1亮
delay(500);
L1=1;//LED1灭
}
void flash2()
{
L2=0;
delay(500);
L2=1;
}
void flash3()
{
L3=0;
delay(500);
L3=1;
}
void flash4()
{
L4=0;
delay(500);
L4=1;
}
void flash5()
{
L5=0;
delay(500);
L5=1;
}
void flash6()
{
L6=0;
delay(500);
L6=1;
}
void flash7()
{
L7=0;
delay(500);
L7=1;
}
void flash8()
{
L8=0;
delay(500);
L8=1;
}
void main (void)
{
while(1)
{
flash1();
flash2();
flash3();
flash4();
flash5();
flash6();
flash7();
flash8();
flash8();
flash7();
flash6();
flash5();
flash4();
flash3();
flash2();
flash1();
}
}
(二)数组总线法
二进制对应表
⑧ | ⑦ | ⑥ | ⑤ | ④ | ③ | ② | ① |
P1^7 | P1^6 | P1^5 | P1^4 | P1^3 | P1^2 | P1^1 | P1^0 |
想让对应引脚的LED亮,只需将二进制数对应位置取0即可。
数组取值
现象 | 二进制表示 | 十六进制表示 |
LED1亮 | 1111 1110 | 0xfe |
LED2亮 | 1111 1101 | 0xfd |
LED3亮 | 1111 1011 | 0xfb |
LED4亮 | 1111 0111 | 0xf7 |
LED5亮 | 1110 1111 | 0xef |
LED6亮 | 1101 1111 | 0xdf |
LED7亮 | 1011 1111 | 0xbf |
LED8亮 | 0111 1111 | 0x7f |
优点:代码简短
缺点:点亮数据编写比较麻烦,且容易出错
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar tab[ ]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//前8个数据为左移点亮数据,后8个数据为右移点亮数据
void delay(uint n)
{
uchar i;
uint j;
for(j=0;j<n;j++)
for(i=0;i<123;i++);
}
void main (void)
{
uchar i;
while(1)
{
for(i=0;i<16;i++)
{
P1=tab[i];
delay(500);
}
}
}
(三)移位运算符法
左移代码分析
i | temp | P1=~temp | LED情况 | temp=temp<<1 (高位丢弃,低位补0) |
0 | 0x01 0000 0001 | 1111 1110 0xfe | LED1亮 | 0000 0010 0x02 |
1 | 0x02 0000 0010 | 1111 1101 0xfd | LED2亮 | 0000 0100 0x04 |
2 | 0x04 0000 0100 | 1111 1011 0xfb | LED3亮 | 0000 1000 0x08 |
3 | 0x08 0000 1000 | 1111 0111 0xf7 | LED4亮 | 0001 0000 0x10 |
4 | 0x10 0001 0000 | 1110 1111 0xef | LED5亮 | 0010 0000 0x20 |
5 | 0x20 0010 0000 | 1101 1111 0xdf | LED6亮 | 0100 0000 0x40 |
6 | 0x40 0100 0000 | 1011 1111 0xbf | LED7亮 | 1000 0000 0x80 |
7 | 0x80 1000 0000 | 0111 1111 0x7f | LED8亮 | 0000 0000 0x00 |
右移代码分析
i | temp | P1=~temp | LED情况 | temp=temp>>1 (低位丢弃,高位补0) |
0 | 0x80 1000 0000 | 0111 1111 0x7f | LED8亮 | 0100 0000 0x40 |
1 | 0x40 0100 0000 | 1011 1111 0xbf | LED7亮 | 0010 0000 0x20 |
2 | 0x20 0010 0000 | 1101 1111 0xdf | LED6亮 | 0001 0000 0x10 |
3 | 0x10 0001 0000 | 1110 1111 0xef | LED5亮 | 0000 1000 0x08 |
4 | 0x08 0000 1000 | 1111 0111 0xf7 | LED4亮 | 0000 0100 0x04 |
5 | 0x04 0000 0100 | 1111 1011 0xfb | LED3亮 | 0000 0010 0x02 |
6 | 0x02 0000 0010 | 1111 1101 0xfd | LED2亮 | 0000 0001 0x01 |
7 | 0x01 0000 0001 | 1111 1110 0xfe | LED1亮 | 0000 0000 0x00 |
优点:代码简短
缺点:移位运算符分析麻烦
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
void delay(uint n)
{
uchar i;
uint j;
for(j=0;j<n;j++)
for(i=0;i<123;i++);
}
void main (void)
{
uchar i,temp;
while(1)
{
temp=0x01;
for(i=0;i<8;i++)//左移循环
{
P1=~temp;//取反
delay(500);
temp=temp<<1;//左移一位
}
temp=0x80;
for(i=0;i<8;i++)//右移循环
{
P1=~temp;//取反
delay(500);
temp=temp>>1;//右移移位
}
}
}
(四)循环左、右移位函数法
左移函数分析
temp | P1=temp | temp=_crol_(temp,1)(高位补低位) |
0xfe | 1111 1110 LED1亮 | 1111 1101 |
0xfd | 1111 1101 LED2亮 | 1111 1011 |
0xfb | 1111 1011 LED3亮 | 1111 0111 |
0xf7 | 1111 0111 LED4亮 | 1110 1111 |
0xef | 1110 1111 LED5亮 | 1101 1111 |
0xdf | 1101 1111 LED6亮 | 1011 1111 |
0xbf | 1011 1111 LED7亮 | 0111 1111 |
0x7f | 0111 1111 LED8亮 | 1111 1110 |
右移函数分析
temp | P1=temp | temp=_cror_(temp,1)(低位补高位) |
0x7f | 0111 1111 LED8亮 | 1011 1111 |
0xbf | 1011 1111 LED7亮 | 1101 1111 |
0xdf | 1101 1111 LED6亮 | 1110 1111 |
0xef | 1110 1111 LED5亮 | 1111 0111 |
0xf7 | 1111 0111 LED4亮 | 1111 1011 |
0xfb | 1111 1011 LED3亮 | 1111 1101 |
0xfd | 1111 1101 LED2亮 | 1111 1110 |
0xfe | 1111 1110 LED1亮 | 0111 1111 |
优点:代码简短
缺点:移位函数分析麻烦
#include <reg52.h>
#include <intrins.h>//包含移位函数的头文件
#define uchar unsigned char
#define uint unsigned int
void delay(uint n)
{
uchar i;
uint j;
for(j=0;j<n;j++)
for(i=0;i<123;i++);
}
void main (void)
{
uchar i,temp;
while(1)
{
temp=0xfe;
for(i=0;i<8;i++)//左移位循环
{
P1=temp;
delay(500);
temp=_crol_(temp,1);
}
temp=0x7f;
for(i=0;i<8;i++)//右移位循环
{
P1=temp;
delay(500);
temp=_cror_(temp,1);
}
}
}