48、定时器中断程序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18077275/article/details/89322035

1、定时器硬件原理

2、定时器相关的寄存器

3、interrupt.c

#include <s3c2440_soc.h>


/* SRCPND 用来显示哪个中断产生了, 需要清除对应位
 * bit0-eint0
 * bit2-eint2
 * bit5-eint8_23
 */

/* INTMSK 用来屏蔽中断, 1-masked
 * bit0-eint0
 * bit2-eint2
 * bit5-eint8_23
 */

/* INTPND 用来显示当前优先级最高的、正在发生的中断, 需要清除对应位
 * bit0-eint0
 * bit2-eint2
 * bit5-eint8_23
 */

/* INTOFFSET : 用来显示INTPND中哪一位被设置为1
 */

/* 初始化中断控制器 */
typedef void(*irq_func)(int);
irq_func irq_array[32];

void interrupt_init(void)
{
    INTMSK &= ~((1<<0) | (1<<2) | (1<<5));
    INTMSK &= ~(1<<10);  /* enable timer0 int */
}

void register_irq(int irq, irq_func fp)
{
    irq_array[irq] = fp;

    INTMSK &= ~(1<<irq);
}


/* 读EINTPEND分辨率哪个EINT产生(eint4~23)
 * 清除中断时, 写EINTPEND的相应位
 */

 void key_eint_irq(int irq)
 {
     unsigned int val = EINTPEND;
     unsigned int val1 = GPFDAT;
     unsigned int val2 = GPGDAT;
     
     if (irq == 0) /* eint0 : s2 控制 D12 */
     {
         if (val1 & (1<<0)) /* s2 --> gpf6 */
         {
             /* 松开 */
             GPFDAT |= (1<<6);
         }
         else
         {
             /* 按下 */
             GPFDAT &= ~(1<<6);
         }
         
     }
     else if (irq == 2) /* eint2 : s3 控制 D11 */
     {
         if (val1 & (1<<2)) /* s3 --> gpf5 */
         {
             /* 松开 */
             GPFDAT |= (1<<5);
         }
         else
         {
             /* 按下 */
             GPFDAT &= ~(1<<5);
         }
         
     }
     else if (irq == 5) /* eint8_23, eint11--s4 控制 D10, eint19---s5 控制所有LED */
     {
         if (val & (1<<11)) /* eint11 */
         {
             if (val2 & (1<<3)) /* s4 --> gpf4 */
             {
                 /* 松开 */
                 GPFDAT |= (1<<4);
             }
             else
             {
                 /* 按下 */
                 GPFDAT &= ~(1<<4);
             }
         }
         else if (val & (1<<19)) /* eint19 */
         {
             if (val2 & (1<<11))
             {
                 /* 松开 */
                 /* 熄灭所有LED */
                 GPFDAT |= ((1<<4) | (1<<5) | (1<<6));
             }
             else
             {
                 /* 按下: 点亮所有LED */
                 GPFDAT &= ~((1<<4) | (1<<5) | (1<<6));
             }
         }
     }
 
     EINTPEND = val;
 }


 void handle_irq_c(void)
{
    /* 分辨中断源 */
    int bit = INTOFFSET;

    /* 调用对应的处理函数 */
    irq_array[bit](bit);
    
    /* 清中断 : 从源头开始清 */
    SRCPND = (1<<bit);
    INTPND = (1<<bit);    
}

 /* 初始化按键, 设为中断源 */
void key_eint_init(void)
{
    /* 配置GPIO为中断引脚 */
    GPFCON &= ~((3<<0) | (3<<4));   //  0  2
    GPFCON |= ((2<<0) | (2<<4));   /* S2,S3被配置为中断引脚 */

    //GPGCON &= ~((3<<6) | (3<<11));  //          
    //GPGCON |= ((2<<6) | (2<<11));   /* S4,S5被配置为中断引脚 */
    GPGCON &= ~((3<<6) | (3<<22));  // 11  19        
    GPGCON |= ((2<<6) | (2<<22));   /* S4,S5被配置为中断引脚 */

    /* 设置中断触发方式: 双边沿触发 */
    EXTINT0 |= (7<<0) | (7<<8);     /* S2,S3 */
    EXTINT1 |= (7<<12);             /* S4 */
    EXTINT2 |= (7<<12);             /* S5 */

    /* 设置EINTMASK使能eint11,19 eint0、2直通cpu*/    
    EINTMASK &= ~((1<<11) | (1<<19));

    register_irq(0, key_eint_irq);
    register_irq(2, key_eint_irq);
    register_irq(5, key_eint_irq);
}

4、main.c


#include <s3c2440_soc.h>
#include <uart.h>
#include  <my_printf.h>
#include <init.h>
#include <interrupt.h>
#include <timer.h>


char g_Char = 'A';
char g_Char3 = 'a';
const char g_Char2 = 'B';
int g_A = 0;
int g_B;

int main(void)
{
    led_init();
   // interrupt_init();  /* 初始化中断控制器 */
    key_eint_init();   /* 初始化按键, 设为中断源 */    
    timer_init();

    puts("\n\rg_A = ");
    printHex(g_A);
    puts("\n\r");
    
    while (1)
    {
        putchar(g_Char);
        g_Char++;
    
        putchar(g_Char3);
        g_Char3++;
        delay(1000000);
    }
    
        
    return 0;

}


5、timer.c


#include "s3c2440_soc.h"

void timer_irq(void)
{
    /* 点灯计数 */
    static int cnt = 0;
    int tmp;

    cnt++;

    tmp = ~cnt;
    tmp &= 7;
    GPFDAT &= ~(7<<4);
    GPFDAT |= (tmp<<4);
}

void timer_init(void)
{
    /* 设置TIMER0的时钟 */
    /* Timer clk = PCLK / {prescaler value+1} / {divider value} 
                 = 50000000/(99+1)/16
                 = 31250
     */
    TCFG0 = 99;  /* Prescaler 0 = 99, 用于timer0,1 */
    TCFG1 &= ~0xf;
    TCFG1 |= 3;  /* MUX0 : 1/16 */

    /* 设置TIMER0的初值 */
    TCNTB0 = 15625;  /* 0.5s中断一次 */

    /* 加载初值, 启动timer0 */
    TCON |= (1<<1);   /* Update from TCNTB0 & TCMPB0 */

    /* 设置为自动加载并启动 */
    TCON &= ~(1<<1);
    TCON |= (1<<0) | (1<<3);  /* bit0: start, bit3: auto reload */

    /* 设置中断 */
    register_irq(10, timer_irq);
}


 

猜你喜欢

转载自blog.csdn.net/qq_18077275/article/details/89322035