找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2329|回复: 7
收起左侧

AT89C52单核A2单片机按下独立按键蜂鸣器响流水灯左移松开按键蜂鸣器不响流水灯右移

[复制链接]
ID:863668 发表于 2020-12-19 21:12 | 显示全部楼层 |阅读模式
初学单片机,很多地方不懂,看了视频,之前尝试的是CPU控制流水灯和蜂鸣器同时运行,但是用delay函数延时两个程序相冲突。然后用定时器控制蜂鸣器50us中断,还是不行,求大神指点

#include<reg52.h>
#include<intrins.h>

typedef unsigned int u16;
typedef unsigned char u8;

sbit k1 = P3^0;
sbit beep = P1^5;

void delay(u16 i)
{
        while(i--);
}

void Timer0Init()
{
        TMOD |= 0x01;
        TH0 = 0xff;
        TL0 = 0xf6;
        ET0 = 1;
        EA = 1;
        TR0 = 1;
}

void main()
{               
        beep = 1;
        Timer0Init();
        if(k1==0)
        {               
                while(k1==0)
                {
                        P2 = 0xfe;
                        delay(30000);
                        while(1)
                        {
                                P2 = _cror_(P2,1);
                                delay(30000);
                        }
                        while(k1!=0)
                        {
                                P2 = 0xff;
                        }
                }
        }
}

void Timer0()  interrupt 1
{
        static u16 j;
        TH0 = 0xff;
        TL0 = 0xf6;
        j++;
        if(j==5 & k1==0)
        {
                j = 0;
                beep = ~beep;
                if(k1==1)
                {
                        beep = 1;
                }
        }
}

回复

使用道具 举报

ID:213173 发表于 2020-12-19 22:10 | 显示全部楼层
按键控制流水灯,无源蜂鸣器提示音。
#include<reg52.h>
#include<intrins.h>

typedef unsigned int u16;
typedef unsigned char u8;

sbit k1 = P3^0;
sbit beep = P1^5;

u16 num;

void delay(u16 i)
{
        while(i--);
}
void Timer0Init()        //200微秒@12.000MHz
{
        TMOD |= 0x02;        //设置自动重装模式
        TH0 = 0x38;                //设置定时重载值
        TL0 = 0x38;                //设置定时初值
        TR0 = 1;                        //定时器0开始计时
        ET0 = 1;
        EA = 1;
}

void main()
{               
        beep = 1;
        Timer0Init();
        P2=0xfe;
        while(1)
        {
                if(!k1)
                {
                        delay(100);
                        if(!k1)
                        {
                                P2=_cror_(P2,1);
                                num=500;//响0.1s
                                while(!k1);
                        }
                }
        }
}

void Timer0()  interrupt 1
{
        if(num>0)
        {
                num--;
                beep=~beep;//2.5KHz
        }
        else beep = 1;
}
回复

使用道具 举报

ID:863668 发表于 2020-12-20 16:48 | 显示全部楼层
wulin 发表于 2020-12-19 22:10
按键控制流水灯,无源蜂鸣器提示音。
#include
#include

感谢大佬!!!
整出来了!琢磨好几天了
我后续加了点东西进去,一直按一直响流水灯左移
看来还有很多东西要学
最后再次感谢大佬!
回复

使用道具 举报

ID:864035 发表于 2020-12-20 16:56 | 显示全部楼层
ADRLED        EQU        8700H                ;LED工作地址

        ORG         0000H
        LJMP         MAIN

        ORG        1BH
        JMP        T1INT                ;定时器1中断入口地址

        ORG         0100H
MAIN:        MOV         SP,#60H
        MOV        R0,#0AH                ;R0为0.1秒的次数
        ANL        TMOD,#0FH        ;定时器1置为方式1
        ORL        TMOD,#10H
        MOV        TL1,#0B0H        ;置定时器1的中断时间为0.1S
        MOV        TH1,#3CH
        ORL        IE,#88H                ;允许定时器1中断
        MOV        R2,#0                ;置R2初值,R2对应显示字符的字形码相对地址
        MOV        R5,#16                ;置显示的字符数初值
        SETB        P3.4                ;使蜂鸣器的负端为高不鸣叫
        CLR        P3.5                ;使数码管的共阴极为低电平
NEXT:        MOV        DPTR,#TAB        ;置字形码表首地址
        MOV        A,R2
        MOVC        A,@A+DPTR        ;取出相应的字形码
        MOV         DPTR,#ADRLED        ;数码管段码地址
        MOVX         @DPTR,A                ;送数码管段码(字形码)
        SETB        TR1                ;启动定时器1
LOOP:        CJNE        R0,#00H,LOOP        ;不够1秒,转LOOP
        INC        R2
        MOV        R0,#0AH                ;重置R0为10
        DJNZ        R5,NEXT                ;16个字符没有显示1遍,转NEXT显示下一字符
        CLR        P3.4                ;使蜂鸣器的负端为低其鸣叫
        MOV        A,#0FFH                ;报警之后数码管显示全亮
        MOV         DPTR,#ADRLED        ;数码管段码地址
        MOVX         @DPTR,A                ;送数码管段码(字形码)
        CLR        TR1                ;定时器停止计数
        SJMP        $                ;死循环

T1INT:        CLR        TR1                ;定时器1中断,首先停止计数
        DEC        R0                ;次数减1
        MOV        TL1,#0B0H        ;重置定时器1时间常数
        MOV        TH1,#3CH
        SETB        TR1                ;恢复定时器1计数
        RETI

TAB:        DB        3FH,06H,5BH,4FH,66H,6DH,7DH,07H                ;字形码表
        DB        7FH,6FH,77H,7CH,58H,5EH,79H,71H

        END                       
回复

使用道具 举报

ID:863668 发表于 2020-12-20 19:41 | 显示全部楼层
787878979867468 发表于 2020-12-20 16:56
ADRLED        EQU        8700H                ;LED工作地址

        ORG         0000H

这....看的我一脸懵啊
这种写代码的格式我好像没有学过
只学过最基本的C语言
回复

使用道具 举报

ID:420836 发表于 2020-12-20 23:51 | 显示全部楼层
作为初学者,请从简单到复杂进行尝试,首先可以使蜂鸣器工作,然后使LED灯工作,最后将两者结合使用。
回复

使用道具 举报

ID:863668 发表于 2020-12-21 11:16 | 显示全部楼层
TTQ001 发表于 2020-12-20 23:51
作为初学者,请从简单到复杂进行尝试,首先可以使蜂鸣器工作,然后使LED灯工作,最后将两者结合使用。

嗯嗯,是一步一步尝试的
蜂鸣器和流水灯单独使用无论是用延时函数还是外部中断都可以实现
可一把他俩放到一起就不知道咋回事了
回复

使用道具 举报

ID:824490 发表于 2020-12-21 16:49 | 显示全部楼层
黑羊羔子 发表于 2020-12-21 11:16
嗯嗯,是一步一步尝试的
蜂鸣器和流水灯单独使用无论是用延时函数还是外部中断都可以实现
可一把他俩放 ...

看你是把哪个任务做为主循环。
如果以流水灯为主,那么:
流水灯
{
//检测按键有效则
while(按键没松开)
  BEEP();
}
如果是BEEP为主,则:
beep
{
//检测按键有效则
while(按键没松开)
  流水灯();


}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表