• 1
    回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

【得捷之选】 基础功能测试——定时器功能

       我们在GPIO和外部中断的基础功能测试的基础上进行定时器功能的测试。在GPIO和外部中断我们实现的按键中断的采集以及LED的控制,在次基础上加入定时器功能会擦出怎么样的火花呢?是的,第一个就是LED的闪烁,在定时器中断中进行LED的翻转。
我们先了解一下MAX78000的定时器:
       MAX78000具有32位定时器/计数器/PWM (TMR, LPTMR),通用的32位定时器提供定时、捕获/比较或脉宽调制(PWM)信号的生成。定时器提供以下功能:
            ●32位向上/向下自动重新加载
            ●可编程预分频器
            ●PWM输出产生
            ●捕获、比较和捕获/比较能力
            ●外部引脚与GPIO复用,用于定时器输入,时钟门控,或捕获
            ●计时器输出管脚
            ●TMR0-TMR3可配置为2 × 16位通用定时器
            ●定时器中断
       MAX78000一共提供6个32位定时器(TMR0、TMR1、TMR2、TMR3、LPTMR0和LPTMR1)。LPTMR0和LPTMR1可以在SLEEP、LOW POWER和MICRO POWER模式下运行。所有计时器都支持I/O功能。请注意,端口的功能可以与其他功能进行复用在GPIO引脚上。(在max78000.h中,6个定时器被描述为MXC_TMR0~MXC_TMR5)。
      每一个定时器能够实现的功能如下:

      在这里我们就要考虑一下本章节测试需要使用哪个定时器呢?基本定时功能基本上都能实现,那么PWM的展现可能需要与LED相结合。我们首先实现基础定时器功能,通过定时器中断中实现LED的翻转。
基础定时功能:
      要想实现LED是连续翻转,我们需要选择定时器为Counter Mode。
      为此我们参考例程定时器初始化内容如下:
#define Basic_CLOCK_SOURCE MXC_TMR_8M_CLK
#define Basic_FREQ 2// (Hz)
#define Basic_TIMER MXC_TMR3 
void BasicTimerInit()
{
    mxc_tmr_cfg_t tmr;
    uint32_t periodTicks = MXC_TMR_GetPeriod(Basic_TIMER, Basic_CLOCK_SOURCE, 128, Basic_FREQ);

    MXC_TMR_Shutdown(Basic_TIMER);
    tmr.pres = TMR_PRES_128;
    tmr.mode = TMR_MODE_CONTINUOUS;
    tmr.bitMode = TMR_BIT_MODE_16B;
    tmr.clock = Basic_CLOCK_SOURCE;
    tmr.cmp_cnt = periodTicks; //SystemCoreClock*(1/interval_time);
    tmr.pol = 0;
    if (MXC_TMR_Init(Basic_TIMER, &tmr, true) != E_NO_ERROR) {
        printf("Failed Continuous timer Initialization.\n");
        return;
    }
    
    MXC_NVIC_SetVector(TMR3_IRQn, BasicTimerHandler);
    NVIC_EnableIRQ(TMR3_IRQn);
    
    printf("Continuous timer started.\n");
    MXC_TMR_Start(Basic_TIMER);
}

      我们创建中断并编写中断程序:

void BasicTimerHandler()
{
    MXC_TMR_ClearFlags(Basic_TIMER);
    LED_Toggle(LEDSt);
}
       以上代码测试开始后出现了异常,我们经过定位发现程序卡在了while (!(tmr->ctrl1 & MXC_F_TMR_REVB_CTRL1_CLKEN_A)),也就是说定时器开启使能失败了,通过
MXC_SYS_IsClockEnabled(MXC_SYS_PERIPH_CLOCK_TMR1)检查时钟发现已经开启了。尝试重新加载例程看一下,同样的问题。、
       通过不断的测试目前的的现象更倾向于无限进入中断,都不用开启定时器计数,只要定时器初始化完成就开启潘多拉魔盒,计数就开始乱跳了。进行深层的挖掘发现在tmr_revb.c中的void MXC_TMR_RevB_ConfigGeneric函数(定时器初始化的底层函数)中,如果tmr.bitMode = TMR_BIT_MODE_16B则直接启动中断和定时器,到这里看似已经慢慢的揭开了这个异常的面纱。不过我准备放弃了,另寻途径,既然tmr.bitMode = TMR_BIT_MODE_16B会造成这种不可接受的异常,那么配置TMR_BIT_MODE_16A试一下,修改代码如下:
void BasicTimerInit()
{
    mxc_tmr_cfg_t tmr;
    uint32_t periodTicks = MXC_TMR_GetPeriod(Basic_TIMER, Basic_CLOCK_SOURCE, 128, Basic_FREQ);
    MXC_TMR_Shutdown(Basic_TIMER);

    tmr.pres = TMR_PRES_128;
    tmr.mode = TMR_MODE_CONTINUOUS;
    tmr.bitMode = TMR_BIT_MODE_16A;
    tmr.clock = Basic_CLOCK_SOURCE;
    tmr.cmp_cnt = periodTicks; //SystemCoreClock*(1/interval_time);
    tmr.pol = 0;

    if (MXC_TMR_Init(Basic_TIMER, &tmr, false) != E_NO_ERROR) {
        printf("Failed Continuous timer Initialization.\n");
        return;
    }

    MXC_NVIC_SetVector(TMR3_IRQn, BasicTimerHandler);
    NVIC_EnableIRQ(TMR3_IRQn);
    MXC_TMR_EnableInt(Basic_TIMER);
    printf("Continuous timer started.\n");
    MXC_TMR_Start(Basic_TIMER);
}
       柳暗花明啊,这是一个bitMode引发的惨案,不过结果是好,使用TMR_BIT_MODE_16A后,可以正常进入中断了,程序正常运行了,也算达到了预期。
PWM输出功能:
      在PWM模式下,定时器使用定时器的输出信号发送PWM输出。计时器首先计数到匹配值存储在TMRn_PWM.pwm寄存器中。在循环结束时,TMRn_CNT值与TMRn_PWM.pwm比较,定时器输出信号切换状态。计时器继续计数,直到到达TMRn_CMP值。
      定时器周期在TMRn_CNT = TMRn_CMP之后的fCNT_CLK上升沿结束。计时器外设在计时器周期结束时自动执行以下动作:
            •TMRn_CNT复位为0x0000 0001,定时器恢复计数。
            •定时器输出信号切换。
            •对应的TMRn_INTFL.irq字段设置为1,表示发生了定时器中断事件。
      TMRn_CTRL0.pol = 0,时,定时器输出信号从低开始,到TMRn_CNT值时变为高匹配TMRn_PWM值。定时器输出信号保持高电平,直到TMRn_CNT值达到TMRn_CMP,导致定时器输出信号变低,TMRn_CNT值复位为0x0000 0001。
      TMRn_CTRL0.pol = 1,时,定时器输出信号高起始,当TMRn_CNT值与TMRn_PWM值,定时器输出信号保持低电平,直到TMRn_CNT值达到TMRn_CMP,导致定时器输出信号转高,TMRn_CNT值复位为0x0000 0001。
      测试代码如下:
#define PWM_CLOCK_SOURCE MXC_TMR_32K_CLK 
#define FREQ 10 // (Hz)
#define DUTY_CYCLE 50 // (%)
#define PWM_TIMER MXC_TMR4 

void PWMTimer()
{
    mxc_tmr_cfg_t tmr; // to configure timer
    unsigned int periodTicks = MXC_TMR_GetPeriod(PWM_TIMER, PWM_CLOCK_SOURCE, 16, FREQ);
    unsigned int dutyTicks = periodTicks * DUTY_CYCLE / 100;

    MXC_TMR_Shutdown(PWM_TIMER);

    tmr.pres = TMR_PRES_16;
    tmr.mode = TMR_MODE_PWM;
    tmr.bitMode = TMR_BIT_MODE_32;
    tmr.clock = PWM_CLOCK_SOURCE;
    tmr.cmp_cnt = periodTicks;
    tmr.pol = 1;

    if (MXC_TMR_Init(PWM_TIMER, &tmr, true) != E_NO_ERROR) {
        printf("Failed PWM timer Initialization.\n");
        return;
    }
    if (MXC_TMR_SetPWM(PWM_TIMER, dutyTicks) != E_NO_ERROR) {
        printf("Failed TMR_PWMConfig.\n");
        return;
    }

    MXC_TMR_Start(PWM_TIMER);
    printf("PWM started.\n\n");
}
      效果如下:

精彩视频分享:

串口接收情况(定时器基础定时测试)

 

定时器基础定时测试效果展示

定时器PWM测试效果展示

 

全部回复(1)
正序查看
倒序查看
04-30 15:10

本帖的MAX78000FTHR, 得捷官网购买连接如下:

https://www.digikey.cn/zh/products/detail/analog-devices-inc-maxim-integrated/MAX78000FTHR/13549063?WT.z_header=search_go&s=N4IgTCBcDaILIEEAaB2AHABiwMQCoAkAlEAXQF8g

关于购买有任何问题,大家可以随时联系我哦(微信:18522870362)

0
回复