ARM9
S3C2440的寄存器特别多,这也是它和单片机不同处之一,对ARM的编程主要也是对寄存器的操作,可是寄存器多了以后,就很容易忘记对某个寄存器的设置,如果能够总结一下寄存器配置的步骤,使得其有章可循,那么应用的时候就可以对号入座了。如果长时间不去使用ARM的话,再次使用的时候重新翻看烦人的芯片用户手册,显得就浪费时间了,这样,趁着熟悉的时候记录下这些要点,以后稍加翻看就能唤起记忆,这也是自己写这些博客的缘由。
定时器初始化配置步骤主要有:
1、rTCFG0和rTCFG1的设置
首先要设置定时器的时钟频率,
TimerinputclockFrequency=PCLK/{prescalervalue+1}/{dividervalue}
TCFG0的[7:0]保存的是定时器0和定时器1的prescalervalue,[15:8]保存的是定时器2和定时器3以及定时器4的prescalervalue。
TCFG1从低位开始每四位表示dividervalue。
0000=1/2
0001=1/4
0010=1/8
0011=1/16
01xx=ExternalTCLK0
比如:rTCFG0=49;//pclk/(49+1)
rTCFG1=0x03;//16分频=62500HZ
2、rTCNTBx和rTCMPBx的设置
设置TCON启动定时器x(x表示0-4,2440有5个16位的定时器,定时器0-3有PWM功能,有输出引脚,定时器4没有输出引脚),这时TCNTBx→TCNTx,TCMPBx→TCMPx,在定时器的工作频率下,TCNTx开始减1,其值可以读取TCNTOx获取。当TCNTx=TCMPx时,定时器x的输出管脚TOUTx反转,TCNTx继续减1计数,当TCNTx=0时,其输出管脚TOUTx再次反转,并触发定时器x的中断。所以作为中断用的计时值由rTCNTBx确定,用作PWM功能时,PWM的频率由rTCNTBx确定,占空比由rTCMPBx确定,占空比等于rTCMPBx/rTCNTBx。TOUTx(x=0~3)外接蜂鸣器控制蜂鸣器的频率或者外接LED灯控制LED灯的亮度,占空比越大,蜂鸣器频率越大,LED灯越亮。如果不作为PWM用途时,一般将rTCMPB0设置为0。
比如:rTCNTB0=62500/2;//TCNTB0[15:0]=计数值
rTCMPB0=0;
3、rTCON的设置
TCON寄存器控制着定时器的启动(1表示启动)、是否自动装载初值(TCNTBx和TCMPBx,1表示自动装载)、PWM死区是否启动(,1表示启用死区)、TOUTx反转启动(1表示允许反转)。
如:rTCON=0x09;//,启动定时器,并允许重载TCNTB0、TCMPB0
4、清IRQ或FIQ中断,如调用ClearPending(BIT_TIMER0)函数。
对于子中断使用ClearSubPending(intbit)。
BIT_TIMER0在2440addr.h中的宏定义是
#defineBIT_TIMER0(0x1<10)
ClearPending函数的在头文件2440addr.h中的定义为:
__inlinevoidClearPending(intbit)
{
registeri;
rSRCPND=bit;
rINTPND=bit;
i=rINTPND;
}
__inlinevoidClearSubPending(intbit)
{
registeri;
rSUBSRCPND=bit;
i=rINTPND;
ClearPending和ClearSubPending是内联函数,编译时,类似宏替换,使用函数体替换调用处的函数名而不是去调用这两个函数,用增加程序代码大小的代价换取程序运行的效率,因为函数调用需要保护现场,入栈和出栈耗用CPU时间。
SRCPND、SUBSRCPND、INTPND相应位为1表示有相应的中断发生,SRCPND、SUBSRCPND可以有多位同时置1,表示有多个中断发生,但是INTPND寄存器是经过优先级裁决后的,所以同一时间只能有一位为1。
另外值得注意的是SRCPND、INTPND、SUBSRCPND三个挂起寄存器的清零不是直接写入0,而是将对应的位置1,这个一定要注意,当然了,编程的时候直接调用这两个函数就行,它已经包含在头文件中,但是了解这个特殊之处还是很有意思的。
5、rEXTINTx(P301)、rEINTPEND(P306)、rEINTMASK(P305)的设置
这三种寄存器是对外部中断而言的,定时器是内部中断,定时器初始化无需对这些寄存器配置,当用到按键、开关等外部中断就要对这几个寄存器配置。
EXTINTx寄存器用于设置25个外部中断的中断触发方式,000=低电平,001高电平,01x=下降沿,0x上升沿,11x边沿触发Bothedgetriggered。比如设置外部中断11,13-15中断触发方式为下降沿触发。
rEXTINT1&=~(7<12|7<20|7<24|7<28);
rEXTINT1|=(2<12|2<20|2<24|2<28);
EINTPEND寄存器相应位为1表示相应的外部中断发生,0表示没有相应中断发生,初始化中要对该寄存器清零,防止原有中断干扰,清零的方式和SRCPND、SUBSRCPND、INTPND三个寄存器的清零方式一样,向相应位写入1,但是没有类似ClearPending的函数调用,必须自己写。比如外部中断11,13-15中断挂起寄存器清零:
rEINTPEND|=(1<11)|(1<13)|(1<14)|(1<15);
EINTMASK寄存器0表示允许对应位中断,1表示禁止对应位中断,默认是禁止的,如外部中断11,13-15中断允许,相应位写入0
rEINTMASK&=~((1<11)|(1<13)|(1<14)|(1<15));
另外也要使用ClearPending(BIT_EINT1|BIT_EINT2|BIT_EINT8_23)清中断挂起寄存器,注意,刚才EINTPEND是清次中断,EXTINT8-23都递属于IRQ的中断号5,所以这里清的是主IRQ中断。