Aurix英飞凌TC334芯片GPT模块定时器配置
大家好,我是左工,在上一节使用英飞凌Aurix系列TC334芯片点亮LED中我们已经运用Port外设实现对板载LED灯珠的亮灭控制。今天我们来聊聊嵌入式控制中非常非常关键的功能模块GPT的定时器。
前言
在上一节使用英飞凌Aurix系列TC334芯片点亮LED中我们使用同步延时的方法切换LED灯的亮灭。这种方法有两个问题,第一是浪费单片机的资源,同步延时过程中,单片机的处理器什么都做不了,就是在单纯的等待;第二延时精度不高且不稳定,可能是0.5s也可能是0.6s,对于精度要求高的时序,比如通讯时序,就不够用了。GPT模块的定时器功能就可以完美的解决这个问题。
GPT(General Purpose Timer Unit)是TC334内部的一个通用定时器模块,内部分为GPT1和GPT2,分别包含T2、T3、T4和T5、T6定时器。各个定时器都可以设置为定时器模式、门控定时器模式、计数器模式、增量编码计数模式。今天我们以GPT1的T3定时器为例,展示其配置过程和使用效果。
一、代码编写
利用上一节文章“搭建英飞凌Aurix系列TC334芯片免费开发工具链”中所描述的方法创建一个名为“2_GPTimer”的工程,如下图所示。
工程创建完成后,我们会在导引栏中看见如下文件和文件夹。其中文件“Cpu0_Main.c”就是我们本次需要操作的文件。
我们双击打开该文件,找到主函数“core0_main”,TC334运行后,将首先运行该函数。我们可以看见该函数里面有一个while循环。我们将把代码写在这个while循环附近。
用如下代码替换上图中被红色框标出的while循环。
GPTimer_init();
while(1)
{
}
添加完成后,我们本次实验对主函数的所有操作就结束了。下面我们来添加一些必要头文件。
#include "IfxGpt12.h"
#include "IfxSrc.h"
在主函数和头文件之间我们添加上“GPTimer_init()”函数的具体定义。
void GPTimer_init(void)
{
/*端口初始化*/
IfxPort_setPinMode(&MODULE_P02,5,IfxPort_Mode_outputPushPullGeneral ); //P02.5配置为输入模式
/*GPT120配置*/
IfxGpt12_enableModule(&MODULE_GPT120); //使能GPT120模块
IfxGpt12_setGpt1BlockPrescaler(&MODULE_GPT120,IfxGpt12_Gpt1BlockPrescaler_8); //GPT模块预分频,使用SPB总线时钟为100MHz
/*配置T3定时器用于产生周期性中断*/
IfxGpt12_T3_setMode(&MODULE_GPT120,IfxGpt12_Mode_timer); //设置T3定时器的模式为定时器模式
IfxGpt12_T3_setDirectionSource(&MODULE_GPT120,IfxGpt12_TimerDirectionSource_internal); //内部控制计数方向
IfxGpt12_T3_setTimerDirection(&MODULE_GPT120,IfxGpt12_TimerDirection_up); //T3的计数方向为向上计数
IfxGpt12_T3_setTimerPrescaler(&MODULE_GPT120,IfxGpt12_TimerInputPrescaler_128); //定时器计数时钟为模块时钟的128分频
IfxGpt12_T3_setTimerValue(&MODULE_GPT120,0xFFFF-50000+1); //计数50000个脉冲即会发生溢出事件
/*配置T3的溢出中断*/
IfxSrc_init(&SRC_GPT120T3,IfxSrc_Tos_cpu0,10); //配置GPT120模块的T3定时器溢出中断服务,中断优先级设为10
IfxSrc_enable(&SRC_GPT120T3); //使能GPT120模块的T3定时器溢出中断服务
/*启动定时器*/
IfxGpt12_T3_run(&MODULE_GPT120,IfxGpt12_TimerRun_start); //启动T3
}
在“GPTimer_init()”函数后面我们添加上中断回调函数“GPTimer_isr()”的定义。
IFX_INTERRUPT(GPTimer_isr,0,10); //声明定时中断服务函数
void GPTimer_isr(void)
{
/*重设初值*/
IfxGpt12_T3_setTimerValue(&MODULE_GPT120,0xFFFF-50000+1);
/*翻转IO*/
IfxPort_setPinState(&MODULE_P02, 5, IfxPort_State_toggled);
}
现在所有代码编写完毕,整个Cpu0_Main.c的定义如下所示。
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
#include "IfxGpt12.h"
#include "IfxSrc.h"
IFX_ALIGN(4) IfxCpu_syncEvent g_cpuSyncEvent = 0;
/*GPT定时模块初始化*/
void GPTimer_init(void)
{
/*端口初始化*/
IfxPort_setPinMode(&MODULE_P02,5,IfxPort_Mode_outputPushPullGeneral ); //P02.5配置为输入模式
/*GPT120配置*/
IfxGpt12_enableModule(&MODULE_GPT120); //使能GPT120模块
IfxGpt12_setGpt1BlockPrescaler(&MODULE_GPT120,IfxGpt12_Gpt1BlockPrescaler_8); //GPT模块预分频,使用SPB总线时钟为100MHz
/*配置T3定时器用于产生周期性中断*/
IfxGpt12_T3_setMode(&MODULE_GPT120,IfxGpt12_Mode_timer); //设置T3定时器的模式为定时器模式
IfxGpt12_T3_setDirectionSource(&MODULE_GPT120,IfxGpt12_TimerDirectionSource_internal); //内部控制计数方向
IfxGpt12_T3_setTimerDirection(&MODULE_GPT120,IfxGpt12_TimerDirection_up); //T3的计数方向为向上计数
IfxGpt12_T3_setTimerPrescaler(&MODULE_GPT120,IfxGpt12_TimerInputPrescaler_128); //定时器计数时钟为模块时钟的128分频
IfxGpt12_T3_setTimerValue(&MODULE_GPT120,0xFFFF-50000+1); //计数50000个脉冲即会发生溢出事件
/*配置T3的溢出中断*/
IfxSrc_init(&SRC_GPT120T3,IfxSrc_Tos_cpu0,10); //配置GPT120模块的T3定时器溢出中断服务,中断优先级设为10
IfxSrc_enable(&SRC_GPT120T3); //使能GPT120模块的T3定时器溢出中断服务
/*启动定时器*/
IfxGpt12_T3_run(&MODULE_GPT120,IfxGpt12_TimerRun_start); //启动T3
}
IFX_INTERRUPT(GPTimer_isr,0,10); //声明定时中断服务函数
void GPTimer_isr(void)
{
/*重设初值*/
IfxGpt12_T3_setTimerValue(&MODULE_GPT120,0xFFFF-50000+1);
/*翻转IO*/
IfxPort_setPinState(&MODULE_P02, 5, IfxPort_State_toggled);
}
void core0_main(void)
{
IfxCpu_enableInterrupts();
/* !!WATCHDOG0 AND SAFETY WATCHDOG ARE DISABLED HERE!!
* Enable the watchdogs and service them periodically if it is required
*/
IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
IfxScuWdt_disableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());
/* Wait for CPU sync event */
IfxCpu_emitEvent(&g_cpuSyncEvent);
IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
GPTimer_init();
while(1)
{
}
}
二、代码解释
下面我们就对这段代码就行简单的分析和讲解。
IfxPort_setPinMode(&MODULE_P02,5,IfxPort_Mode_outputPushPullGeneral );
上面这行代码中“&MODULE_P02,5”表示设置P02.5端口,这与硬件原理图中的端口对应。“IfxPort_Mode_outputPushPullGeneral”意思是将P02.5端口设置为推挽输出。
IfxGpt12_enableModule(&MODULE_GPT120);
IfxGpt12_setGpt1BlockPrescaler(&MODULE_GPT120,IfxGpt12_Gpt1BlockPrescaler_8);
这两行的作用是使能GPT模块和预分频。因为GPT模块分为GPT1和GPT2,所以底层驱动就命名的时候就将其命名为Gpt12了。使能的意思就是打开GPT模块的开关。预分频是将进入到GPT模块的频率进行缩小。进入GPT模块的频率是100MHz,我们对其进行了1/8的预分频,也就是GPT下属的定时器用到的频率为100/8=12.5MHz。这个频率有什么用处呢,我们后面会讲^_^。
IfxGpt12_T3_setMode(&MODULE_GPT120,IfxGpt12_Mode_timer);
IfxGpt12_T3_setDirectionSource(&MODULE_GPT120,IfxGpt12_TimerDirectionSource_internal);
IfxGpt12_T3_setTimerDirection(&MODULE_GPT120,IfxGpt12_TimerDirection_up);
IfxGpt12_T3_setTimerPrescaler(&MODULE_GPT120,IfxGpt12_TimerInputPrescaler_128);
IfxGpt12_T3_setTimerValue(&MODULE_GPT120,0xFFFF-50000+1);
上面几行代码的作用是设置GPT模块下属的T3定时器。代码的含义从函数的名字就能猜出来,我们讲讲几个比较重要的概念。
IfxGpt12_T3_setDirectionSource(&MODULE_GPT120,IfxGpt12_TimerDirectionSource_internal);
这行代码是设置T3定时器的计数来源。T3定时器的本质就是一个计数器,每来一个周期的震荡T3就是自增或自减一个数,这行代码的作用就是将震荡的来源设定为内部,也就是从T3的上级GPT传过来的震荡。
IfxGpt12_T3_setTimerDirection(&MODULE_GPT120,IfxGpt12_TimerDirection_up);
这行代码就确定了每来一个周期震荡,T3要自增。
IfxGpt12_T3_setTimerPrescaler(&MODULE_GPT120,IfxGpt12_TimerInputPrescaler_128);
这行是将进入到T3的周期震荡的频率继续分频,我们对其进行了128分频,也就是进入到T3的频率为100/8/128=(100/1024)MHz。
IfxGpt12_T3_setTimerValue(&MODULE_GPT120,0xFFFF-50000+1);
这行代码是设定T3定时器的起始值,0xFFFF-50000+1 = 65535-50000+1 =15536。T3定时会以(100/1024)MHz的频率从15536开始自增,一直增长到65535后归零,并且产生一个中断通知处理器。所以我们可以算一下,(100/1024)MHz的频率对应的周期为(1024/100M)秒,也就是10.24微秒。从15536开始到65535归零,一共计数50000次,所以产生一个中断的时间为10.24*50000=512000微秒=512毫秒=0.512秒。我们就利用这0.512秒的间隔实现LED的闪烁。
IfxSrc_init(&SRC_GPT120T3,IfxSrc_Tos_cpu0,10);
IfxSrc_enable(&SRC_GPT120T3);
这两行代码的作用是开通GPT模块的T3定时器的中断服务,并将其优先级定为10。就是允许T3发生溢出的时候通知处理器过来看它一下。优先级的意思是当有多个中断产生的时候,通知处理器优先看哪个中断,防止打架。
IFX_INTERRUPT(GPTimer_isr,0,10);
这行代码定义了优先级为10的中断发生的时候,让处理器干啥。这里就是执行函数“GPTimer_isr()”,这个函数一般称为中断回调函数。
void GPTimer_isr(void)
{
IfxGpt12_T3_setTimerValue(&MODULE_GPT120,0xFFFF-50000+1);
IfxPort_setPinState(&MODULE_P02, 5, IfxPort_State_toggled);
}
这就是中断回调函数的定义,这个中断回调函数就干了两件事,第一将T3定时器重新设定初值;第二翻转P02.5端口的电平,从而实现LED灯的亮灭。
利用定时器实现LED闪烁的程序逻辑就清晰了。LED闪烁的关键步骤仅仅是翻转P02.5的端口电平的瞬间,其他时候不需要操作。而上一节使用英飞凌Aurix系列TC334芯片点亮LED,我们使用同步延时的方法时,在不翻转电平的时候,我们会让处理器执行一堆毫无意义的加法操作,等加法操作执行完了,处理器翻转一下电平。而通过定时器的方法,一旦定时器设定完成,定时器作为一个独立于处理器的外设,可以独立的默默累加计时。这时处理器可以去干其他事情。直到定时器时间到了,溢出了,处理器回来执行一下翻转电平和定时器重置的工作即可。因为定时器的定时周期很准,所以定时稳定且精确。因此该方法同时解决了同步延时的资源浪费和定时不准的问题。
三、下载调试
程序编写完毕后,我们点击任务栏中的编译按钮。
编译完成后,在输出窗口可以看见“编译完成,无错误,无警告”的字样。
然后我们通过Type-C将测试板与你的电脑相连。
点击任务栏中的下载按钮。
下载完成后,在输出窗口可以看见“下载成功”的字样。
此时你就能看见LED等闪烁了。
LED闪烁
总结
今天我们介绍了如何运用TC334芯片GPT外设定时器T3实现对板载LED灯珠的亮灭控制。后续我们将继续介绍如何完成该芯片底层基础模块的基本配置,包括CAN通讯模块,ADC采样模块等。敬请收藏关注。
如需测试板,请点击。
https://store.weixin.qq.com/shop/b/feHVuMfOAmRCoHk?entrance_id=h5
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)