一.从文档中我们可以知道,mini2440一共有5个定时器.如下图所示:
其中定时器0,1,2,3四个寄存器是有输出引脚的,是和蜂鸣器结合在一起的。定时器4是没有输出引脚的,所以定时器4是专门用来计时用的。
其中定时器0,1公用一个8位分频器,定时器2,3,4公用一个8位的分频器。
T = 次数 * 周期 = 1/fre(pwm) 其中:周期=1/f = 1/(50M/(prescaler+1)/(divider value).
关于定时器4的有关配置方法:
一.从上面的原理图可以知道,先输入一个PCLK(大小为50M,在启动代码中已经设置好了)。
然后经过一个8位分频器,值可以在(0~255之间)。再经过一个clock divider(值可以是2,4,8,16)
所以首先我们应该配置分频器和divider value(对应的寄存器是TCFG0,TCFG1).
二.我们需要配置
设置次数
三.配置:
首先,我们需要设置manual update bit 和 auto reload bit (TCON)
然后,我们需要设置定时器中断了,中断方法见中断总结的文档。
其次,我们需要设置 set start bit 和 clear the manual update bit
这样,我们设置一个定时器就算完成了。
关于定时器0的设置方法:
1.首先,我们需要设置相应的输出引脚(由原理图中可以知道)。
2.其次,我们需要设置分频器的值和divider value .(TCFG0,TCFG1).
3.再次,我们需要配置次数的初始值和比较值,其中比较值决定了电平的反转时刻。
4.然后,我们需要设置manual update bit 和 auto reload bit (TCON)
再是我们需要配置定时器中断了,中断方法见中断配置的相关文档了,
最后就是启动我们的定时器了,需要配置的是 set start bit 以及 clear the manual update bit.
这样,定时器0也就配置好了。
定时器相关的代码如下:
/************************************************
NAME : PWM.C
DESC :
Revision: 2015.8.18 ver 0.0
************************************************/
#include "pwm.h"
#include "led.h"
#include "music.h"
#include "uart.h"
volatile unsigned int div=0;
volatile unsigned int div10ms=0;
volatile unsigned int t=0;
volatile unsigned int t1=0;
extern void Delay_MS( unsigned int time);
volatile int count = 0;
//音调频率表
unsigned Syllable_freq[30]={
262,294,330,349,392,440,494,50000000,0,0,
523,587,659,698,784,880,988,0,0,0,
1046,1175,1318,1397,1568,1760,1976,0,0,0
};
void delayns(volatile int ns) //延时200ms
{
t=(int)ns*200;
while(1)
{
if(t==0)
{
break;
}
}
}
void delayns1(volatile int ns) //延时1s
{
t1=(int)ns*1000;
while(1)
{
if(t==0)
{
break;
}
}
}
/***********************************************
Function name : timer4_irq
Description : 定时器4 中断服务函数
Input parameter : none
Return : none
Others : none
*************************************************/
static void __irq timer4_irq(void)
{
rSRCPND |= BIT_TIMER4;
rINTPND |= BIT_TIMER4;
t--;
t1--;
div++;
switch(div%2)
{
case 0:
timer10ms();
break;
case 1:
break;
default:
break;
}
}
/***********************************************
Function name : time4_init
Description : 定时器4 初始化
Input parameter : none
Return : none
Others : none
*************************************************/
void time4_init(unsigned int msec) //传入1
{
volatile unsigned temp;
temp=rTCFG0;
temp&=~(0xf<<8);
temp|=0xff<<8;
rTCFG0=temp;
temp=rTCFG1;
temp&=~(0xf<<20|0xf<<16);
temp|=0x2<<16;
rTCFG1=temp;//使用8分之1频
msec=(msec==0)?1:msec; //合法边界数值判断
rTCNTB4 = (50000*msec)>>11;//设定定时计数缓冲器数值
temp=rTCON;
temp&=~(0x7<<20); //初始化
temp|=1<<22|1<<21;//可以自动重载可以重新定义TCNTB4的数值
rTCON=temp;
rSRCPND|=BIT_TIMER4;
rINTPND|=BIT_TIMER4;
rINTMOD &=~BIT_TIMER4;
rINTMSK &=~BIT_TIMER4;
pISR_TIMER4 = (unsigned int)timer4_irq;
temp = rTCON;
temp &=~(0x7<<20);
temp|=1<<22|1<<20;
rTCON=temp;
}
/***********************************************
Function name : timer10ms
Description : 定时器处理函数
Input parameter : none
Return : none
Others : none
*************************************************/
void timer10ms()
{
(div10ms<=4)?(div10ms++):(div10ms=0); //0 1 2 3 4
switch(div10ms)
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
default:
break;
}
}
/***********************************************
Function name : timer0_irq
Description : 定时器0 中断服务函数
Input parameter : none
Return : none
Others : none
*************************************************/
static void __irq timer0_irq(void)
{
rSRCPND |= BIT_TIMER0;
rINTPND |= BIT_TIMER0;
}
/***********************************************
Function name : time0_stop
Description : 关闭定时器0
Input parameter : none
Return : none
Others : none
*************************************************/
void time0_stop()
{
volatile int temp;
//1.停止寄存器
rTCON &= ~(0x1<<0);
//2.configure GPB0 to output and low level disable the pull up function
temp = rGPBCON;
temp &=~(0x3<<0);
temp |= (0x1<<0);
rGPBCON =temp;
rGPBDAT &=~(0x1<<0);
rGPBUP |=(0x1<<0);
}
/***********************************************
Function name : time0_init
Description : 定时器0 初始化
Input parameter : none
Return : none
Others : timer0 init
*************************************************/
void time0_init(unsigned int nes)
{
volatile unsigned temp;
temp=rGPBCON;
temp&=~(0x3);
temp|=0x2;
rGPBCON=temp;
temp=rGPBUP;
temp&=0;
rGPBUP=temp;
temp=rTCFG0;
temp&=~(0xf);
temp|=0xff;
rTCFG0=temp;
temp=rTCFG1;
temp&=~(0xf<<20|0xf);//初始化
temp|=0x2;
rTCFG1=temp;//使用8分之1频
rTCNTB0 = (50000000/nes)>>11;
rTCMPB0 = (50000000/nes)>>13;
temp=rTCON;
temp&=~(1<<3|1<<2|1<<1|1);
temp|=1<<3|1<<1;
rTCON=temp;
rSRCPND|=BIT_TIMER0;
rINTMOD &=~BIT_TIMER0;
rINTMSK &=~BIT_TIMER0;
rINTPND|=BIT_TIMER0;
pISR_TIMER0 = (unsigned int)timer0_irq;
temp=rTCON;
temp&=~(0xf);
temp|=1<<3|1;
rTCON=temp;
}
/***********************************************
Function name : play_music
Description : 音乐播放函数
Input parameter : none
Return : none
Others : none
*************************************************/
void play_music(void)
{
unsigned char ch;
ch=uart_getc();
while(1)
{
switch(ch)
{
case 'q':
{
time0_stop();
time0_init(262);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'w':
{
time0_stop();
time0_init(294);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'e':
{
time0_stop();
time0_init(330);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'r':
{
time0_stop();
time0_init(349);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 't':
{
time0_stop();
time0_init(392);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'y':
{
time0_stop();
time0_init(440);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'u':
{
time0_stop();
time0_init(494);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'a':
{
time0_stop();
time0_init(523);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 's':
{
time0_stop();
time0_init(587);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'd':
{
time0_stop();
time0_init(659);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'f':
{
time0_stop();
time0_init(698);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'g':
{
time0_stop();
time0_init(784);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'h':
{
time0_stop();
time0_init(880);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'j':
{
time0_stop();
time0_init(988);
delayns(1);
time0_init(Syllable_freq[7]); // 1046,1175,1318,1397,1568,1760,1976
break;
}
case 'z':
{
time0_stop();
time0_init(1046);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'x':
{
time0_stop();
time0_init(1175);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'c':
{
time0_stop();
time0_init(1318);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'v':
{
time0_stop();
time0_init(1397);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'b':
{
time0_stop();
time0_init(1568);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'n':
{
time0_stop();
time0_init(1760);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
case 'm':
{
time0_stop();
time0_init(1976);
delayns(1);
time0_init(Syllable_freq[7]);
break;
}
default:
break;
}
ch=uart_getc();
}
}