精华内容
下载资源
问答
  • 今天这个程序主要实现了通过mini2440上面的六个按键控制那个4个LED,并且在按键的过程中蜂鸣器还会发出声音。程序的功能图: <br />      在此程序中并没有使用到按键中断,而是...

    今天这个程序主要实现了通过mini2440上面的六个按键去控制那个4个LED,并且在按键的过程中蜂鸣器还会发出声音。程序的功能图:

     

     

     

    在此程序中并没有使用到按键的中断,而是使用了一个死循环去实现的。并且这个程序保护两个部分,一个是汇编程序编写的引导部分,因为这是一个裸机的程序,即没有操作系统的程序,因此想要在板子上运行C程序必须进行相应的初始化的工作,这个就是汇编程序的功能。汇编代码如下:
    IMPORT Main
    CODE32
    AREA Init,CODE,READONLY
    ENTRY
    ldr r0, =0x53000000
    mov r1, #0x0
    str r1, [r0]
    ldr sp, =1024 * 4
    bl Main
    main_loop
    b main_loop
    END
    这是一个非常简单的汇编引导程序,我并没有使用那个自带的2440test中的引导程序,主要是为了让简化一点,在这个程序中只是初始化了一下堆栈并且关闭了WatchDog,因为C语言的运行环境必须要用到堆栈。
    下面是C语言的部分,也是这个程序最核心的部分:

     

     

     

    摘自网络,在MDK调试运行在MICRO2440上。

     

     

     

     

    展开全文
  • 注意:key0为按键1(控制两个灯翻转状态),key1为按键2(控制LED0,即右边小灯),key2为按键3,(控制LED1,即左边小灯)key_up为按键4,(控制蜂鸣器)。每次按下后会根据当前状态输出到串口相应语句。(为了搞定...
  • //蜂鸣器   <p>void delayms(unsigned char x)//按键消抖毫秒级延时 <p>{<!-- -->  int i,j;  for(i=x;i>0;i--)  for(j=0;j<120;j++); <p>} <p>/***************主函数 ********...
  • 中断服务程序将蜂鸣器控制输出信号取反。  按键蜂鸣器接口电路图阅读实验程序,回答问题(将注释补充完整):  <p>#include "config.h"  <p>#define LED (1 << 7 )...
  • s5p6818裸机-中断学习

    2021-03-24 12:17:33
    本次学习的目的是通过按按键触发按键中断,调用相关的中断服务函数,实现蜂鸣器鸣响。通过裸机学习能使自己对SoC的运行环境,开发环境有更好的了解。 软件实现流程 1)在start.S启动汇编中实现中断向量表,及irq处理...

    前言

    本次学习的目的是通过按按键触发按键中断,调用相关的中断服务函数,实现蜂鸣器鸣响。通过裸机学习能使自己对SoC的运行环境,开发环境有更好的了解。

    软件实现流程

    1)在start.S启动汇编中实现中断向量表,及irq处理函数
    2)实现irq中断结构体数组,irq通用中断服务函数注册函数(中断号和中断服务函数的联系)
    3)实现gic中断控制器初始化函数
    4)实现gpio初始化函数,复用-中断配置

    流程具体

    1、异常向量表和IRQ_Handler一般都在start.S里面编写,因为需要做一些中断触发时保护现场和恢复现场的工作。

    _start:
        /*DDR范围:0x40000000~0x80000000 1GB*/
    
        /*异常向量表 */
        ldr pc, =Reset_Handler      /* 复位中断 					*/	
        ldr pc, =Undefined_Handelr  /* 未定义中断 					*/
        ldr pc, =SVC_Handelr        /* SVC(Supervisor)中断 		*/
        ldr pc, =PrefAbort_Handler  /* 预取终止中断 					*/
        ldr pc, =DataAbort_Handler  /* 数据终止中断 					*/
        ldr pc, =NotUsed_Handler    /* 未使用中断					*/
        ldr pc, =IRQ_Handler        /* IRQ中断 					*/
        ldr pc, =FIQ_Handler        /* FIQ(快速中断)未定义中断 			*/
    
    IRQ_Handler:
        ldr sp,=0x7FC00000 /*设置irq模式的sp指针 */
        /*保护现场 */
        push {lr}
        push {r0-r3,r12}   
        mrs r0, spsr   /*访问SPSR寄存器,保存cpsr */
        push {r0}
    /****************************************************** */
    
        mrc p15,1,r1,c15,c3,0 /*读取GIC的CPU接口端基地址 GICC_CTLR*/
        ldr r0, [r1,#0xC]   /*基地址偏移0xC,访问GICC_IAR寄存器 */
                            /*GICC_IAR能够获取到中断ID号 */
        push {r0,r1}
        cps #0x3           /*进入svc模式 */
        push {lr}       /*保存svc的lr寄存器 */
    
        //ldr r2, =system_irqhandler 
        blx system_irqhandler            /*跳转到c程序的中断处理函数中,带上一个参数r0(中断ID)*/
    
        pop {lr}   /*lr出栈 */
        cps #0x2   /*进入irq模式 */
        pop {r0,r1}
        str r0, [r1,#0x10]  /*中断执行完成,把中断ID写入EOIR寄存器 */
    
        /*恢复现场 */
        pop {r0}
        msr spsr, r0  /*恢复cpsr */
        pop {r0-r3,r12}
        pop {lr}
    /********************************** */
        subs pc, lr, #4 /*返回触发中断时,下一条指令的位置 */
    

    其中恢复现场的subs pc, lr, #4 是因为cpu是三级流水线工作的,取址,译址,执行。比如当前第一条指令是执行,第二条指令是译址,第三条指令是取址,那么当中断触发时,pc所指向的是取址,而恢复现场则需要从第二条指令那里开始恢复即pc-4的位置。

    2、实现irq中断结构体数组,(中断号和中断服务函数的联系)

    /*中断服务函数的形式*/
    typedef void (*system_irq_handler_t)(unsigned int giccIar,void *param);
    
    /*中断服务函数结构体*/
    typedef struct _sys_irq_handle
    {
        system_irq_handler_t irqhandler;    /*中断服务函数*/
        void *userParam;                    /*中断服务函数参数*/
    }sys_irq_handle_t;
    
    static sys_irq_handle_t irqTable[160]; /*数组大小为160,每一个元素的下标对应一个中断ID*/
    

    有了这个结构体数组,就实现了中断号和中断服务函数的联系了,下一步就是把中断服务函数往里面注册就可以了。

    3、irq通用中断服务函数注册函数

    /*给指定的中断号注册中断服务函数 */
    void system_register_irqhandler(IRQn_Type irq, system_irq_handler_t handler, void *userParam)
    {
        irqTable[irq].irqhandler = handler;
        irqTable[irq].userParam = userParam;
    }
    
    

    这个就是往结构体里面注册中断服务函数了,自己编写好最终的中断服务函数,作为参数handler往里面存。

    4、上面start.S的IRQ_Handler会跳进这个函数,根据中断ID执行最终的中断服务函数

    /*具体的中断服务函数*/
    void system_irqhandler(unsigned int giccIar)
    {
        unsigned int intNum = giccIar & 0x3FF;  /*GICC_IAR的bit[9:0]为中断ID*/
        if(intNum < NUMBER_OF_INT_VECTORS)
        {
            irqNesting++;
            irqTable[intNum].irqhandler(intNum, irqTable[intNum].userParam);
            irqNesting--;
        }
        else
            return;
    }
    

    5、gic的初始化
    参考数据手册,得到需要用到的寄存器GICD_TYPER、GICD_ISCENABLERn、GICC_PMR、GICC_BPR、GICD_CTRL、GICC_CTRL、GICD_ISENABLERn、GICD_IPRIORITYRn,寄存器的具体作用我在下面代码里面也作了注释,或者去查看手册。

    /*GIC初始化*/
    void GIC_init(void)
    {
        unsigned int i;
        unsigned int irqRegs;
    
        /*读取bit[0:4]为N,支持的中断ID最大值:(32(N+1)-1=159)*/
        irqRegs = (GIC->D_TYPER & 0x1F) + 1; 
    
        /*关闭所有SGI,PPI,SPI中断*/
        for(i=0; i<irqRegs; i++) 
            GIC->D_ISCENABLERn[i] |= 0xFFFFFFFF; 
    
        /*设置支持32个优先级,即bit[7:0]=11111000*/
        GIC->C_PMR |= (0xFF << 3);  
        //GIC->C_PMR |= 0xFF;
    
        /*设置5级抢占优先级bit[2:0]=2,即所有中断优先级位都为抢占优先级*/
        GIC->C_BPR |= (2<<0);
    
        /*使能组0的中断分发控制*/
        GIC->D_CTRL |= (0x1<<0);
    
        /*使能组0的中断发送到CPU Core的中断请求信号*/
        GIC->C_CTRL |= (0x1<<0);
    }
    
    /*使能指定中断,并设置优先级*/
    void GIC_EnableIRQ(IRQn_Type IRQn, unsigned int pri)
    {
        /*IRQn/32: 取到0~4寄存器里对应的寄存器*/
        /*IRQn%32: 取到对应寄存器里相应的bit*/
        GIC->D_ISENABLERn[IRQn/32] |= (1<<(IRQn%32));
        GIC->D_IPRIORITYRn[IRQn/4] &= ~(0xFF<<((IRQn%4)*8));
        GIC->D_IPRIORITYRn[IRQn/4] |= (pri<<((IRQn%4)*8));      /*设置指定中断的优先级*/
        //GIC->D_ITARGETSRn[21] &= (~(0xFF<<16));
        //GIC->D_ITARGETSRn[21] |= (0x1<<16);    /*设置指定中断的CPU接口*/
    }
    
    

    6、gpio的中断设置
    通过查看数据手册得到需要使用的寄存器有GPIOXINTENB、GPIOXDETENB、GPIOXDETMODE0、GPIOXDETMODE1、GPIOXDETMODEEX、GPIOXDET,具体功能也是在下面代码的注释里面有说明

    /*使能GPIO口的中断功能*/
    void gpio_intEnable(GPIO_Type *base, int pin)
    {
        base->GPIO_INTENB |= (1<<pin);  /*中断使能*/
        base->GPIO_DETENB |= (1<<pin);  /*检测使能*/
    }
    
    /*设置gpio的中断配置功能*/
    /*GPIOXDETMODE0或者GPIOXDETMODE1需要跟GPIOXDETMODEEX配合一起使用,
    因为配置中断检测方式即高/低电平触发,上升/下降沿触发等需要用到3bit数来配置,
    其中高1bit由GPIOXDETMODEEX提供,低2bit由GPIOXDETMODE0或者GPIOXDETMODE1提供*/
    
    void gpio_intconfig(GPIO_Type *base, int pin, GPIO_Interrupt_Mode_t intmode)
    {
        volatile unsigned int *DetMode;
        unsigned int pin_t;
    
        pin_t = pin;
    
        if (pin<16)
        {
            DetMode = &(base->GPIO_DETMODE0); /*0~15引脚*/
        }
        else
        {
            DetMode = &(base->GPIO_DETMODE1); /*16-31引脚*/
            pin_t -= 16;
        }
        switch(intmode)
        {
            case GPIO_IntLowLevel:
                base->GPIO_DETMODEEX &= ~(1<<pin);    /*000的高(1-bit)*/
                *DetMode &= ~(3<<(2 * pin_t));        /*000的低(2-bit)*/
                break;
            case GPIO_IntHighLevel:
                base->GPIO_DETMODEEX &= ~(1<<pin);                                      /*001的高(1-bit)*/
                *DetMode = (*DetMode & (~(3<<(2 * pin_t)))) | (1<<(2 * pin_t));         /*001的低(2-bit)*/             
                break;
             case GPIO_IntFallingEdge:
                base->GPIO_DETMODEEX &= ~(1<<pin);                                      /*010的高(1-bit)*/
                *DetMode = (*DetMode & (~(3<<(2 * pin_t)))) | (2<<(2 * pin_t));         /*010的低(2-bit)*/       
                break;
            case GPIO_IntRisingEdge:
                base->GPIO_DETMODEEX &= ~(1<<pin);                                      /*011的高(1-bit)*/
                *DetMode = (*DetMode & (~(3<<(2 * pin_t)))) | (3<<(2 * pin_t));         /*011的低(2-bit)*/
                break;
             case GPIO_IntFallingorRisingEdge:
                base->GPIO_DETMODEEX |= (1<<pin);   /*100的高(1-bit)*/
                *DetMode &= ~(3<<2 * pin_t);        /*100的低(2-bit)*/
                break;   
            default:
    			break;
    
        }
    }
    
    /*清除中断标注位*/
    void gpio_clearintflags(GPIO_Type *base, int pin)
    {
        base->GPIO_DET |= (1<<pin);	/*往里面写1即可清除标志位*/
    }
    

    小结

    总体来说整个中断的执行顺序大概是:按下按键 -> 触发irq中断信号 -> gic控制器 -> CPU -> 异常向量表 -> IRQ异常处理 -> 执行最终的中断服务程序

    展开全文
  • 前言 最近写avr时候发现网上教程太少,本着为各位的学习提供帮助的心理,把自己写的程序发...状态指示灯,使用蜂鸣器作为车的报警器。通过编程,实现以下功能: -在按下使能键的同时,可通过指定按键模拟吊车操作,松开

    前言

    最近写avr时候发现网上教程太少,本着为各位的学习提供帮助的心理,把自己写的程序发出来,一起探讨学习,希望我们共同努力,为梦想奋斗。

    功能

    在AVR开发板上模拟一台吊车的操作控制和状态显示功能。将开发板上独立按键设定
    为使能键、急停键、电压采集键,将开发板上的按键或遥杆方向键设定为车的前进、后退、
    提起和放下等控制键,使用LCD1602作为车的状态显示屏,使用LED(红、绿)作为车的
    状态指示灯,使用蜂鸣器作为车的报警器。通过编程,实现以下功能:
    -在按下使能键的同时,可通过指定按键模拟吊车操作,松开使能键,则操作按键无效;
    -按下急停按钮,停止一切动作;
    -控制配套的直流电机旋转,模拟吊车的前进、后退、提起、放下等功能;
    -按下指定按键进行电压采集,通过电位计调节电压,模拟吊车的电量显示功能,同时
    控制电机加速;
    -根据按键输入,控制LED绿灯和红灯的亮、灭,模拟吊车的正常运行、急停或警示
    状态;
    -根据按键输入,控制蜂鸣器不响、响一声、连续响,模拟吊车的正常运行、使能键按
    下、急停或警示等状态;
    -根据按键输入,控制LCD显示多种状态信息,如:按秒更新显示系统累计运行时间、
    暂停更新系统累计运行时间、显示采集的输出电压值(保留小数点后一位)、显示吊车执行
    的工作状态。

    程序

    /*
     * test.c
     *
     * Created: 2020/4/20 15:55:49
     * Author : zjlc
     
     PC0 使能键  | PC1 电机前进(可调)| PC2 电机后退(可调)| PC3 提起(可调,软件调) |PC4 放下(可调,硬件调)
     |PD2 急停键 |PC5 电压采集 |PA6 蜂鸣器|PA5 红灯|PA4 绿灯|PA0 电压采集脚|
     PD7 PD6 电机 PD4,5 电机 PD3 1602 EN PD1,0 RS,RW |
     PB0-PB7 1602数据口
     
     */ 
    
    
    #define F_CPU 8000000
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    char  number[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
    
    #define sreg _SFR_IO8(0X3F)
    #define rs 0
    #define rw 1
    #define en 3
    #define setrs() PORTD |=(1<<rs)
    #define setrw() PORTD |=(1<<rw)
    #define seten() PORTD |=(1<<en)
    #define clrrs() PORTD &=~(1<<rs)
    #define clrrw() PORTD &=~(1<<rw)
    #define clren() PORTD &=~(1<<en)
    int cishu=500;
    void hungray()//忙信号
    {
    	DDRB=0x00;
    	clrrs();
    	setrw();
    	seten();
    	_delay_us(5);
    	while((PINB&0x80)&&(cishu--));
    	clren();
    	DDRB=0xff;
    }
    void write(char data,int or)//写指令或者数据
    {
    	hungray();
    	PORTB=data;
    	if (or==0)//指令
    	{
    		clrrs();
    	}
    	else
    	{
    		setrs();
    	}
    	clrrw();
    	seten();
    	_delay_us(5);
    	clren();
    }
    void move(int x,int y)
    {
    	if(x==0)
    	write(0x80|y,0);
    	else
    	write(0xc0|y,0);
    }
    void display(int x,int y,char cdata)
    {
    	move(x,y);
    	write(cdata,1);
    }
    void dis_cstring(int x,int y,char *cdata)
    {
    	move(x,y);
    	while(*cdata!='\0')
    	{
    		write(*cdata,1);
    		cdata++;
    	}
    }
    void init()
    {
    	write(0x38,0);
    	_delay_ms(300);
    	write(0x0c,0);
    	_delay_ms(20);
    	write(0x01,0);
    	_delay_ms(20);
    	
    }
    char stop[]="stop";
    char run[]="run";
    int i=0,perameter=0,moddle=0,perameter_1=0,initialization=0,time_1=0;
    float C=1.0,lingshi;
    char bit[]={0x01,0x02,0x04,0x08,0x10};
    void begin()
    {
    		PORTB=0XFF;	
    		DDRB=0XFF;
    		
    		PORTA=0XFF;
    		DDRA=0XF0;
    		ADCSRA=0XE7;
    		
    		PORTD=0X0F;
    		DDRD=0XFF;
    		
    		PORTC=0XFF;
    		DDRC=0X00;
    		
    		GICR=0x40;
    		sreg |=(1<<7);
    		
    		TCCR1A=0XA2;
    		TCCR1B=0X19;
    		ICR1=65535;
    		OCR1A=0;
    		OCR1B=0;
    		
    		TCCR0=0x04;
    		TCNT0=0;
    		TIMSK=0X01;
    }
    void buzzer()
    {
    	for(i=0;i<100;i++)
    	{
    		PORTA |=(1<<6);
    		_delay_us(500);
    		PORTA &=~(1<<6);
    		_delay_us(500);
    	}
    }
    SIGNAL(INT0_vect)
    {
    	if(perameter==0)
    		{
    			write(0x01,0);
    			perameter=1;
    		}
    	PORTA |=(1<<4);
    	PORTA &=~(1<<5);
    	PORTD &=~(1<<6);
    	TIMSK=0;
    	OCR1A=0;
    	OCR1B=0;
    	
    	dis_cstring(0,6,stop);
    	buzzer();
    	
    }
    SIGNAL(TIMER0_OVF_vect)
    {
    	if (initialization==122)
    	{
    		initialization=0;
    		time_1++;
    		if((time_1>0)&(time_1<10))
    		display(0,0,48+time_1);
    		else if((time_1>=10)&(time_1<100))
    		{
    			display(0,0,48+time_1/10%10);
    			display(0,1,48+time_1%10);
    		}
    		else if (time_1>99)
    		{
    			display(0,0,48+time_1/100%10);
    			display(0,1,48+time_1/10%10);
    			display(0,2,48+time_1%10);
    		}
    		
    	}
    	initialization++;
    }
    int time_2=0;
    int time_delay=0;
    void delay(int c)
    {
    	for(time_delay=0;time_delay<c*100;time_delay++)
    	{
    		
    	}
    }
    //电机 PD4,PD5,PD7 PD7端口复用.绿灯PA4 红灯PA5 蜂鸣器 PA6
    void run_begin()
    {
    	if(!(PINC&0x01))
    	{
    		_delay_ms(10);
    		if(!(PINC&0x01))
    		{
    			dis_cstring(1,6,run);
    			if (perameter_1==0)
    			{
    				buzzer();
    				perameter_1=1;
    				
    			}
    			
    			PORTA &=~(1<<4);
    			for (i=1;i<5;i++)
    			{
    				if(!(PINC&bit[i]))
    				{
    					_delay_ms(10);
    					if(!(PINC&bit[i]))
    					{
    						switch (i)
    						{
    							case 1:OCR1A=0;OCR1B=0;while(!(PINC&bit[i])){ PORTD |=(1<<7); delay(100*C);PORTD &=~(1<<7); delay(100*(1-C));};break;
    							case 2:OCR1B=0;OCR1A=0;time_2=100*C; while(!(PINC&bit[i])){ PORTD |=(1<<6); delay(100*C);PORTD &=~(1<<6); delay(100*(1-C));};break;
    							case 3:OCR1B=65535*C;OCR1A=0;break;
    							case 4:OCR1A=65535*C;OCR1B=0;break;	
    							default:break;
    						}
    					}
    					while(!(PINC&bit[i]));
    				}
    						
    			}
    			while(!(PINC&0X01))
    			{
    				for (i=1;i<5;i++)
    				{
    					if(!(PINC&bit[i]))
    					{
    						_delay_ms(10);
    						if(!(PINC&bit[i]))
    						{
    							break;
    						}
    					}
    				}
    				if(i!=5)
    				break;
    			}	
    		}
    	}
    	else if(!(PINC&0x20))
    	{
    		_delay_ms(10);
    		 if(!(PINC&0x20))
    		{
    			moddle=ADCL;
    			moddle+=ADCH*256;
    			moddle=((moddle*100.0)/1024)*5;
    			C=moddle/1024.0;
    			display(1,0,48+(moddle/100%10));
    			display(1,1,'.');
    			display(1,2,48+(moddle/10%10));
    			display(1,3,'V');
    		}
    	}
    	if (perameter==1)
    	{
    			_delay_ms(10);
    			write(0x01,0);
    	}
    	perameter=0; perameter_1=0;	
    	PORTA |=(1<<5);
    	OCR1A=0;
    	OCR1B=0;
    	PORTD &=~(1<<6);
    	PORTD &=~(1<<7);
    }
    	
    
    int main(void)
    {
        /* Replace with your application code */
    	begin();
    	init();
    	
    		//OCR1A=10000;
    	
        while (1) 
        {
    		run_begin();
        }
    }
    
    
    展开全文
  • 通过按键外部中断控制蜂鸣器,当使用PB3作为中断IO口时,不管怎么样都控制不了。仿真发现根本就没有进入外部中断服务函数 void KEY_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2...

    STM32上PB3作为外部中断IO口无法正常使用


    问题描述:

    通过按键外部中断来控制蜂鸣器,当使用PB3作为中断IO口时,不管怎么样都控制不了。仿真发现根本就没有进入外部中断服务函数

    
    
    void KEY_Init(void)
    {
    	
    	GPIO_InitTypeDef GPIO_InitStructure;
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
    
     	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
    	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_3;//PB3
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //PB3设置成输入,
    	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
    }	
    
    void key_exti(void)
    {
     
       	EXTI_InitTypeDef EXTI_InitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
        KEY_Init();	 //	按键端口初始化
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	//使能时钟
    /***************************************************************
    ** 功能:     KEY6初始化函数			
    ** 参数:	  GPIOB3
    ** 返回值:    
    ****************************************************************/		
    		
    	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource3); 
      	EXTI_InitStructure.EXTI_Line=EXTI_Line3;
      	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    	EXTI_InitStructure.EXTI_LineCmd=ENABLE;
      	EXTI_Init(&EXTI_InitStructure);		//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
    		
    	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;			
      	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	
      	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;				
      	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								
      	NVIC_Init(&NVIC_InitStructure);  	  
    }
    
    void EXTI3_IRQHandler(void)
    {
    	Delay(3000);//消抖
    	if(key6==0)	 
    	{			
    	 KEEP_ON;
    		
    	}		 
    	EXTI_ClearITPendingBit(EXTI_Line3);  //清除LINE3上的中断标志位  
    }
    

    原因分析:

    在网上查了很多资料,绝大多数都提到了GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);并且说明了函数调用的顺序要非常严谨

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE)
    我自己尝试了很多次也没有成功

    解决方案:

    在尝试过程中,我无意间将另外一个按键的初始化函数调用了出来,然后PB3突然就可以正常使用了!!!!

    void KEY_Init(void)
    {
    	
    	GPIO_InitTypeDef GPIO_InitStructure;
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
    	
     	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
    	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_1;//PA1
    	GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU; //设置成上拉输入
     	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA1
    
    	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_3;//PB3
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //PB3设置成输入,
    	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
    }
    
    void key_exti(void)
    {
     
       	EXTI_InitTypeDef EXTI_InitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
        KEY_Init();	 //	按键端口初始化
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	//使能时钟
    /***************************************************************
    ** 功能:     KEY1初始化函数			
    ** 参数:	  GPIOA1
    ** 返回值:    
    ****************************************************************/
    
       //GPIOA.1	  
      	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);
      	EXTI_InitStructure.EXTI_Line=EXTI_Line1;
      	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
      	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    	EXTI_InitStructure.EXTI_LineCmd=ENABLE;
      	EXTI_Init(&EXTI_InitStructure);	  	
    	
    	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;			
      	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	
      	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;					
      	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								
      	NVIC_Init(&NVIC_InitStructure);  	  
    /***************************************************************
    ** 功能:     KEY6初始化函数			
    ** 参数:	  GPIOB3
    ** 返回值:    
    ****************************************************************/		
    		
    	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource3); 
      	EXTI_InitStructure.EXTI_Line=EXTI_Line3;
      	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    	EXTI_InitStructure.EXTI_LineCmd=ENABLE;
      	EXTI_Init(&EXTI_InitStructure);		//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
    		
    	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;			
      	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	
      	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;				
      	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								
      	NVIC_Init(&NVIC_InitStructure);  	  
    }
    

    就很莫名其妙,突然就成功了,有大佬给我解释一下嘛


    展开全文
  • 1、自动流水灯:在LED1~LED4上实现自动流水灯,流水间隔时间为200ms/bit,然后通过按键KEY1改变流水灯的速度,每次按键间隔时间增加200ms:当间隔时间增加到1s后(蜂鸣器报警),再次按键间隔时间恢复为初始值200ms。...
  • 通过板载的 4 个按键,控制板载的两个 LED 的亮灭以及蜂鸣器的发声。 一、外部中断是什么? STM32F4 的每个 IO 都可以作为外部中断的中断输入口,这点也是 STM32F4 的强大之处。STM32F407 的中断控制器支持 22个...
  • 目录 本文,在上一章的基础上,将介绍如下内容 外部中断 独立看门狗 ...通过中断的功能,达到通过板载的3个按键控制板载的两个LED的亮灭以及蜂鸣器的发声。 STM32的每个I/O口都可以作为外部中断的...
  • 将 STM32F4 的 IO 口作为外部中断输入,实现通过板载的 4 个按键控制板载的两个 LED 的亮灭以及蜂鸣器的发声 STM32F4外部中断简介   与外部中断有关的代码分布在stm32f4xx_exti.h和stm32f4xx.c文件中。   STM32...
  • 比赛计分电路设计

    2021-01-26 18:00:45
    设计主要由独立按键中断按键控制采集数据到单片机进行处理再通过数码管显示出来,主要研究了数码管及独立按键,对硬件连接方案进行了详尽的介绍,在软件方面算法也进行了论述。 关键词:AT89C51;数码管;独立...
  • 蜂鸣器蜂鸣器主要是起到提醒和报警的作用,当主持人按下开始键时,蜂鸣器响,当有选手犯规时,蜂鸣器也要发出声音,还有就是当倒计时开始时,蜂鸣器就要发出报警的声音。它是利用三极管处于开关状态时的导通与截止...
  • 本次设计采用了在主程序中进行中断等待,并通过按键使计数器溢出,产生中断服务程序,在中断程序中实现叮咚clock()函数的执行、计数器的置初值初始化,然后再次回到主程序中,等待下一次的按键触发中断——触发...
  • (5) 配合按键外部中断控制警报声响的启动与解除。 实验电路: 3在2ms的定时中断中设计实现蜂鸣器发出0.25 KHz、每隔500 ms的断续警报声响。当按下按键时,启动警报声响,并于数码管显示”HELP” ,当再次按下按键时...
  • 实现了ADC采集,间隔定时器唤醒MCU,IIC与EEPROM和RTC时钟的通讯进行对其的控制,以及硬件SPI对OLED的显示控制蜂鸣器输出控制对无源蜂鸣器的叫声控制等功能。 电子密码锁主要功能: 1.实现按键中断功能,中断处...
  • 基于51单片机电子时钟

    万次阅读 多人点赞 2019-01-05 21:39:20
    3. 能实现整时报时的功能(蜂鸣器响) 4. 闹钟模式 5.按键切换模式(模式一:时-分显示,模式二:60秒倒计时) 一、设计思路: 主体: 通过外部中断0来控制mod值;mod=0,1.2,3分别对应时钟模式,调整模式,闹钟设置...
  • 低功耗功能:通过按键中断或1秒计时中断唤醒。连续10秒无操作时,自动进入低功耗状态 按键设定功能:通过MIN,SEC按键进行计时时间的设定,最大值为99分59秒。通过START/STOP按键,开启与暂停倒计时功能。 LCD显示功能...
  •  3.25 INT0中断控制LED  3.26 INT0及INT1中断计数  3.27 TIMER0控制单只LED闪烁  3.28 TIMER0控制流水灯  3.29 TIMER0控制4只LED滚动闪烁  3.30 T0控制LED实现二进制计数  3.31 TIMER0与TIMER1控制条形LED  ...
  • msp430 程序集合

    热门讨论 2009-08-23 12:17:37
    (4)4×1键盘4:控制蜂鸣器 5、4×4矩阵键盘实验 (1)4×4键盘1:行列扫描数码管显示 (2)4×4键盘2:行列扫描1602液晶显示 (3)4×4键盘3:控制LED蜂鸣器 6、1602液晶实验 (1)1602液晶1:动态字符显示 (2)...
  • 单片机计算器

    2012-06-07 20:14:55
     3.25INT0中断控制LED  3.26INT0及INT1中断计数  3.27TIMER0控制单只LED闪烁  3.28TIMER0控制流水灯  3.29TIMER0控制4只LED滚动闪烁  3.30T0控制LED实现二进制计数  3.31TIMER0与TIMER1控制条形LED  3....
  • 25 INT0中断控制LED 26 INT0及INT1中断计数 27 TIMER0控制单只LED闪烁 28 TIMER0控制流水灯 29 TIMER0控制四只LED滚动闪烁 30 TIMER0控制LED二进制计数 31 TIMER0与TIMER1控制条形LED 32 10秒的秒表 33 用计数器中断...
  • ( 4) 4×1 键盘 4:控制蜂鸣器 5、 4×4 矩阵键盘实验 ( 1) 4×4 键盘 1:行列扫描数码管显示 ( 2) 4×4 键盘 2:行列扫描 1602 液晶显示 ( 3) 4×4 键盘 3:控制 LED 蜂鸣器 6、 1602 液晶实验 ( 1) 1602...
  • STM32F4的电压实时检测

    千次阅读 2019-03-06 09:05:04
    本人最近课程设计学习STM32F4系列,在此进行学习...B:通过旋转滑动变阻器改变电压,随着电压的不同,通过点亮LED灯发出警告,当电压达到最大值,蜂鸣器叫。 C:串口输出当前电压值。 二、过程 1、代码风格 考虑该项目...
  • 25 INT0中断控制LED 26 INT0及INT1中断计数 27 TIMER0控制单只LED闪烁 28 TIMER0控制流水灯 29 TIMER0控制四只LED滚动闪烁 30 TIMER0控制LED二进制计数 31 TIMER0与TIMER1控制条形LED 32 10秒的秒表 33 用...
  • 通过按键停止蜂鸣。 键盘控制时钟的启停和时间的设置,键的定义参见上图。F键(启停键)—— 程序启动后,按下该键时钟启动;再次按下该键,暂停计时,显示当前时间。C键(设置键)—— 按下C...
  • 实例48:用计数器T1的中断控制蜂鸣器发出1KHz音频 实例49:用定时器T0的中断实现"渴望"主题曲的播放 实例50-1:输出50个矩形脉冲 实例50-2:计数器T0统计外部脉冲数 实例51-2:定时器T0的模式2测量正脉冲宽度 ...
  • 流水灯 跑马灯,蜂鸣器按键实验 LED大屏幕显示系统 字符型LCD显示 总线接口扩展 RS232实验 SPI与TLC2543接口实验 I2C总线与外部存储器 USB数据采集系统 多任务模拟系统 LCD菜单综合系统设计 交通灯控制系统 无线步...
  • matlab学习

    2018-02-01 15:05:58
    mugege5位移动流水灯和蜂鸣器共鸣 mugege6第六个数码管显示1 mugege7数码管依次点亮以十六进制依次递增 mugege8一三五数码管依次递增,p3^2口中断一号二极管点亮 mugege9 hello megege10数码管从左向右依次以十六...
  • 1、蜂鸣器(由MCU1的P1.0口控制)在不同频率信号的驱动下,会产生不同的声调,通过程序将不同的声调组合起来,就能够产生音乐。 2、利用定时器可以产生不同频率的信号。 3、可以将曲调预先编辑好,给程序查表用。 ...

空空如也

空空如也

1 2
收藏数 39
精华内容 15
关键字:

通过按键中断控制蜂鸣器