题目:
使用单片机驱动8个LED,2个按键并实现跑马灯功能。
当按下按键1时,LED 从左至右依次点亮,全亮后再从右至左依次熄灭,全灭后再从左至右依次点亮,依次循环下去。
当按下按键2 时,LED 从右至左依次点亮,全亮后再从左至右依次熄灭,全灭后再从右至左依次点亮,依次循环下去。
电路部分:
利用Proteus软件搭建的电路图如下:
部分一:AT89C51最小系统电路。
AT89C51最小系统电路其中包括时钟电路和复位电路。
时钟电路:产生像时钟一样准确运动的振荡电路。
复位电路:按键按下可以使程序重新运行。
部分二:从LED-0到LED7接入P2口的八个LED灯电路。
发光二极管:只允许电流单方向通过,并发光。
上拉电阻:降低回路电流,避免元件损坏。
部分三:按钮控制电路
按键按下,P3_2或P3_3口与GND相接,置 0。
按键未按下,P3_2或P3_3口与电阻相接,按键处断开,置 1。
上拉电阻:降低电流,保护电路。
程序部分:
设计思路:
1.先利用两个for循环和延时函数初步实现LED灯延时流水功能。
2.按键部分接入单片机的外部中断0和外部中断1,当按键按下时利用外部中断去打断for循环,从而实现流水灯方向的改变。
跑马灯亮灭思路:
右移亮:
P2=0xFE;
for(i=0;i<7;i++)
{
DELAY;
P2<<=1;
}
左移灭:
P2=0x80;
for(i=0;i<7;i++)
{
DELAY;
P2=(P2>>1)|0x80;
}
左移亮:
P2=0x7F;
for(i=0;i<7;i++)
{
DELAY;
P2>>=1;
}
右移灭:
P2=0x01;
for(i=0;i<7;i++)
{
DELAY;
P2=(P2<<1)|0x01;
}
方法一:利用外部中断0、外部中断1和Delay延时函数。
具体代码:文章来源:https://www.toymoban.com/news/detail-470888.html
#include <REGX52.H>
#include <intrins.h>
typedef unsigned char u8;
typedef unsigned int u16;
void Delay300ms();
bit key1_flag = 0;
bit key2_flag = 0;
u8 i =0;
u16 Num;
void main()
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD=0x01;//设置定时器0为工作方式1
TH0=(65535-50000)/256;//50MS
TL0=(65535-50000)%256;
ET0=1;
TR0=1;
EA=1;//开总中断
while(1)
{
if(key1_flag)
{
P2 = 0xFE;
for(i=0;i<7;i++) //左移循环亮
{
Delay300ms();
P2 <<= 1;
}
Delay300ms();
P2 = 0x80;
for(i=0;i<7;i++)//右移循环灭
{
Delay300ms();
P2 = (P2 >> 1) | 0x80;
}
Delay300ms();
}
if(key2_flag)
{
P2=0x7F;
for(i=0;i<7;i++)//右移循环亮
{
Delay300ms();
P2>>=1;
}
Delay300ms();
P2=0x01;
for(i=0;i<7;i++)//左移循环灭
{
Delay300ms();
P2=(P2<<1)|0x01;
}
Delay300ms();
}
}
}
void exter0() interrupt 0 //外部中断0
{
key1_flag = 1;
key2_flag = 0;
}
void exint1() interrupt 2 //外部中断1
{
key1_flag = 0;
key2_flag = 1;
}
//时钟频率为12MHz的300ms的延时函数
void Delay300ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
i = 3;
j = 72;
k = 161;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
弊端:
1.浪费CPU资源:因为采用了大量的Delay()函数会导致单片机cpu进行大量的空运算。
2.延时可能不够精准:通过指令周期进行延时会产生误差。
改进的方法二:利用外部中断0、外部中断1和定时器0。
具体代码:
#include <REGX52.H>
#include <intrins.h>
typedef unsigned char u8;
typedef unsigned int u16;
bit key1_flag = 0;
bit key2_flag = 0;
u8 i =0;
u16 Num = 0;
sbit led = P2^0;
void main()
{
TMOD = 0x01;//设置定时器0为工作方式1
TH0 = (65535-1000)/256;//设初值1ms
TL0 = (65535-1000)%256;
ET0 = 1;//定时器0的溢出允许位
TR0 = 1;//定时器0的运行控制位
EX0 = 1;//外部中断0的控制位
EX1 = 1;//外部中断1控制位
EA = 1;//开总中断
while(1)
{
}
}
void exter0() interrupt 0 //外部中断0
{
key1_flag = 1;
key2_flag = 0;
i = 0;
}
void exint1() interrupt 2 //外部中断1
{
key1_flag = 0;
key2_flag = 1;
i= 0;
}
void tm0_isr() interrupt 1 using 1 //定时器中断0
{
TH0 = (65535-1000)/256;//设初值1ms
TL0 = (65535-1000)%256;
Num++;
if(Num>199)
{
Num = 0;
if(key1_flag)
{
switch(i++)
{
case 0:P2 = 0xFE; break;
case 1:case 2:case 3:case 4:case 5:case 6:case 7:P2 <<= 1;break;
case 8:P2 = 0x80;break;
case 9:case 10:case 11:case 12:case 13:case 14:P2 = (P2 >> 1) | 0x80;break;
case 15:P2 = (P2 >> 1) | 0x80;i=0;break;
}
}
else if(key2_flag)
{
switch(i++)
{
case 0:P2 = 0x7F; break;
case 1:case 2:case 3:case 4:case 5:case 6:case 7:P2 >>= 1;break;
case 8:P2 = 0x01; break;
case 9:case 10:case 11:case 12:case 13:case 14:P2 = (P2 << 1) | 0x01; break;
case 15:P2 = (P2 << 1) | 0x01;i=0;break;
}
}
}
}
以上就是我此次对51单片机跑马灯部分的学习,如有错误或者更好的想法,欢迎大家提出。 文章来源地址https://www.toymoban.com/news/detail-470888.html
到了这里,关于利用51单片机进行LED 跑马灯设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!