微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 求大神帮忙看这个中断为何无法启用?

求大神帮忙看这个中断为何无法启用?

时间:10-02 整理:3721RD 点击:
用的52单片机,但是蜂鸣器无法响。求大神解答,谢谢
#include<reg52.h>
#include<intrins.h>
sbit left=P3^0;
sbit right= P3^2;
sbit fuyuan=P3^1;
sbit led1=P1^0;
sbit led2=P1^1;
sbit led3=P1^2;
sbit bee=P2^3;
sbit beekey=P3^3;
int i=1;
void delay1s(void)   //  1秒延时
{
    unsigned char a,b,c;
    for(c=46;c>0;c--)
        for(b=152;b>0;b--)
            for(a=70;a>0;a--);
    _nop_();  //if Keil,require use intrins.h
}
void delay(void)   // 10微妙延时
{
    unsigned char a,b,c;
    for(c=5;c>0;c--)
        for(b=4;b>0;b--)
            for(a=248;a>0;a--);
}
void InitTimer0(void)   //定时器0;
{
    TMOD = 0x01;
    TH0 = 0x0FF;
    TL0 = 0x9C;
    EA = 1;
    ET0 = 1;
    TR0 = 1;
}
void beescankey()    //按下蜂鸣器响
{
if(beekey==0)
{
  delay();
  if(beekey==0)
   {
    bee=1;
    while(beekey==0) ;
    bee=0;
   }
}
}  
   
void scankey()     //按下L独立按键 ,led灯亮
{
if(left==0)
{
  delay();
  if(left==0)
   {
    led1=0;
    while(left==0) ;
    delay1s() ;  
    led1=1;
   }  
}
if(right==0)
{
  delay();
  if(right==0)
   {
    led3=0;
    while(right==0) ;
       delay1s() ;
    led3=1;
   }  
}
if(fuyuan==0)
{
  delay();
  if(fuyuan==0)
   {
    led2=0;
    while(fuyuan==0) ;
    delay1s() ;
    led2=1;
   }  
}
}
void main()
{
InitTimer0();
while(1)
scankey();
}
void Timer0Interrupt(void) interrupt 1
{
    TH0 = 0x0FF;
    TL0 = 0x9C;
    beescankey() ;
}

d顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶

把按键里面就加一个bee=1看看会不会响,感觉有可能松手有问题

版权声明:本文为博主原创文章,未经博主允许不得转载。
最近写一个程序,需要在用户模式下关中断,但ARM 7的体系结构决定了中断必须在特权模式下才可以更改,所以想到使用ARM的软中断来实现关中断和开中断.

使用软中断,首先要有硬件指令的支持.ARM有条指令是SWI.
SWI 指令的格式为:
SWI {条件} 24 位的立即数
SWI 指令用于产生软件中断,以便用户程序能调用操作系统的系统例程。操作系统在 SWI 的异常处理程序中提供相应的系统服务,指令中 24 位的立即数指定用户程序调用系统例程的类型,相关参数通过通用寄存器传递,当指令中 24 位的立即数被忽略时,用户程序调用系统例程的类型由通用寄存器 R0 的内容决定,同时,参数通过其他通用寄存器传递。
指令示例:
SWI  0x02       ;该指令调用操作系统编号位02的系统例程。

在keil MDK中,关键字__svc可以产生硬件SWI指令,使得处理器能响应软件中断.关键字__svc,keil MDK帮助文件中这样描述:
__svc 关键字声明超级用户调用 (SVC) 函数,该函数最多使用四个类似于整数的参数,并通过 value_in_regs 结构最多返回四个结果。
__svc 是一个函数限定符。它影响函数的类型。
语法
__svc(int svc_num) return-type function-name([argument-list]);
其中:
    svc_num 是在 SVC 指令中使用的立即值。
    它是一个表达式,其计算结果为以下范围内的整数:
         ? 在 ARM 指令中为 0 到 224–1 (24 位值)
         ? 在 16 位 Thumb 指令中为 0-255 (8 位值)。
要在keil MDK中使用软件中断,要做好两件事:第一件,更改启动文件,编写软件中断的汇编入口.在这个汇编入口中主要根据软件中断命令号进行相应的函数跳转.第二件,编写相应命令号的C语言服务函数.下面举例怎么样用软件中断实现开中断和关中断.

第一步:更改启动代码
keil MDK自带的启动代码有类似下面的语句:
Vectors         LDR     PC, Reset_Addr         
                     LDR     PC, Undef_Addr
                     LDR     PC, SWI_Addr
                     LDR     PC, PAbt_Addr
                     LDR     PC, DAbt_Addr
蓝色语句是程序复位后要执行的第一条指令,即复位异常入口;而红色语句就是执行一个软件中断指令后,要跳转到的软件中断异常入口.通过语句"SWI_Addr        DCD     SWI_Handler"进行中转,软件中断会跳转到标号为SWI_Handler的语句处,该处即处理软件中断的命令号.源代码如下:
       EXPORT    SWI_Handler
      extern  EnableIrqFunc          ;使能中断函数名,用C语言实现
      extern  DisableIrqFunc         ;禁止中断函数名,用C语言实现
SWI_Handler
    STMFD  SP!, {R0,R12,LR}       ;入栈
    LDR      R0, [LR,#-4]               ;取指令
    BIC       R0,R0,#0xFF000000  ;取软件中断命令号
    CMP      R0,#0                        ;和0比较,因为我的使能中断用了软件中断命令0,禁止中断使用了软件中断命令1
    BLEQ     EnableIrqFunc                ;为零调用使能中断函数
    BLNE    DisableIrqFunc                ;不为零调用禁止中断函数
    LDMFD  SP!,{R0,R12,PC}^    ;出栈

第二部:编写相应命令号的C语言服务函数.
声明软件中断:
__svc(0x00) void EnableIrq(void);  //使能中断
__svc(0x01) void DisableIrq(void);  //禁止中断

编写服务函数:
[cpp] view plain copy print?
void DisableIrqFunc(void)  
{  
    int temp;  
    __asm  
    {  
        MRS temp,SPSR  
        ORR temp,temp,#0x80  
        MSR SPSR_c,temp  
    }  
}  
void EnableIrqFunc(void)  
{  
    int temp;  
    __asm  
    {  
        MRS temp,SPSR  
        BIC temp,temp,#0x80  
        MSR SPSR_c,temp  
    }  
}  

到此,使能和禁止中断的软中断就结束了,下面看一下执行过程.

在程序中,如果想关中断,只需使用:DisableIrq();
MDK编译器在执行这句函数时,自动用软中断指令代替,即: SWI 0x01
ARM执行这条软件中断指令后,发生软件中断异常,程序跳转到软件中断异常服务函数处,即汇编代码标号为SWI_Handler处,在这里判断软件中断命令号是0x01,然后执行 BLNE    DisableIrqFunc   语句,调用禁止中断函数,实现关中断.

谢谢啦

专业打酱油的路过!

顶顶顶顶顶顶顶顶顶顶

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top