打印

ARM裸奔系列之—定时器中断

[复制链接]
2665|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zbb564833642|  楼主 | 2012-2-16 20:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 zbb564833642 于 2012-2-16 20:26 编辑

这两天 我对s3c440a 的芯片手册中的 定时器和中断这部分进行了比较系统的学习 。。以下是我的学习感悟。。此后的学习中我会多和大家分享的。。
其实定时器的设置是非常简单的,只需设置 中断源挂起寄存器SRCPND,中断屏蔽寄存器INTMSK,中断挂起寄存器INTPND,根据需要决定是否设置外部中断控制寄存器(默认设置为低电平触发)EXTINTn。。。。。 如需要设置PWM 则继续设置定时器配置寄存器0 TCFG0(设置预分频值,只能取0—255) , 定时器配置寄存器1 TCFG1(分频值,只能取2,4,6,8,16)  其变换公式为: 定时器输入时钟频率=PCLK/(预分频值+1)/分频值;
定时器计数缓冲寄存器TCNTBn(设置计数的最大值),比较缓冲寄存器TCMPBn(当TCNTN的值等于该值时,电平翻转);
然后设置定时器控制寄存器TCON(死区无效,自动装载,电平反转,手动更新,定时器 都 开启),最后将寄存器TCON中的手动更新位置零(手册上这么写的), 此时 ,定时器就设定好了..
现将源代码贴出,原代码如下:
/*
实现功能: 通过改变脉宽来改变蜂鸣器发声的频率
并且四个灯来表示 蜂鸣器频率的强弱 ,最高时LED全亮,最低时LED全灭
。用1个按键来分别暂停蜂鸣器和重新开启蜂鸣器:
注意 : 此定时器0为计数器 ,不具备定时器‘中断 功能
*/
#define _ISR_STARTADDRESS 0x33ffff00

#define U32 unsigned int
typedef unsigned char BOOL;     //类型名   不是太懂 。。。
//???????????????????????????????????????????
#define pISR_EINT0            (*(unsigned *)(_ISR_STARTADDRESS+0x20))
#define pISR_EINT1            (*(unsigned *)(_ISR_STARTADDRESS+0x24))

#define rSRCPND     (*(volatile unsigned *)0x4a000000)     //Interrupt request status
#define rINTMSK     (*(volatile unsigned *)0x4a000008)      //Interrupt mask control
#define rINTPND     (*(volatile unsigned *)0x4a000010)      //Interrupt request status

#define rGPBCON    (*(volatile unsigned *)0x56000010)      //Port B control
#define rGPBDAT    (*(volatile unsigned *)0x56000014)       //Port B data
#define rGPBUP     (*(volatile unsigned *)0x56000018) //Pull-up control B

#define rGPFCON    (*(volatile unsigned *)0x56000050)       //Port F control

#define rEXTINT0   (*(volatile unsigned *)0x56000088) //External interrupt control register 0

#define rTCFG0  (*(volatile unsigned *)0x51000000)      //Timer  configuration
#define rTCFG1  (*(volatile unsigned *)0x51000004)      //Timer  configuration
#define rTCON   (*(volatile unsigned *)0x51000008)      //Timer control
#define rTCNTB0 (*(volatile unsigned *)0x5100000c)       //Timer count buffer 0
#define rTCMPB0 (*(volatile unsigned *)0x51000010)      //Timer compare buffer 0

BOOL stop;
int num;
void delay(int a)   
{
       int k;
       for(k=0;k<a;k++)
              ;
}
static void __irq key1_ISR(void)  //外部中断控制蜂鸣器响与不响
{
rSRCPND=rSRCPND | 0x1;    // 清零
rINTPND= rINTPND| 0x1;
num++;
switch(num)
{
  case 1: rTCON &= ~0x8;          //   rTCON|=0xe0; 该语句无效
  break;       ////???????????????
  case 2:// rTCON|=0xe0;
       rTCON|=0xf;
       rTCON &= ~0x2 ;
       num=0;
  break;  
  default:rTCON &= ~0x8;                // 该语句无效  rTCON|=0xe0;
    num=0;
  break;
}

  
}

void Main()
{
int freq;
freq=1000;
num=0;     //B0为TOUT0,B5~B8为输出,给LED ,  10为 TOUT0(定时器0)
rGPBCON=0x015402; //禁止使能上拉  0000 0001 0101 0100 0000 0010
    rGPBUP=0x1e1; //0001 1110 0001

   
       rSRCPND=rSRCPND | 0x3;// 中断源挂起寄存器,
  rINTMSK=rINTMSK & (~0x3);// 中断屏蔽寄存器
  rINTPND= rINTPND| 0x3; //中断挂起寄存器
rEXTINT0=rEXTINT0 | 0x22;//设置 外部中断控制寄存器 的触发方式 为下降沿触发

rGPFCON=rGPFCON |0x2; // 按键 中断设置

//rTCFG0 &= 0xFFFF00;  //??????
rTCFG0|=0x46; // 预分频值 70
    rTCFG1=0x0; // 1/2 因为PCLK为50MHz,所以50MHz/70/2=?kHz
    rTCNTB0=10000;//  设置定时器0的 计数器缓冲器的值(既最大值)
    rTCMPB0=freq;//    设置定时器比较缓冲器的值(当TCNTN的值等于该值时,电平翻转)
   
   // rTCON|=0xe0;
    rTCON|=0xf;   //死区无效,自动装载,电平反转,手动更新,定时器 都 开启
    rTCON &= ~0x2 ;   //   手动更新位清零,PWM开始工作              pISR_EINT0 = (U32) key1_ISR;
   
   
    while(1)
    {
     for(; freq<=9900;)
     {
       freq=freq+40;
       rTCMPB0 = freq;  //  忘从新赋值
       delay(30000);  //  每发出一个频率的 波时 延时该波 的时间
      
       if(freq == 1040)
              rGPBDAT = ~0x1e0;
             if(freq == 3000)
              rGPBDAT = ~0xe0;
             if(freq == 5000)
                    rGPBDAT = ~0x60;
             if(freq == 7000)
                    rGPBDAT = ~0x20;
             if(freq > 9000)
                    rGPBDAT = ~0x0;
     
     
     }
     if(freq>9900)
     {
      delay(10000);
      delay(10000);
      freq=1000;
     }
        
    }
   
}

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

317

帖子

2

粉丝