一、项目描述
1.1 开发板资源介绍
本次Funpack2-2活动使用的是英飞凌Aurix TC275 Lite板卡。该板卡板载仿真调试器,可直接通过micro-usb线连接电脑进行调试。板卡框架图如图1-1所示。
图1-1 Aurix TC275 Lite框架图
本开发套件电路板俯视图如图1-2所示,可以看出该套件资源十分丰富,且板载连接器多,可扩展性强,具体包括:
- Arduino 连接器
- 用于 WIFI/BLE 的 Mikrobus 连接器
- 2 x Shield2GO 连接器,用于 Infineon Maker Shields
- 电位器 (10 kOhm)
- LED D1/D2 用于 ADBUS7/4 和 LED3 用于 ESR0 信号
- 英飞凌 CAN 收发器 TLE9251VSJ 和 CAN 连接器
- Micro USB(USB3.0)
- 10 针 DAP 连接器
- 复位按钮和一个用户按钮
- EEPROM 1Kbit
图1-2 Aurix TC275 Lite电路板俯视图
TC275拥有三个独立的32 位 TriCore CPU,其中包含两个TC1.6P核和一个TC1.6E核。P核即性能核,拥有一个额外的循环流水线,一个智能分支预测器,可以并行执行三条指令,与以相同速度运行的核心相比,执行速度提高了约15-25%。TC275主频高达200MHz,且拥有2个锁步核,锁步核在异相的两个时钟周期与主核执行相同的指令,如果核心之间任何指令的结果不一致,则会引发异常。由于其高实时性能、嵌入式安全和安全功能,TriCore family是汽车应用的理想平台。这些包括动力系统发动机管理和变速器、电动和混合动力车辆、底盘领域、制动系统、电动动力转向系统、安全气囊、连接和高级驾驶员辅助系统,以支持自动、清洁汽车的趋势。
2.2 任务描述及实现
本次活动我实现的是任务二:设计一个呼吸灯,通过旋转板卡上的电位计,改变呼吸灯闪烁速率,同时将ADC采集的数据通过串口/CAN,发送到另一台设备上显示。
本项目实现的逻辑框图如图2-1所示。主要实现逻辑为:
- 10ms周期通过ADC的AN0通道获取电位器R32上的电压。
- 将ADC值均分为16个闪烁等级,用来改变LED闪烁频率。
- 将ADC值和闪烁等级通过UART传输给PC,使用串口上位机查看。
图2-1 功能实现逻辑框图
本项目使用的编译环境为英飞凌基于Eslipse的免费IDE AURIX™ Development Studio,简称ADS。在ADS中,英飞凌提供了许多基于此开发套件的iLLD详细例程,我也是基于这些例程进行学习的,主要使用的模块有GPT12,GTM,VADC,ASCLIN。
首先介绍一下GPT12模块,通用定时器单元块GPT1和GPT2具有非常灵活的多功能定时器结构,可用于定时、事件计数、脉冲宽度测量、脉冲产生、频率乘法和其他目的。在本项目中使用它的定时器模式来配置一个10ms的中断,用来实现adc和串口的10ms调度。
PWM的产生使用GTM实现,通用计时器模块(GTM)是一个模块化计时器单元。它有一个内置的定时器输出模块(TOM),可以提供多达16个独立的通道来产生输出信号。时钟管理单元(CMU)负责GTM的时钟生成。固定时钟生成(FXU)是它的子单元之一,它为GTM模块提供了5个预定义的不可配置的时钟。
ADC的采集使用VADC模块,TC275使用逐次逼近原理提供一系列模拟输入通道(每个ADC最多8个)连接到模拟/数字转换器集群(最多11个)。且VADC可有多个请求源请求,如排队、扫描或后台扫描源。
串口由ASCLIN模块实现,异步/同步接口(ASCLIN)模块实现与外部设备的异步/同步串行通信。其中,它支持异步接收/传输(UART)通信,收发可由一个引脚来实现。
二、主要代码片段及说明
首先具体的功能实现逻辑函数都是10ms调度一次,在这里我将GPT12模块配置为定时器模式,10ms会产生一次中断,在中断中对全局变量Task10msFlag计数,并在main函数的while(1)中对该变量进行判断,在到达计数时清零并调用对应函数。
函数initGpt12Timer()用于初始化GPT12定时器。interruptGpt12()为中断函数。
uint8 Task10msFlag = 0;
/* Macro defining the Interrupt Service Routine */
IFX_INTERRUPT(interruptGpt12, 0, ISR_PRIORITY_GPT12_TIMER);
/* Function to initialize the GPT12 and start the timer */
void initGpt12Timer(void)
{
/* Initialize the GPT12 module */
IfxGpt12_enableModule(&MODULE_GPT120); /* Enable the GPT12 module */
IfxGpt12_setGpt1BlockPrescaler(&MODULE_GPT120, IfxGpt12_Gpt1BlockPrescaler_16); /* Set GPT1 block prescaler */
/* Initialize the Timer T3 */
IfxGpt12_T3_setMode(&MODULE_GPT120, IfxGpt12_Mode_timer); /* Set T3 to timer mode */
IfxGpt12_T3_setTimerDirection(&MODULE_GPT120, IfxGpt12_TimerDirection_down); /* Set T3 count direction */
IfxGpt12_T3_setTimerPrescaler(&MODULE_GPT120, IfxGpt12_TimerInputPrescaler_64); /* Set T3 input prescaler */
IfxGpt12_T3_setTimerValue(&MODULE_GPT120, RELOAD_VALUE); /* Set T3 start value */
/* Initialize the Timer T2 */
IfxGpt12_T2_setMode(&MODULE_GPT120, IfxGpt12_Mode_reload); /* Set T2 to reload mode */
IfxGpt12_T2_setReloadInputMode(&MODULE_GPT120, IfxGpt12_ReloadInputMode_bothEdgesTxOTL); /* Set reload trigger */
IfxGpt12_T2_setTimerValue(&MODULE_GPT120, RELOAD_VALUE); /* Set T2 reload value */
/* Initialize the interrupt */
volatile Ifx_SRC_SRCR *src = IfxGpt12_T3_getSrc(&MODULE_GPT120); /* Get the interrupt address */
IfxSrc_init(src, ISR_PROVIDER_GPT12_TIMER, ISR_PRIORITY_GPT12_TIMER); /* Initialize service request */
IfxSrc_enable(src); /* Enable GPT12 interrupt */
IfxGpt12_T3_run(&MODULE_GPT120, IfxGpt12_TimerRun_start); /* Start the timer */
}
/* Interrupt Service Routine of the GPT12 */
void interruptGpt12(void)
{
Task10msFlag++;
}
函数initGtmTomPwm() 用来初始化TOM模块,主要含两步:调用IfxGtm_enable()使能GTM;调用IfxGtm_Cmu_enableClocks()使能FXU时钟。函数fadeLED()根据传入参数来修改PWM占空比的步进值。
void initGtmTomPwm(void)
{
IfxGtm_enable(&MODULE_GTM); /* Enable GTM */
IfxGtm_Cmu_enableClocks(&MODULE_GTM, IFXGTM_CMU_CLKEN_FXCLK); /* Enable the FXU clock */
/* Initialize the configuration structure with default parameters */
IfxGtm_Tom_Pwm_initConfig(&g_tomConfig, &MODULE_GTM);
g_tomConfig.tom = LED.tom; /* Select the TOM depending on the LED */
g_tomConfig.tomChannel = LED.channel; /* Select the channel depending on the LED */
g_tomConfig.period = PWM_PERIOD; /* Set the timer period */
g_tomConfig.dutyCycle = PWM_PERIOD / 2;
g_tomConfig.pin.outputPin = &LED; /* Set the LED port pin as output */
g_tomConfig.synchronousUpdateEnabled = TRUE; /* Enable synchronous update */
IfxGtm_Tom_Pwm_init(&g_tomDriver, &g_tomConfig); /* Initialize the GTM TOM */
IfxGtm_Tom_Pwm_start(&g_tomDriver, TRUE); /* Start the PWM */
}
/* This function creates the fade effect for the LED */
void fadeLED(uint16 step)
{
if((g_fadeValue + step) >= PWM_PERIOD)
{
g_fadeDir = -1; /* Set the direction of the fade */
}
else if((g_fadeValue - step) <= 0)
{
g_fadeDir = 1; /* Set the direction of the fade */
}
g_fadeValue += g_fadeDir * step; /* Calculation of the new duty cycle */
setDutyCycle(g_fadeValue); /* Set the duty cycle of the PWM */
}
/* This function sets the duty cycle of the PWM */
void setDutyCycle(uint32 dutyCycle)
{
g_tomConfig.dutyCycle = dutyCycle; /* Change the value of the duty cycle */
IfxGtm_Tom_Pwm_init(&g_tomDriver, &g_tomConfig); /* Re-initialize the PWM */
}
函数indicateConversionValue()为主要的功能实现函数,当adc的结果寄存器标志位有效时,将adc值右移8位以获取均分的16个闪烁等级,将闪烁等级乘上一个放大倍数传入函数fadeLED()中,以实现改变LED闪烁的快慢,再通过函数printf()将adc值和闪烁等级发送给上位机。
void indicateConversionValue(void)
{
Ifx_VADC_RES conversionResult;
/* Retrieve the conversion value until valid flag of the result register is true */
do
{
conversionResult = IfxVadc_Adc_getResult(&g_vadcBackgroundScan.adcChannel);
}while (!conversionResult.B.VF);
g_adcVal = conversionResult.B.RESULT;
g_blinkLevel = ((g_adcVal + 1) >> 8) + 1;
fadeLED(g_blinkLevel * 150);
printf("adc:%d, %d\n", g_adcVal, g_blinkLevel);
}
三、功能展示及说明
当adc值变高时,led1的闪烁频率将增加。当达到最高4095时,此时闪烁等级为17。
当adc值减小时,呼吸灯闪烁变慢,adc值为0时,此时闪烁地最慢,闪烁等级为1。
四、心得体会
本人是一名在职的汽车嵌入式软件工程师,工作内容以AUTOSAR为主,使用的芯片主要是瑞萨的RH850系列,当初在硬禾学堂看到这个活动时就有了极大的兴趣,TC275这款芯片在汽车上也有很多的应用,让我对英飞凌的产品有了进一步的了解,且返券的活动形式对于大多数人,特别是学生有了很大的帮助,不仅能够学到技术,也不用担心开发板昂贵售价,希望硬禾越办越好!