×
单片机 > 单片机程序设计 > 详情

S3C2410 按键控制LED(中断)

发布时间:2020-09-03 发布时间:
|

一、开发环境


1、硬件平台:UP-TECH2410DVK1.1


2、主机:PC+eclipse


二、相关原理图



LED1-->GPC5


LED2-->GPC6


LED3-->GPC7


KEY1-->EINIT3


KEY2-->EINIT5


KEY3-->EINIT9


三、基本原理


通过按键的按下而触发中断,从而进行中断处理,进而实现相应功能(如闪烁LED),然后退出中断。


如何判断按键被按下:


以KEY1为例,未按下时,因为EINT3连接的是VDD,所以为高电平,当按键发生,EINT3连接的是GND,接地,此时为低电平。

通过芯片手册可查到EINT3 、5、9连接的为复用管脚,需要先配置对应的GPIOCON,让其为中断引脚。


四、代码部分


1、head.s


@******************************************************************************

@ File:head.S

@ 功能:初始化,设置中断模式、管理模式的栈,设置好中断处理函数

@******************************************************************************       

   

.extern     main

.text 

.global _start 

_start:

@******************************************************************************       

@ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用

@******************************************************************************       

    b   Reset

 

@ 0x04: 未定义指令中止模式的向量地址

HandleUndef:

    b   HandleUndef 

 

@ 0x08: 管理模式的向量地址,通过SWI指令进入此模式

HandleSWI:

    b   HandleSWI

 

@ 0x0c: 指令预取终止导致的异常的向量地址

HandlePrefetchAbort:

    b   HandlePrefetchAbort

 

@ 0x10: 数据访问终止导致的异常的向量地址

HandleDataAbort:

    b   HandleDataAbort

 

@ 0x14: 保留

HandleNotUsed:

    b   HandleNotUsed

 

@ 0x18: 中断模式的向量地址

    b   HandleIRQ

 

@ 0x1c: 快中断模式的向量地址

HandleFIQ:

    b   HandleFIQ

 

Reset:                  

    ldr sp, =4096           @ 设置栈指针,以下都是C函数,调用前需要设好栈

    bl  disable_watch_dog   @ 关闭WATCHDOG,否则CPU会不断重启

    

    msr cpsr_c, #0xd2       @ 进入中断模式

    ldr sp, =3072           @ 设置中断模式栈指针

 

    msr cpsr_c, #0xd3       @ 进入管理模式

    ldr sp, =4096           @ 设置管理模式栈指针,

                            @ 其实复位之后,CPU就处于管理模式,

                            @ 前面的“ldr sp, =4096”完成同样的功能,此句可省略

 

    bl  init_led            @ 初始化LED的GPIO管脚

    bl  init_irq            @ 调用中断初始化函数,在init.c中

    msr cpsr_c, #0x5f       @ 设置I-bit=0,开IRQ中断

    

    ldr lr, =halt_loop      @ 设置返回地址

    ldr pc, =main           @ 调用main函数

halt_loop:

    b   halt_loop

 

HandleIRQ:

    sub lr, lr, #4                  @ 计算返回地址

    stmdb   sp!,    { r0-r12,lr }   @ 保存使用到的寄存器

                                    @ 注意,此时的sp是中断模式的sp

                                    @ 初始值是上面设置的3072

    

    ldr lr, =int_return             @ 设置调用ISR即EINT_Handle函数后的返回地址  

    ldr pc, =EINT_Handle            @ 调用中断服务函数,在interrupt.c中

int_return:

    ldmia   sp!,    { r0-r12,pc }^  @ 中断返回, ^表示将spsr的值复制到cpsr

    

2、init.s

/*

 * init.c: 进行一些初始化

 */ 

 

#include "s3c24xx.h"

 

/*

 * LED1,LED2,LED4对应GPF4、GPF5、GPF6

 */

#define GPF4_out (1<

#define GPF5_out (1<

#define GPF6_out (1<

 

#define GPF4_msk (3<

#define GPF5_msk (3<

#define GPF6_msk (3<

 

/*

 * S2,S3,S4对应GPF0、GPF2、GPG3

 */

#define GPF0_eint     (0x2<

#define GPF2_eint     (0x2<

#define GPG3_eint     (0x2<

 

#define GPF0_msk    (3<

#define GPF2_msk    (3<

#define GPG3_msk    (3<

 

/*

 * 关闭WATCHDOG,否则CPU会不断重启

 */

void disable_watch_dog(void)

{

    WTCON = 0;  // 关闭WATCHDOG很简单,往这个寄存器写0即可

}

 

void init_led(void)

{

    // LED1,LED2,LED4对应的3根引脚设为输出

    GPFCON &= ~(GPF4_msk | GPF5_msk | GPF6_msk);

    GPFCON |= GPF4_out | GPF5_out | GPF6_out;

}

 

/*

 * 初始化GPIO引脚为外部中断

 * GPIO引脚用作外部中断时,默认为低电平触发、IRQ方式(不用设置INTMOD)

 */ 

void init_irq( )

{

    // S2,S3对应的2根引脚设为中断引脚 EINT0,ENT2

    GPFCON &= ~(GPF0_msk | GPF2_msk);

    GPFCON |= GPF0_eint | GPF2_eint;

 

    // S4对应的引脚设为中断引脚EINT11

    GPGCON &= ~GPG3_msk;

    GPGCON |= GPG3_eint;

    

    // 对于EINT11,需要在EINTMASK寄存器中使能它

    EINTMASK &= ~(1<<11);

        

    /*

     * 设定优先级:

     * ARB_SEL0 = 00b, ARB_MODE0 = 0: REQ1 > REQ3,即EINT0 > EINT2

     * 仲裁器1、6无需设置

     * 最终:

     * EINT0 > EINT2 > EINT11即K2 > K3 > K4

     */

    PRIORITY = (PRIORITY & ((~0x01) | (0x3<<7))) | (0x0 << 7) ;

 

    // EINT0、EINT2、EINT8_23使能

    INTMSK   &= (~(1<<0)) & (~(1<<2)) & (~(1<<5));

}

 

 

 

 

3、interrupt.c

#include "s3c24xx.h"

 

void EINT_Handle()

{

    unsigned long oft = INTOFFSET;

    unsigned long val;

    

    switch( oft )

    {

        // S2被按下

        case 0: 

        {   

            GPFDAT |= (0x7<<4);   // 所有LED熄灭

            GPFDAT &= ~(1<<4);      // LED1点亮

            break;

        }

        

        // S3被按下

        case 2:

        {   

            GPFDAT |= (0x7<<4);   // 所有LED熄灭

            GPFDAT &= ~(1<<5);      // LED2点亮

            break;

        }

 

        // K4被按下

        case 5:

        {   

            GPFDAT |= (0x7<<4);   // 所有LED熄灭

            GPFDAT &= ~(1<<6);      // LED4点亮                

            break;

        }

 

        default:

            break;

    }

 

    //清中断

    if( oft == 5 ) 

        EINTPEND = (1<<11);   // EINT8_23合用IRQ5

    SRCPND = 1<

    INTPND = 1<

}


4、main.c

int main()

{

    while(1);

    return 0;

}

5、s3c24xx.h

/* WOTCH DOG register */

#define     WTCON           (*(volatile unsigned long *)0x53000000)

 

/* SDRAM regisers */

#define     MEM_CTL_BASE    0x48000000

#define     SDRAM_BASE      0x30000000

 

/* NAND Flash registers */

#define NFCONF              (*(volatile unsigned int  *)0x4e000000)

#define NFCMD               (*(volatile unsigned char *)0x4e000004)

#define NFADDR              (*(volatile unsigned char *)0x4e000008)

#define NFDATA              (*(volatile unsigned char *)0x4e00000c)

#define NFSTAT              (*(volatile unsigned char *)0x4e000010)

 

/*GPIO registers*/

#define GPBCON              (*(volatile unsigned long *)0x56000010)

#define GPBDAT              (*(volatile unsigned long *)0x56000014)

 

#defi

关键字:S3C2410  按键控制  LED  中断 


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
MSP430F5529 上手小例程2