本帖最后由 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;
}
}
} |