查看: 1833|回复: 1

[LPC双核挑战赛] 【lpc54114学习笔记3】通用定时器

[复制链接]
  • TA的每日心情
    无聊
    2021-12-29 19:06
  • 签到天数: 47 天

    [LV.5]常住居民I

    49

    主题

    188

    帖子

    21

    金牌会员

    Rank: 6Rank: 6

    积分
    1375
    最后登录
    2024-5-13
    发表于 2018-4-22 11:05:55 | 显示全部楼层 |阅读模式
    本帖最后由 day_day 于 2018-4-22 19:55 编辑

    外部中断、定时计数器是从8051时代开始单片机的基础功能,学习一款新单片机自然先要攻克这两个关卡,上两章粗略探索了一下外部中断,这一章就探索一下定时器。


    (一)用户手册
    第十六章,通用计数定时器:
    数据手册16章.png

    根据数据手册介绍,lpc54110总共有5个通用定时器:
    定时器.png

    其中CTIMER0/1/2的使能时钟设置在AHBCLKCTRL1寄存器,复位时钟设置在ASYNCAPBCLKCTRL寄存器CTIMER3/4的使能时钟在ASYNCAPBCLKCTRL寄存器复位时钟设置在PRESETCTRL1寄存器


    (二)用户手册里面的寄存器
    IR(Interrupt Register中断寄存器):
    • The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending.
    • IR寄存器可以被写入从而清除中断,也可以通过读取这个寄存器数值来确认8个中断哪一个正在进行。
    TCR(Timer Control Register时间控制寄存器):
    • The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR.
    • TCR寄存器用于控制Timer Counter时间计数器的机能,时间计数器可以通过TCR被除能或重新设置
    TC(Timer Counter时间计数器):
    • The 32-bit TC is incremented every PR+1 cycles of the APB bus clock. The TC is controlled through the TCR.
    • 这个32位的TC寄存器每当经历PR+1个APB总线上时钟节拍,就会加一。它能够被TCR寄存器控制。
    PC(Prescale Counter预分频计数器)
    • The 32 bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface.
    • 32位的PC寄存器保存着一个不断递增值。当达到该值到达PR寄存器的数值时,TC加一,PC清除。PC寄存器是可以通过总线接口观察和操作的。
    PR(Prescale Register预分频寄存器)
    • Prescale Register. When the Prescale Counter (PC) is equal to this value, thenext clock increments the TC and clears the PC.
    • 当Prescale计数器(PC)等于这个值时。下一个时钟增加TC并清除PC。
    MCR(Match Control Register匹配控制寄存器):
    • The MCR is used to control whether an interrupt is generated, and whether the TC is reset when a Match occurs.
    • MCR是用来控制中断产生、TC重置(当匹配发生时)
    MR0-3(Match Register 0-3匹配寄存器):
    • MR0 can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR0 matches the TC.
    • MR0能够通过MCR重设TC,同时停止TC和PC,或者每当MR0匹配TC时产生中断。

    可以看出,每个定时器可以产生四个匹配中断!
    后面就是一些捕获、pwm生成的寄存器,与计数器功能有关,这里不再提。


    (三)例程
    1. #include "board.h"
    2. #include <stdio.h>

    3. /** @defgroup PERIPH_TIMER_5411X Simple timer example
    4. * @ingroup EXAMPLES_PERIPH_5411X
    5. * @include "periph_timer\readme.txt"
    6. */

    7. /**
    8. * @}
    9. */

    10. /*****************************************************************************
    11. * Private types/enumerations/variables
    12. ****************************************************************************/

    13. #define TICKRATE_HZ1 (1)/* 1 ticks per second */
    14. #define TICKRATE_HZ2 (2)/* 2 ticks per second */
    15. #define PRESCALE_HZ2 (0xFFFF)        /* 16-bit prescale count */

    16. /*****************************************************************************
    17. * Public types/enumerations/variables
    18. ****************************************************************************/

    19. /*****************************************************************************
    20. * Private functions
    21. ****************************************************************************/

    22. /*****************************************************************************
    23. * Public functions
    24. ****************************************************************************/

    25. /**
    26. * @brief        Handle interrupt from Timer 0
    27. * @return        Nothing
    28. */
    29. void CT32B0_IRQHandler(void)
    30. {
    31.         if (Chip_TIMER_MatchPending(LPC_TIMER0, 1)) {
    32.                 Chip_TIMER_ClearMatch(LPC_TIMER0, 1);
    33.                 Board_LED_Toggle(2);
    34.         }
    35. }

    36. /**
    37. * @brief        Handle interrupt from Timer 1
    38. * @return        Nothing
    39. */
    40. void CT32B1_IRQHandler(void)
    41. {
    42.         if (Chip_TIMER_MatchPending(LPC_TIMER1, 1)) {
    43.                 Chip_TIMER_ClearMatch(LPC_TIMER1, 1);
    44.                 Board_LED_Toggle(1);
    45.         }
    46. }

    47. /**
    48. * @brief        main routine for timer example
    49. * @return        Function should not exit.
    50. */
    51. int main(void)
    52. {
    53.         int loop = 1;        /* Used to fix the unreachable statement warning */

    54.         uint32_t timerBaseClock;

    55.         SystemCoreClockUpdate();
    56.         Board_Init();
    57.         Board_LED_Set(2, false);
    58.         Board_LED_Set(1, false);

    59.         /* Initialize Timer 0 and Timer 1 */
    60.         Chip_TIMER_Init(LPC_TIMER0);
    61.         Chip_TIMER_Init(LPC_TIMER1);

    62.         /* Setup prescale value on Timer 0 to PCLK */
    63.         Chip_TIMER_PrescaleSet(LPC_TIMER0, 0);
    64.         /* Setup prescale value on Timer 1 for lower resolution */
    65.         Chip_TIMER_PrescaleSet(LPC_TIMER1, PRESCALE_HZ2);

    66.         /* Reset timers */
    67.         Chip_TIMER_Reset(LPC_TIMER0);
    68.         Chip_TIMER_Reset(LPC_TIMER1);

    69.         /* Enable both timers to generate interrupts when time matches */
    70.         Chip_TIMER_MatchEnableInt(LPC_TIMER0, 1);
    71.         Chip_TIMER_MatchEnableInt(LPC_TIMER1, 1);

    72.         /* Get rate of timer base clock */
    73.         timerBaseClock = Chip_Clock_GetAsyncSyscon_ClockRate();

    74.         /* Setup Timer 0 for a match every 1s */
    75.         Chip_TIMER_SetMatch(LPC_TIMER0, 1, (timerBaseClock / TICKRATE_HZ1));

    76.         /* Setup Timer 1 for a match twice in a second */
    77.         Chip_TIMER_SetMatch(LPC_TIMER1, 1, (timerBaseClock / ((PRESCALE_HZ2 + 1) * TICKRATE_HZ2)) );

    78.         /* Setup both timers to restart when match occurs */
    79.         Chip_TIMER_ResetOnMatchEnable(LPC_TIMER0, 1);
    80.         Chip_TIMER_ResetOnMatchEnable(LPC_TIMER1, 1);

    81.         /* Start both timers */
    82.         Chip_TIMER_Enable(LPC_TIMER0);
    83.         Chip_TIMER_Enable(LPC_TIMER1);

    84.         /* Clear both timers of any pending interrupts */
    85.         NVIC_ClearPendingIRQ(CT32B0_IRQn);
    86.         NVIC_ClearPendingIRQ(CT32B1_IRQn);

    87.         /* Enable both timer interrupts */
    88.         NVIC_EnableIRQ(CT32B0_IRQn);
    89.         NVIC_EnableIRQ(CT32B1_IRQn);

    90.         /* Wait for timers to generate interrupts (LEDs toggle in interrupt handlers) */
    91.         while (loop) {
    92.                 __WFI();
    93.         }

    94.         return 0;
    95. }
    复制代码


    (四)例程分析
    1、初始化定时器
    1. /* Initialize Timer 0 and Timer 1 */
    2.         Chip_TIMER_Init(LPC_TIMER0);
    3.         Chip_TIMER_Init(LPC_TIMER1);
    复制代码

    看看初始化函数Chip_TIMER_Init:
    1. /**
    2. * @brief        Initialize a timer
    3. * @param        pTMR        : Pointer to timer IP register address
    4. * @return        Nothing
    5. */
    6. __STATIC_INLINE void Chip_TIMER_Init(LPC_TIMER_T *pTMR)
    7. {
    8.         switch((uint32_t) pTMR) {
    9.                 case LPC_TIMER4_BASE:
    10.                         Chip_Clock_EnablePeriphClock(SYSCON_CLOCK_TIMER4);
    11.                         Chip_SYSCON_PeriphReset(RESET_TIMER4);
    12.                 case LPC_TIMER3_BASE:
    13.                         Chip_Clock_EnablePeriphClock(SYSCON_CLOCK_TIMER3);
    14.                         Chip_SYSCON_PeriphReset(RESET_TIMER3);
    15.                 case LPC_TIMER2_BASE:
    16.                         Chip_Clock_EnablePeriphClock(SYSCON_CLOCK_TIMER2);
    17.                         Chip_SYSCON_PeriphReset(RESET_TIMER2);
    18.                 case LPC_TIMER1_BASE:
    19.                         Chip_Clock_EnablePeriphClock(SYSCON_CLOCK_TIMER1);
    20.                         Chip_SYSCON_PeriphReset(RESET_TIMER1);
    21.                 case LPC_TIMER0_BASE:
    22.                         Chip_Clock_EnablePeriphClock(SYSCON_CLOCK_TIMER0);
    23.                         Chip_SYSCON_PeriphReset(RESET_TIMER0);
    24.                 default:
    25.                         /* BUG: Application has provided wrong timer base address */
    26.                         return;
    27.         }
    28. }
    复制代码
    对定时器时钟使能


    2、设置定时器分频系数
    1. /* Setup prescale value on Timer 0 to PCLK */
    2.         Chip_TIMER_PrescaleSet(LPC_TIMER0, 0);
    3.         /* Setup prescale value on Timer 1 for lower resolution */
    4.         Chip_TIMER_PrescaleSet(LPC_TIMER1, PRESCALE_HZ2);
    复制代码
    Chip_TIMER_PrescaleSet:
    1. __STATIC_INLINE void Chip_TIMER_PrescaleSet(LPC_TIMER_T *pTMR, uint32_t prescale)
    2. {
    3.         pTMR->PR = prescale;
    4. }
    复制代码
    操作PR(Prescale Register预分频寄存器)

    3、复位定时器
    1. /* Reset timers */
    2.         Chip_TIMER_Reset(LPC_TIMER0);
    3.         Chip_TIMER_Reset(LPC_TIMER1);
    复制代码


    4、使能定时器中断

    1. /* Enable both timers to generate interrupts when time matches */
    2.         Chip_TIMER_MatchEnableInt(LPC_TIMER0, 1);
    3.         Chip_TIMER_MatchEnableInt(LPC_TIMER1, 1);
    复制代码
    Chip_TIMER_MatchEnableInt:
    1. __STATIC_INLINE void Chip_TIMER_MatchEnableInt(LPC_TIMER_T *pTMR, int8_t matchnum)
    2. {
    3.         pTMR->MCR = (pTMR->MCR & TIMER_MCR_MASK) | TIMER_INT_ON_MATCH(matchnum);
    4. }
    复制代码
    操作MCRMatch Control Register匹配控制寄存器)
    mcr.png
    TIMER_INT_ON_MATCH是MCR寄存器的第一位:
    1. /** Bit location for interrupt on MRx match, n = 0 to 3 */
    2. #define TIMER_INT_ON_MATCH(n)   (_BIT(((n) * 3)))
    3. /** Bit location for reset on MRx match, n = 0 to 3 */
    4. #define TIMER_RESET_ON_MATCH(n) (_BIT((((n) * 3) + 1)))
    5. /** Bit location for stop on MRx match, n = 0 to 3 */
    6. #define TIMER_STOP_ON_MATCH(n)  (_BIT((((n) * 3) + 2)))
    7. /** Match Control register Mask */
    8. #define TIMER_MCR_MASK          ((uint32_t) 0x0FFF)
    复制代码


    5、设置匹配装载值
    1. /* Get rate of timer base clock */
    2.         timerBaseClock = Chip_Clock_GetAsyncSyscon_ClockRate();

    3.         /* Setup Timer 0 for a match every 1s */
    4.         Chip_TIMER_SetMatch(LPC_TIMER0, 1, (timerBaseClock / TICKRATE_HZ1));

    5.         /* Setup Timer 1 for a match twice in a second */
    6.         Chip_TIMER_SetMatch(LPC_TIMER1, 1, (timerBaseClock / ((PRESCALE_HZ2 + 1) * TICKRATE_HZ2)) );
    复制代码
    函数:
    1. __STATIC_INLINE void Chip_TIMER_SetMatch(LPC_TIMER_T *pTMR, int8_t matchnum, uint32_t matchval)
    2. {
    3.         pTMR->MR[matchnum] = matchval;
    4. }
    复制代码
    MR(Match Register 0-3匹配寄存器

    6、当MR0-3匹配TC时,TC重置

    1. /* Setup both timers to restart when match occurs */
    2.         Chip_TIMER_ResetOnMatchEnable(LPC_TIMER0, 1);
    3.         Chip_TIMER_ResetOnMatchEnable(LPC_TIMER1, 1);
    复制代码
    Chip_TIMER_ResetOnMatchEnable函数:
    1. __STATIC_INLINE void Chip_TIMER_ResetOnMatchEnable(LPC_TIMER_T *pTMR, int8_t matchnum)
    2. {
    3.         pTMR->MCR = (pTMR->MCR & TIMER_MCR_MASK) | TIMER_RESET_ON_MATCH(matchnum);
    4. }
    复制代码
    TIMER_RESET_ON_MATCH是MCR寄存器的第二位:
    1. /** Bit location for reset on MRx match, n = 0 to 3 */
    2. #define TIMER_RESET_ON_MATCH(n) (_BIT((((n) * 3) + 1)))
    复制代码

    7、使能定时器
    1. /* Start both timers */
    2.         Chip_TIMER_Enable(LPC_TIMER0);
    3.         Chip_TIMER_Enable(LPC_TIMER1);
    复制代码
    Chip_TIMER_Enable:
    1. __STATIC_INLINE void Chip_TIMER_Enable(LPC_TIMER_T *pTMR)
    2. {
    3.         pTMR->TCR = (pTMR->TCR & TIMER_CTRL_MASK) | TIMER_ENABLE;
    4. }
    复制代码
    操作TCR(Timer Control Register时间控制寄存器)
    tcr.png

    8、清除标志位、使能中断
    1. /* Clear both timers of any pending interrupts */
    2.         NVIC_ClearPendingIRQ(CT32B0_IRQn);
    3.         NVIC_ClearPendingIRQ(CT32B1_IRQn);

    4.         /* Enable both timer interrupts */
    5.         NVIC_EnableIRQ(CT32B0_IRQn);
    6.         NVIC_EnableIRQ(CT32B1_IRQn);
    复制代码
    NVIC_ClearPendingIRQ:
    1. __STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
    2. {
    3.   NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */
    4. }
    复制代码
    NVIC_EnableIRQ:
    1. __STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
    2. {
    3. /*  NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));  enable interrupt */
    4.   NVIC->ISER[(uint32_t)((int32_t)IRQn) >> 5] = (uint32_t)(1 << ((uint32_t)((int32_t)IRQn) & (uint32_t)0x1F)); /* enable interrupt */
    5. }
    复制代码

    (五)小结
    • 初始化定时器,Chip_TIMER_Init
    • 设置定时器分频系数,PR(Prescale Register预分频寄存器),Chip_TIMER_PrescaleSet
    • 复位定时器,Chip_TIMER_Reset
    • 使能定时器中断,MCR(Match Control Register匹配控制寄存器)第一位,Chip_TIMER_MatchEnableInt
    • 设置匹配装载值,MR(Match Register 0-3匹配寄存器),Chip_TIMER_SetMatch
    • 当MR0-3匹配TC时,TC重置;MCRMatch Control Register匹配控制寄存器)第二位;Chip_TIMER_ResetOnMatchEnable
    • 使能定时器,TCR(Timer Control Register时间控制寄存器),Chip_TIMER_Enable
    • 清除标志位、使能中断,NVIC_ClearPendingIRQ、NVIC_EnableIRQ


    总的来说,就是设置了分频系数、匹配值(及匹配机制);其余就是初始化、复位、使能定时器;使能定时器中断、清除标志位、使能NVIC中断服务函数。

    评分

    参与人数 1 +5 收起 理由
    doatello + 5 很给力!

    查看全部评分

    该会员没有填写今日想说内容.
    回复

    使用道具 举报

  • TA的每日心情
    无聊
    2018-7-31 08:40
  • 签到天数: 43 天

    [LV.5]常住居民I

    299

    主题

    876

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    14706
    最后登录
    2020-3-1
    发表于 2018-4-23 09:57:20 | 显示全部楼层
    感谢分享!
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

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

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-5-14 06:40 , Processed in 0.113780 second(s), 22 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表