537

帖子

0

TA的资源

五彩晶圆(初级)

21
 
善于写总结的人,不错,很详细的资料!应该向你好好学习!
此帖出自NXP MCU论坛
 

回复

60

帖子

0

TA的资源

一粒金砂(初级)

22
 
不错~
此帖出自NXP MCU论坛
 
 
 

回复

6366

帖子

4920

TA的资源

版主

23
 

本节内容是利用LPC1343内部计数/定时器得到一个准确的时间间隔。比较简单,但仍求详细。

以下是一些官方描述:

1Description

每一个计数/定时器的设计是用以对设备时钟(PCLK)或者外部提供的时钟进行其时钟周期数的计量,同时基于四个匹配寄存器中存放着既定的时间值,可以有选择地产生中断或者履行其他既定的操作。每一个计数/定时器还包含一个输入捕获环节可以在输入信号转变的时候捕获计数器值,同样可以选择产生一个中断。

PWM模式中,三个匹配寄存器用以提供单边沿控制匹配输出引脚的PWM输出。另外一个寄存器控制PWM的占空比。

提醒:

两个32位定时器在功能上完全一样,它们只有设备基地址上的区别。

2Features

带有32位可编程预分频器的两个32位计数/定时器

计数/定时模式

各拥有一个捕获通道,当输入信号变化之时可以对时间值进行快照。一次捕获时间可以选择产生一次中断。

四个32位匹配寄存器可以做到:

   当可选匹配中断产生时继续计数器

   当可选匹配中断产生时停止计数器

   当可选匹配中断产生时复位计数器

      四个对应匹配寄存器的外部输出引脚可以做到:

匹配时置为低电平

匹配时置为高电平

匹配时产生跳变

匹配时无操作

      每一个定时器,多达四个匹配寄存器可以设置为PWM模式,允许多达三个匹配寄存器输出单边沿控制的PWM输出。

3Applications

通过既定时间间隔执行既定时间

通过输入捕获实现脉宽解调

定时器自由运行

通过输出匹配实现脉宽解调

以上是关于LPC134332位定时器的简要描述,其实定时器本身就不应该是一个太复杂的东西。这在我们学习51单片机的时候就应该知道了。下面是定时器的一个结构图:

从这个图,我们可以看出定时器的运行过程:

1、   时钟进入预分频器后供给TIMER COUNTER

2、   TIMER COUNTER计数

3、   TIMER COUNTER中数值与MATCH REGISTER中数值相等时……

4、   CONTROL单元进行相应操作,而CONTROL的反应取决于围绕在它周围的一系列寄存器;

我们就跟着这个思路,来亲自看看程序是怎么做的,NXP带给我们的第一个演示程序,就是32位定时器产生固定时间间隔的功能,下面是稍有改动之后的主函数:

[ 本帖最后由 tiankai001 于 2010-5-20 08:02 编辑 ]
此帖出自NXP MCU论坛
 
 
 

回复

4997

帖子

19

TA的资源

裸片初长成(初级)

24
 
继续学习!!!!!!!!!!!
此帖出自NXP MCU论坛
 
 
 

回复

720

帖子

0

TA的资源

纯净的硅(中级)

25
 
学习啦,支持你……
此帖出自NXP MCU论坛
 
 
 

回复

66

帖子

0

TA的资源

纯净的硅(中级)

26
 
这么快,学习了 ,以后,多交流了
此帖出自NXP MCU论坛
 
 
 

回复

6366

帖子

4920

TA的资源

版主

27
 

int main (void)

{

init_timer32(0, TIME_INTERVAL*10);  //初始化定时器,并设置其时间间隔

    enable_timer32(0);//使能定时器

    GPIOInit();

    GPIOSetDir( LED_PORT, LED_BIT, 1 );

while (1)

    {

    }

}

很明显,第一句就是定时器设置的关键所在,找出它的原型并先把所有的预编译部分去掉:

void init_timer32(uint8_t timer_num, uint32_t TimerInterval)//参数分别为定时器标//号和计数值

{

  if ( timer_num == 0 )

  {

LPC_SYSCON->SYSAHBCLKCTRL |= (1<<9);    //  开启设备时钟

/*以下语句是选择IO口的定时器功能*/

    LPC_IOCON->;PIO1_5 &= ~0x07;  /*  Timer0_32 I/O config */

    LPC_IOCON->;PIO1_5 |= 0x02;   /* Timer0_32 CAP0 */

    LPC_IOCON->;PIO1_6 &= ~0x07;

    LPC_IOCON->;PIO1_6 |= 0x02;   /* Timer0_32 MAT0 */

    LPC_IOCON->;PIO1_7 &= ~0x07;

    LPC_IOCON->;PIO1_7 |= 0x02;   /* Timer0_32 MAT1 */

    LPC_IOCON->;PIO0_1 &= ~0x07; 

LPC_IOCON->;PIO0_1 |= 0x02;  /* Timer0_32 MAT2 */

/*以上语句是选择IO口的定时器功能*/

    LPC_TMR32B0->MR0 = TimerInterval;//设置计数值

    LPC_TMR32B0->MCR = 3;            /* 当匹配时触发匹配中断并复位TC寄存器*/

    NVIC_EnableIRQ(TIMER_32_0_IRQn);//使能32位定时器0中断

  }

  else if ( timer_num == 1 )

  {

    /*这部分是对定时器1的设置,跟上面完全一样,故也省去*/

  }

  return;

}

以上程序中,

1、首先开启AHB时钟给TIMER32提供驱动时钟;

2、其次对把相关的IO设置为定时器功能,因为32位定时器0IOLPC1343JTAG端口IO存在复用情况,默认情况下IO执行JTAG IO功能;

3、接着设置计数值;

4、设置匹配时触发匹配中断,并且复位TC寄存器。这个地方比较关键,首先要知道TIMER是加1计数,即计数范围从0x00000000xffffffff,但是当其计数值和设置的计数值TimerInterval匹配(相等)时,便触发了匹配中断,同时复位TC寄存器即清0,相当于起到了一个初值重装的作用。

5、最后是开启32TIMER的中断;

回到主函数,enable_timer32(0),如此定时器就开始启动计数了。

最后总结一下定时器的运作,打开时钟,IO设置,写入匹配值,打开中断并开始运行。当TC中的计数值和匹配值相等时,触发中断,执行中断服务程序,并且清零TC计数值开始新一轮计数。

下面是另外一个重点,定时时间的计算。

从定时器的内部结构图和初始化函数都可以看出,定时器时钟来自PCLKPeripheral CLOCK),而定时器属于APB设备,所以它的时钟来自AHB->APB

所以,为了看看AHB总线上传递过来的时钟是多少,这是一个顺藤摸瓜的过程。

 

上图展示了AHB时钟的来源:main clock经过CLOCK DIVIDER提供。

main clock来自哪里呢,这是一个逆势而上的过程。

在此笔者挖出LPC1343带的函数库里面所做的系统设置函数,在此之列出和本次试验有关的时钟设置语句,节省篇幅,来自system_LPC13xx.c

 

void SystemInit (void)

{

  …… ……

LPC_SYSCON->SYSPLLCLKSEL  = SYSPLLCLKSEL_Val;/*选择PLL输入★★★★*/

  LPC_SYSCON->SYSPLLCLKUEN  = 0x01;       /* 更新时钟源*/

  LPC_SYSCON->SYSPLLCLKUEN  = 0x00;       /* 更寄存器*/

  LPC_SYSCON->SYSPLLCLKUEN  = 0x01;

  while (!(LPC_SYSCON->SYSPLLCLKUEN & 0x01));/*等待时钟更新完毕 */

#if (SYSPLL_SETUP)               /* PLL设置*/

  LPC_SYSCON->SYSPLLCTRL    = SYSPLLCTRL_Val;//★★★★★

  LPC_SYSCON->PDRUNCFG     &= ~(1 << 7);   /* 打开PLL电源 */

  while (!(LPC_SYSCON->SYSPLLSTAT & 0x01));/* 等到PLL锁定完毕 */

  …… ……

  LPC_SYSCON->MAINCLKSEL  = MAINCLKSEL_Val;/*选择主时钟源★★★★ */

  LPC_SYSCON->MAINCLKUEN    = 0x01;     /* 更新主时钟 */

  LPC_SYSCON->MAINCLKUEN    = 0x00;     /*更新寄存器  */

  LPC_SYSCON->MAINCLKUEN    = 0x01;

  while (!(LPC_SYSCON->MAINCLKUEN & 0x01));/* 等待更新完毕  */

  …… ……

LPC_SYSCON->SYSAHBCLKDIV  = SYSAHBCLKDIV_Val;//选择AHB分频数★★★

  LPC_SYSCON->SYSAHBCLKCTRL = AHBCLKCTRL_Val;//打开AHB时钟

  …… ……

}

星号注释为关键语句。从上述注释中,我们发现主时钟源的选择语句是

LPC_SYSCON->MAINCLKSEL  = MAINCLKSEL_Val

而可以查找出MAINCLKSEL_Val的值是:

#define MAINCLKSEL_Val    0x00000003

 

 

[ 本帖最后由 tiankai001 于 2010-5-26 07:25 编辑 ]
此帖出自NXP MCU论坛
 
 
 

回复

6366

帖子

4920

TA的资源

版主

28
 

翻阅到寄存器:

 

所以发现,主时钟源来自System PLL clock out,所以要找出PLL的输出是多少。

PLL内部结构:

这个结构里面,最为关键的是FCCOPSELMSEL三个环节,user.manual.lpc13xx给出了计算范例:

至此我们知道Fclkout = M× Fclkin = (FCCO) (2 × P),我们要找出这个公式的两个未知量,首先是M(MSEL),存放于以下寄存器:

以及以下语句:

LPC_SYSCON->SYSPLLCTRL    = SYSPLLCTRL_Val;//★★★★★

再查找出:

#define SYSPLLCTRL_Val        0x00000025

所以MESL=0x101,同时PSEL=0x01

然后再找出Fclkin,对应以下语句:

LPC_SYSCON->SYSPLLCLKSEL  = SYSPLLCLKSEL_Val;/*选择PLL输入★★★★*/

依旧查找到:

#define SYSPLLCLKSEL_Val      0x00000001

以及寄存器:

可以看出,Fclkin来自系统外部振荡器,也就是外部12MHz晶振。

所以最终:

                 Fclkout = M× Fclkin = (FCCO) (2 × P)=72MHz

 

这个就是主时钟频率,也是LPC1343可以达到的最大工作频率。前文亦提到,APB设备时钟来自主时钟经过分频器提供,所以AHB分频数来自:

LPC_SYSCON->SYSAHBCLKDIV  = SYSAHBCLKDIV_Val;//选择AHB分频数★★★

还有:

#define SYSAHBCLKDIV_Val      0x00000001

结论是1分频,所以到达定时器时钟入口处的时钟就是72MHz/1=72MHz

接下来就是定时器内部的事情了,接下来要得到定时器内部的预分频值,但是在定时器初始化语句里面并没有看到相应的设置,于是翻阅user.manual.lpc13xx,找到如下描述

This causes the TC to increment on every PCLK when PR = 0, every 2 PCLKs when PR = 1, etc

所以我们知道两点,第一,预分频值PR默认为0,第二,当预分配值PR=0时,causes the TC to increment on every PCLK,即分频数为1

所以我们最终得到32位定时器的计数时钟为72MHz。计数一次所需要的时间是(1/72000000)s

回到主函数中的初始化语句 

init_timer32(0, TIME_INTERVAL*10);

查到:

#define TIME_INTERVAL (720000-1)//1是因为计数值为0~719999而不是1~720000

PS在此原宏定义为:

#define TIME_INTERVAL (SystemCoreClock/100 - 1)

笔者其实在此将SystemCoreClock/100计算出来了,因为SystemCoreClock72MHz

所以得到定时器的匹配间隔时间为:

 

T=1 x 10 x 720000 / 72000000=0.01=100ms

 

至此,定时器定时间隔就计算出来了!

将定时器中断服务作如下修改:
void TIMER32_0_IRQHandler(void)

{

  static int k=1;

  if ( LPC_TMR32B0->IR & 0x01 )

  { 

    LPC_TMR32B0->IR = 1;                /* clear interrupt flag */

    timer32_0_counter++;

    GPIOSetValue( 0, 7, k );

    k=~k;

  }

  if ( LPC_TMR32B0->IR & (0x1<<4) )

  { 

    LPC_TMR32B0->IR = 0x1<<4;           /* clear interrupt flag */

    timer32_0_capture++;

  }

  return;

}

编译,运行,每隔100ms便进入一次中断服务函数,LED100ms间隔闪烁。

 

 

下一节,我们尝试使用这个32位定时器产生PWM信号,在LED上显示渐亮的效果。

此帖出自NXP MCU论坛

点评

感谢了,最近搞了块板子,学习一下。。  详情 回复 发表于 2013-4-23 16:44
 
 
 

回复

928

帖子

0

TA的资源

五彩晶圆(高级)

29
 
值得细看
此帖出自NXP MCU论坛
 
个人签名动手创造个性自我

https://home.eeworld.com.cn/?95709
 
 

回复

2955

帖子

0

TA的资源

纯净的硅(初级)

30
 
不错.............
此帖出自NXP MCU论坛
 
个人签名不断地学习,才会有创新!
淘宝小店:手机、qq点卡、游戏点卡自动充值 http://shop63727265.taobao.com/
 
 

回复

1673

帖子

0

TA的资源

五彩晶圆(中级)

31
 

原帖由 losingamong 于 2010-5-11 21:54 发表 比较奇怪的是,似乎这样的好帖子人气都不太好啊

 

 

同感啊,好贴,LZ辛苦。

好多人都没时间挨个帖子翻的

[ 本帖最后由 simonprince 于 2010-5-29 14:49 编辑 ]
此帖出自NXP MCU论坛
 
个人签名要把目标订的实现起来辛苦一点!
 
 

回复

66

帖子

0

TA的资源

纯净的硅(高级)

32
 
LZ,你是神吧?
此帖出自NXP MCU论坛
 
 
 

回复

6366

帖子

4920

TA的资源

版主

33
 

上一节里,我们了解了如何使用LPC1343内部的32位定时器来产生准确的时间间隔。本节,我们来实现32位定时器的另一个重要的功能,PWM信号的产生。

我们都知道PWM的全称是Pulse Width Modulation,即脉宽调制的意思。多用于电机控制领域,也可以用来实现DA转换。在此不需要累赘它的特点,我们直接切入主题。

 

user.manual.lpc13xx中对PWM的描述很简单也足够充分:

In PWM mode, three match registers can be used to provide a single-edge controlled

PWM output on the match output pins. One match register is used to control the PWM cycle length.

在定时器的PWM模式里,四个匹配寄存器中的三个可以用来提供单边沿控制的PWM信号在相应引脚输出。同时剩下的一个用来控制PWM波形的周期。

For each timer, a maximum of three-single edge controlled PWM outputs can be selected on the MATn[2:0] outputs. One additional match register determines the PWM cycle length. When a match occurs in any of the other match registers, the PWM output is set to HIGH. The timer is reset by the match register that is configured to set the PWM cycle length. When the timer is reset to zero, all currently HIGH match outputs configured as PWM outputs are cleared.

 

翻译一下:

每一个定时器可以产生最多三路的单边沿控制的PWM输出,可以在MATn[2:0]里选择输出引脚。另外一个寄存器用以决定PWM周期长度。当匹配事件发生在其PWM控制寄存器中,PWM输出引脚会置高电平。而当计数值和PWM周期长度寄存器匹配时,计数值复位清0,同时PWM输出引脚清零。

此外还需要看到一个寄存器:

 

 

上图中唯一的一个Note

It is recommended to use match channel 3 to set the PWM cycle

意为:推荐使用第三个匹配通道设置PWM的周期。

如此,整体思路就有了:

MATCH3寄存器设置PWM周期,同时在另外三个寄存器MAT0,1,2设置占空比。当计数值与MAT0,1,2中的数值匹配时,PWM输出引脚输出高电平;当计数值与MATCH3寄存器中的值匹配时,PWM引脚清零。所以PWM的高电平周期是VALUE[MAT0,1,2]-VALUE[MAT3],低电平周期就是0- VALUE[MAT0,1,2]

 

我们来看了PWM带的PWM范例:

int main (void)

{

LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);//打开IO时钟

init_timer32PWM(1, period, MATCH0); //设置32位定时器为PWM模式,定义周期,输出通道

enable_timer32(1);//使能32位定时器1

setMatch_timer32PWM (1, 0, period/4);//设置占空比

    while (1)                

    {

    }

}

PS:在此做了不小的删改,原本NXP带的例程里,前面做的许多的定时器设置之后,下面居然匪夷所思地来了个模拟PWM

此程序里,首先是打开AHB中对于GPIO的时钟,这个前面章节提到多次了。

看看32位定时器PWM输出初始化程序:

void init_timer32PWM(uint8_t timer_num, uint32_t period, uint8_t match_enable)

{

   

    disable_timer32(timer_num);//首先要使能定时器,才能对定时器进行设置

    if (timer_num == 1)

    {

    LPC_SYSCON->SYSAHBCLKCTRL |= (1<<10);//打开定时器时钟

LPC_TMR32B1->EMR = (1<<EMC3)|(1<<EMC2)|(2<<EMC1)

|(1<<EMC0)|(1<<3)|(match_enable);//使能各个匹配寄存器

/*以下四个if函数的作用是切换各个MATCH通道对于的输出IO到普通输出IO状态,因为LPC1343JTAG接口与32位定时器1的匹配IO存在复用情况,而默认情况下这些IO行使JTAGIO功能,所以必须切换*/   

if (match_enable & 0x01)

    {

LPC_IOCON->JTAG_TDO_PIO1_1  &= ~0x07;  

    LPC_IOCON->JTAG_TDO_PIO1_1  |= 0x03;

    }      

if (match_enable & 0x02)

    {

    LPC_IOCON->JTAG_nTRST_PIO1_2 &= ~0x07;

 LPC_IOCON->JTAG_nTRST_PIO1_2 |= 0x03;  

    }

    if (match_enable & 0x04)

    {

    LPC_IOCON->ARM_SWDIO_PIO1_3&= ~0x07;

 LPC_IOCON->ARM_SWDIO_PIO1_3|= 0x03;

    }

    if (match_enable & 0x08)

    {

    LPC_IOCON->PIO1_4&= ~0x07;

    LPC_IOCON->PIO1_4|= 0x02;  

    }

LPC_TMR32B1->PWMC = (1<<3)|(match_enable);//使用匹配寄存器MATCH3设置PWM//期,与用户手册推荐的一致

timer32_1_period = period;

LPC_TMR32B1->MR3 = timer32_1_period; //写入周期

LPC_TMR32B1->MR0    = timer32_1_period/2;//设置MATCH0通道占空比为50%

LPC_TMR32B1->MR1    = timer32_1_period/2; //设置MATCH1通道占空比为50%

LPC_TMR32B1->MR2    = timer32_1_period/2; //设置MATCH2通道占空比为50%

LPC_TMR32B1->MCR = 1<<10;//允许当计数值和MAT3寄存器值匹配时请0计数值

}

else

{

    /*以下是对定时器0的设置,与上半段程序类同*/

}

此帖出自NXP MCU论坛
 
 
 

回复

6366

帖子

4920

TA的资源

版主

34
 

从以上注释可以看出,设置定时器为PWM模式的步骤:

1、  首先要使能定时器,才能对定时器进行设置;

2、  打开定时器时钟;

3、  使能各个匹配寄存器;

4、  切换IO功能;

5、  制定存放PWM周期值的寄存器;

6、  写入周期;

7、  设置各通道占空比;

8、  允许当计数值和MAT3寄存器值匹配时请0计数值;

Ps:可以注意到,在此函数中已经把各个匹配输出通道设置为50%的占空比。

回到主函数,接下来使能定时器:

enable_timer32(1);

接着设置占空比:

setMatch_timer32PWM (1, 0, period/4);

原型如下:

void setMatch_timer32PWM (uint8_t timer_num, uint8_t match_nr, uint32_t value)

{

    if (timer_num)

    {

        switch (match_nr)

        {

            case 0:LPC_TMR32B1->MR0 = value;break;

            case 1:LPC_TMR32B1->MR1 = value;break;

            case 2:LPC_TMR32B1->MR2 = value;break;

            case 3:LPC_TMR32B1->MR3 = value;break;

            default:break;

        }  

}

    else

    {  

        /*此处是对另一个定时器进行设置,与上类同*/

    }

}

同样轻易看出,该函数是对各个MAT寄存器(在初始化函数中已经写入了50%的占空比数值)进行设置,以达到改变占空比的目的。

最后提一提PWM的周期如何确定呢,我们已经知道PWM周期以MATCH3寄存器中的数值N决定,所以定时器计数N次,就是该PWM波形的单周期。在本次例程中,NXP将周期值设为N=1000,所以PWM的周期是(1000/72000000s,频率便是72KHz

这样,在一定的时间间隔离改变占空比,就可以实现LED灯渐亮的效果了。

 

下一节,我们来看看定时器的第三个功能:捕获

 

此帖出自NXP MCU论坛
 
 
 

回复

66

帖子

0

TA的资源

纯净的硅(高级)

35
 

楼主太牛,必须每天都顶

楼主太牛,必须每天都顶!
此帖出自NXP MCU论坛
 
 
 

回复

10

帖子

0

TA的资源

一粒金砂(初级)

36
 

 

同学习

此帖出自NXP MCU论坛
 
 
 

回复

394

帖子

0

TA的资源

一粒金砂(高级)

37
 

原帖由 tiankai001 于 2010-5-26 07:31 发表 翻阅到寄存器: 46865   所以发现,主时钟源来自System PLL clock out,所以要找出PLL的输出是多少。 PLL内部结构: 46866 这个结构里面,最为关键的是FCCO、PSEL和MSEL三个环节,user.manual.lpc13x ...

其实关于时钟,版主有没有可以外部设备进行效验的方式,这样可以检测我们计算出来的每个时钟,定时的准确性?亦或是将内部时钟引出来检测的方式,或是通过IO口,通过AHB设置IO口时钟,然后翻转IO来检测IO管脚时钟的方式检测内部时钟系统的正确性,谢谢站送回复!或是有回复的话,站送消息,我来拜读也可以,谢谢!

此帖出自NXP MCU论坛
 
 
 

回复

6366

帖子

4920

TA的资源

版主

38
 

原帖由 pepsi360 于 2010-6-2 16:18 发表 其实关于时钟,版主有没有可以外部设备进行效验的方式,这样可以检测我们计算出来的每个时钟,定时的准确性?亦或是将内部时钟引出来检测的方式,或是通过IO口,通过AHB设置IO口时钟,然后翻转IO来检测IO管脚时钟的 ...

 

 

 

呵呵,回复的晚了。实在不好意思,

 

我这里工具比较少,没有示波器这些,所以没有认真验证过,

此帖出自NXP MCU论坛
 
 
 

回复

14

帖子

0

TA的资源

一粒金砂(初级)

39
 
顶,对照手册跟你的说明,很快就弄明白了。
此帖出自NXP MCU论坛
 
 
 

回复

36

帖子

0

TA的资源

一粒金砂(中级)

40
 

太强了!

学习中!!向前辈学习!!
此帖出自NXP MCU论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表