单片机下面程序是怎么实行LED灯闪烁的?

ORG 0000H

LJMP MAIN
MAIN:CLR P2.0
LCALL DELAY
SETB P2.0
LCALL DELAY
SJMP MAIN
DELY:MOV R7,#1000
D2:DJNZ R6,D2
DJNZ R7,D1
RET
END
程序怎么走我知道,就是为何这样就可以让灯闪亮不懂
请问是不是,首先低电平,然后灯亮,走完之后到RET 再返回到开头输出高电平,然后灯灭这样重复?
但假如是这样的话,程序到RET时,返回主程序,又怎么直接走到输出高电平? 而跳过了低电平?
最新回答
海心

2024-09-06 21:05:20

led的闪烁是通过一定频率的开关led实现的。如果开关频率太快,人类是看不出来是在闪烁,所以开关频率要低一些,比较高的切换频率可以用来控制led亮度(PWM),或者用来做数码管显示。
实现方式主要有两种方式:
(1)使用代码循环做为延时来控制led开关频率:
eg:
#define HIGH 1
#define LOW  0
#define LED P1.1//假设为51单片机
void delay_nms(unsigned int n_ms)
{
    while(n_ms--)
    {
        delay_1ms();//延时一毫米函数,可以根据具体单片机自己定义
    }
}

void main()
{
    for(;;)
    {
        LED = HIGH;
        delay_nms(500);
        LED = LOW;
        delay_nms(500);
    }
}

(2)使用定时器来控制led开关频率:
eg:
#define HIGH 1
#define LOW  0
#define LED P1.1
unsigned char f_500ms = 0;
void timer0() interrupt 1 //假设为10ms定时
{
    //xxxx
    f_500ms++;
}
void main()
{
    for(;;)
    {
        if(f_500ms < 100)//1秒(10ms * 50 = 1000ms = 1s)
        {
            if(f_500ms < 50)
            {
                LED = HIGH;
            }
            else
            {
                LED = LOW;
            }
        }
        else
        {
            f_500ms = 0;
        }
    }
}
两种方式都可以,但在实际使用中尽量不要使用循环延时,因为使用循环延时在延时过程中,单片机除了中断的响应,不能再做任何事情了,而使用定时器,程序只需要通过判断时间变量就可以实现同样的效果,不会占用太多时间,所以单片机能够做更多的事情,实现实时性的要求,这是嵌入式开发中需要重视的。
纯洁的小黄瓜

2024-09-06 18:06:17

  1. 原理:LED闪烁其实就是LED亮灭,要看电路,有的直接是单片机驱动的小LED,给高平亮,给低电平灭,一直给高低电平循环就表现出亮灭了。

  2. 延时:就是亮多久后灭,灭多久后亮。

  3. 实现:先给高电平,LED亮,经过延时后,再给一个低电平,LED灭,再给一个延时,如此无限循环。

我萌怪我咯

2024-09-06 13:26:47

单片机通过I/O口高低电平控制LED灯闪烁
led可以正极接单片机也可以负极接单片机,中间接一个限流电阻,以负极接单片机为例:
二极管正极接电源正极,负极接单片机I/O口,程序控制单片机接led的I/O输出低电平,led就点亮,输出高电平则led两端都为高电平,led不导通熄灭,程序利用单片机定时器控制io口不断输出高低电平就可以实现LED灯闪烁,闪烁的快慢通过定时器定时的长短来控制
美少女壮士

2024-09-06 12:12:45

这个很好理解的呀,P2.0清零--延时--置1--延时,一直循环。
换成C语言就是如下:
while(1)
{
P2^0=0;
delay();
P2^0=1;
delay();
}
追问
咳咳,虽然不懂C语言,大概也能看出0和1就是闪亮。。。的确好理解
但还是想弄清楚汇编怎么弄,能否麻烦解释一下吗
追答
MAIN:
CLR P2.0 ;P2.0置低
LCALL DELAY ;延时
SETB P2.0 ;P2.0置高
LCALL DELAY ;延时
SJMP MAIN ;转MAIN从头开始
DELAY:
MOV R7,#200 ;这里送1000超出范围了,最大255
D2:
;DJNZ R6,D2 ;这句取消,没有给R6赋值
DJNZ R7,D2 ;这里D1改D2,没有D1标号
RET
END

改写一下延时程序:
DELAY:
MOV R7,#200
DLY:
MOV R6,#250
DJNZ R6,$
DJNZ R7,DLY
RET
追问
谢谢,我今天问了老师了,老师跟我说程序执行完好到RET,就跳转到主程序的下一条指令了,原本是亮的,跳到SETB 高电平就灭了,但跳到主程序的下条指令怎么是挑到SETB P2.0了,它上面还有好多条指令啊
対妳旳执着ヽ

2024-09-06 09:44:31

开一段时间,关一段时间就是LED闪烁;比如:
#include<STC.H>
#define uint unsigned int
#define uchar unsigned char
sbit LED=P1^0;

void delay(uint x )
{
uint i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
void main()
{

while(1)
{
LED=~LED;
delay(15);
}
}
此处是用延时使得LED闪烁;也可以用定时器,精确定时使得LED闪烁:下面是四个LED循环滚动闪烁;
#include<STC.H>
#define uchar unsigned char
#define uint unsigned int
sbit B1=P0^0;
sbit G1=P0^1;
sbit R1=P0^2;
sbit Y1=P0^3;
uint i,j,k;
//主程序
void main()
{
i=j=k=0;
P0=0xff;
TMOD=0x02; //定时器 0 工作方式 2
TH0=256-200; //200us 定时
TL0=256-200;
IE=0x82;
TR0=1; //启动定时器
}while(1);

//T0 中断函数
void LED_Flash_and_Scroll() interrupt 1
{
if(++k<35) return; //定时中断若干次后执行闪烁
k=0;
switch(i)
{
case 0: B1=~B1;break;
case 1: G1=~G1;break;
case 2: R1=~R1;break;
case 3: Y1=~Y1;break;
default:i=0;
}
if(++j<300) return; //每次闪烁持续一段时间
j=0;
P0=0xff;关闭显示
i++; //切换到下一个 LED
}