Funpack第二季第二期:KIT_AURIX_TC275_LITE实现控制改变呼吸灯闪烁频率
AURIX TM TC275 lite 套件配备了基于 32 位单芯片 AURIX TM TriCore TM的微控制器 Aurix TM TC275。它可以与一系列开发工具一起使用,包括 AURIX TM Development Studio、英飞凌免费的基于 Eclipse 的 IDE,或来自 Hightec/PLS/Infineon 的基于 Eclipse 的“FreeEntryToolchain”板子外观如图一所示。
主要特性:
- Arduino 连接器
- Arduino ICSP 连接器
- 稳压器 5V 至 3.3V
- 可选 0 欧姆电阻器(1210 英制中的 R39_opt/R40_opt)
- Arduino 连接器(数字)
- 用于 AURIX™ TM的 20 MHz 晶振和用于 OCDS 的 12 MHz 晶振
- 用于 WIFI/BLE 的 Mikrobus 连接器
- 英飞凌 CAN 收发器 TLE9251VSJ 和 CAN 连接器
- 针连接器 X2
- 电源指示灯 (D5)
- LED D1/D2 用于 ADBUS7/4 和 LED3 用于 ESR0 信号(低电平有效)
- Arduino 针连接器(电源和模拟输入)
- 电位器 (10 kOhm) 和可焊接的 0 Ohm 电阻器(0805 英制中的 R33)
- 微型 USB(推荐 USB3.0)
- 10 针 DAP 连接器
- 复位按钮
- 2 x Shield2GO 连接器,用于 Infineon Maker Shields
- EEPROM 1Kbit
图一.板子外观
图二.板子各模块布局
AURIX™ Development Studio(以下简称ADS)是英飞凌公司于2019年底推出的免费*的集成开发环境,支持英飞凌TriCore™内核AURIX™ 系列MCU;ADS是一个完整的开发环境,包含了Eclipse IDE、C编译器、Multi-core调试器、英飞凌底层驱动库(low-level driver,iLLD),同时对于编辑、编译及调试应用代码没有时间及代码大小的限制。
ADS软件由以下组成:
- AURIX™ Development Studio 1.1.8
- DAS 7.1.9: 英飞凌AURIX™驱动
- iLLD 1.0.1.11.0: 英飞凌底层驱动库
- Oracle JRE11: Java Runtime Environment
- TASKING Debugger v1.1r2 –仅能使用于非商业目的
- TASKING Compiler v1.1r1–仅能使用于非商业目的
- CMake 3.14.0
- GNU Make 4.2.1
- GNU Coreutils 5.3.0
相关论坛/网站:
1)Aurix Forum,英飞凌官方的论坛,都是英文:https://www.infineonforums.com/forums/13-Aurix-Forum?_ga=2.212753875.675854992.1584004040-127082800.1584004040
2)英飞凌汽车电子生态圈:https://www.infineon-autoeco.com/
3)Aurix产品模块公开课程:由昆明理工的姚国仲老师录制,超过50节课时,详细介绍Aurix各个模块,并有动手实验总结:https://videos.infineon-autoeco.com/pc/page/detail/159?id=215 软件界面如如三所示。
图三.软件界面图
2.1软件编写
本项目实现的是任务二
任务二:
设计一个呼吸灯,通过旋转板卡上的电位计,改变呼吸灯闪烁速率,同时将ADC采集的数据通过串口/CAN,发送到另一台设备上显示。任务二主要使用了板子的UART串口,GPIO,定时器模块以及ADC模块,为此,移植了相关驱动程序。
设计逻辑:
我的主要设及逻辑是:
- 是各种驱动模块的移植(PWM,ADC,串口,GPIO)
- PWM实现LED呼吸灯的控制
- 获取电位器的ADC值
- 改变呼吸灯的闪烁周期
- ADC采集值发送到串口
程序部分
- GPIO的PWM驱动移植,参考了官方例程,LED呼吸灯的主要控制函数是void fade_LED(uint32 time);time用来控制呼吸灯闪烁的周期,详细代码如下:
#include "GTM_TOM_PWM.h"
#include "Ifx_Types.h"
#include "IfxGtm_Tom_Pwm.h"
#include "Bsp.h"
/*********************************************************************************************************************/
/*------------------------------------------------------Macros-------------------------------------------------------*/
/*********************************************************************************************************************/
#define ISR_PRIORITY_TOM 20 /* Interrupt priority number */
#define LED IfxGtm_TOM1_4_TOUT14_P00_5_OUT /* LED which will be driven by the PWM */
#define PWM_PERIOD 50000 /* PWM period for the TOM */
#define FADE_STEP PWM_PERIOD / 100 /* PWM duty cycle for the TOM */
/*********************************************************************************************************************/
/*-------------------------------------------------Global variables--------------------------------------------------*/
/*********************************************************************************************************************/
IfxGtm_Tom_Pwm_Config g_tomConfig; /* Timer configuration structure */
IfxGtm_Tom_Pwm_Driver g_tomDriver; /* Timer Driver structure */
uint32 g_fadeValue = 0; /* Fade value, starting from 0 */
sint8 g_fadeDir = 1; /* Fade direction variable */
/*********************************************************************************************************************/
/*-----------------------------------------------Function Prototypes-------------------------------------------------*/
/*********************************************************************************************************************/
void setDutyCycle(uint32 dutyCycle); /* Function to set the duty cycle of the PWM */
/*********************************************************************************************************************/
/*--------------------------------------------Function Implementations-----------------------------------------------*/
/*********************************************************************************************************************/
/* This function initializes the TOM */
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.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 */
//控制呼吸灯的闪烁周期
//time是延迟时间
void fade_LED(uint32 time)
{
for(uint8 i=0;i<=100;i++)
{
setDutyCycle(i*500);
waitTime(IfxStm_getTicksFromMilliseconds(BSP_DEFAULT_TIMER, time)); /* Delay of 10ms */
}
for(uint8 i=100;i>0;i--)
{
setDutyCycle(i*500);
waitTime(IfxStm_getTicksFromMilliseconds(BSP_DEFAULT_TIMER, time));
}
/* Set the duty cycle of the PWM */
}
/* This function creates the fade effect for the LED */
void fadeLED(void)
{
if((g_fadeValue + FADE_STEP) >= PWM_PERIOD)
{
g_fadeDir = -1; /* Set the direction of the fade */
}
else if((g_fadeValue - FADE_STEP) <= 0)
{
g_fadeDir = 1; /* Set the direction of the fade */
}
g_fadeValue += g_fadeDir * FADE_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 */
}
2.UART串口的驱动移植包括串口初始化函数void init_UART(void),详细程序如下:
#include "IfxAsclin_Asc.h"
#include "IfxCpu_Irq.h"
/*********************************************************************************************************************/
/*------------------------------------------------------Macros-------------------------------------------------------*/
/*********************************************************************************************************************/
#define SERIAL_BAUDRATE 115200 /* Baud rate in bit/s */
#define SERIAL_PIN_RX IfxAsclin0_RXA_P14_1_IN /* RX pin of the board */
#define SERIAL_PIN_TX IfxAsclin0_TX_P14_0_OUT /* TX pin of the board */
#define INTPRIO_ASCLIN0_TX 19 /* Priority of the ISR */
#define ASC_TX_BUFFER_SIZE 64 /* Definition of the buffer size */
/*********************************************************************************************************************/
/*-------------------------------------------------Global variables--------------------------------------------------*/
/*********************************************************************************************************************/
IfxAsclin_Asc g_asc; /* Declaration of the ASC handle */
uint8 g_ascTxBuffer[ASC_TX_BUFFER_SIZE + sizeof(Ifx_Fifo) + 8]; /* Declaration of the FIFOs parameters */
/*********************************************************************************************************************/
/*---------------------------------------------Function Implementations----------------------------------------------*/
/*********************************************************************************************************************/
IFX_INTERRUPT(asclin0_Tx_ISR, 0, INTPRIO_ASCLIN0_TX); /* Adding the Interrupt Service Routine */
void asclin0_Tx_ISR(void)
{
IfxAsclin_Asc_isrTransmit(&g_asc);
}
void init_UART(void)
{
/* Initialize an instance of IfxAsclin_Asc_Config with default values */
IfxAsclin_Asc_Config ascConfig;
IfxAsclin_Asc_initModuleConfig(&ascConfig, SERIAL_PIN_TX.module);
/* Set the desired baud rate */
ascConfig.baudrate.baudrate = SERIAL_BAUDRATE;
/* ISR priorities and interrupt target */
ascConfig.interrupt.txPriority = INTPRIO_ASCLIN0_TX;
ascConfig.interrupt.typeOfService = IfxCpu_Irq_getTos(IfxCpu_getCoreIndex());
/* FIFO configuration */
ascConfig.txBuffer = &g_ascTxBuffer;
ascConfig.txBufferSize = ASC_TX_BUFFER_SIZE;
/* Port pins configuration */
const IfxAsclin_Asc_Pins pins =
{
NULL_PTR, IfxPort_InputMode_pullUp, /* CTS pin not used */
&SERIAL_PIN_RX, IfxPort_InputMode_pullUp, /* RX pin not used */
NULL_PTR, IfxPort_OutputMode_pushPull, /* RTS pin not used */
&SERIAL_PIN_TX, IfxPort_OutputMode_pushPull, /* TX pin */
IfxPort_PadDriver_cmosAutomotiveSpeed1
};
ascConfig.pins = &pins;
IfxAsclin_Asc_initModule(&g_asc, &ascConfig); /* Initialize module with above parameters */
}
void send_UART_message(char *tx_data,Ifx_SizeT length)
{
//uint8 txData[] = "Hello World!"; /* Message to send */
// Ifx_SizeT count = 12; /* Size of the message */
IfxAsclin_Asc_write(&g_asc, tx_data, &length, TIME_INFINITE); /* Transfer of data */
}
#include "IfxVadc_Adc.h"
#include "ADC_Single_Channel.h"
#include "GTM_TOM_PWM.h"
/*********************************************************************************************************************/
/*------------------------------------------------------Macros-------------------------------------------------------*/
/*********************************************************************************************************************/
#define LED1 &MODULE_P00, 5 /* LED1 */
#define LED2 &MODULE_P00, 6 /* LED2 */
#define LIMIT_HIGH 0xAAA /* Higher limit to be compared with the measurement */
#define LIMIT_LOW 0x555 /* Lower limit to be compared with the measurement */
#define VADC_GROUP IfxVadc_GroupId_0 /* Use the ADC group 0 */
#define CHANNEL_ID 0 /* Use the Channel 0 */
#define CHANNEL_RESULT_REGISTER 5 /* Use the Result Register 5 */
#define INDEX 0//通道an0
#define TX_LENGTH 21 /* Size of the results message, sent to the user */
#define ASCII_SHIFT 48 /* Shift in the ASCII table: '0', '1', '2'[...], start at value 48 */
#define change_data 0.8057 //电压和测量值的转换 3300/4096
/*********************************************************************************************************************/
/*-------------------------------------------------Global variables--------------------------------------------------*/
/*********************************************************************************************************************/
ApplicationVadcBackgroundScan g_vadcBackgroundScan;
/*********************************************************************************************************************/
/*---------------------------------------------Function Implementations----------------------------------------------*/
/*********************************************************************************************************************/
/* The initialization of the port pins to control the LEDs is done by this function */
void initializeLEDs(void)
{
/* Initialize the Port Pins */
IfxPort_setPinMode(LED1, IfxPort_Mode_outputPushPullGeneral);
IfxPort_setPinMode(LED2, IfxPort_Mode_outputPushPullGeneral);
/* Turn off the LEDs */
IfxPort_setPinHigh(LED1);
IfxPort_setPinHigh(LED2);
}
/* This function retrieves the conversion value and indicates it by LEDs */
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);
if(conversionResult.B.RESULT < LIMIT_LOW) /* LED1 lights up if the conversion value is smaller than 0x555 */
{
IfxPort_setPinLow(LED1);
IfxPort_setPinHigh(LED2);
}
else if(conversionResult.B.RESULT > LIMIT_HIGH) /* LED2 lights up if the conversion value is greater than 0xAAA */
{
IfxPort_setPinHigh(LED1);
IfxPort_setPinLow(LED2);
}
else /* LED1 and LED2 light up if the conversion value is in between */
{
IfxPort_setPinLow(LED1);
IfxPort_setPinLow(LED2);
}
}
void get_adc_Value(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);
send_adc_data(conversionResult.B.RESULT);
}
void send_adc_data( uint32 adcVal)
{
char str[TX_LENGTH] = {'C','h','.','X',':',' ','X','X','X','X',' ',' ','V',':','X','.','X','X','X','\n','\r'}; /* X to be replaced by correct values*/
str[3] = (char) INDEX + ASCII_SHIFT;
uint32 time = 0, voltage = 0;
//最长周期5s对应adc值4096
//最短周期0s对应adc值0
time =50 *adcVal / 4096.0; //计算延迟时间
voltage = adcVal * change_data;
fade_LED(time);
/* Turns the digital converted value into its ASCII characters, e.g. 1054 -> '1','0','5','4' */
/* 12-bits range value: 0-4095 */
str[6] = (adcVal / 1000) + ASCII_SHIFT; /* Thousands */
str[7] = ((adcVal % 1000) / 100) + ASCII_SHIFT; /* Hundreds */
str[8] = ((adcVal % 100) / 10) + ASCII_SHIFT; /* Tens */
str[9] = (adcVal % 10) + ASCII_SHIFT; /* Units */
str[14] = (voltage / 1000) + ASCII_SHIFT; /* Thousands */
str[16] = ((voltage % 1000) / 100) + ASCII_SHIFT; /* Hundreds */
str[17] = ((voltage % 100) / 10) + ASCII_SHIFT; /* Tens */
str[18] = (voltage % 10) + ASCII_SHIFT; /* Units */
/* Print via UART */
send_UART_message(str, TX_LENGTH);
}
/* The VADC module and group are initialized */
void vadcBackgroundScanInit(void)
{
/* VADC module configuration */
/* Create VADC configuration */
IfxVadc_Adc_Config adcConfig;
/* Initialize the VADC configuration with default values */
IfxVadc_Adc_initModuleConfig(&adcConfig, &MODULE_VADC);
/* Initialize the VADC module using the VADC configuration */
IfxVadc_Adc_initModule(&g_vadcBackgroundScan.vadc, &adcConfig);
/* VADC group configuration */
/* Create group configuration */
IfxVadc_Adc_GroupConfig adcGroupConfig;
/* Initialize the group configuration with default values */
IfxVadc_Adc_initGroupConfig(&adcGroupConfig, &g_vadcBackgroundScan.vadc);
/* Define which ADC group is going to be used */
adcGroupConfig.groupId = VADC_GROUP;
adcGroupConfig.master = VADC_GROUP;
/* Enable background scan source */
adcGroupConfig.arbiter.requestSlotBackgroundScanEnabled = TRUE;
/* Enable background auto scan mode */
adcGroupConfig.backgroundScanRequest.autoBackgroundScanEnabled = TRUE;
/* Enable the gate in "always" mode (no edge detection) */
adcGroupConfig.backgroundScanRequest.triggerConfig.gatingMode = IfxVadc_GatingMode_always;
/* Initialize the group using the group configuration */
IfxVadc_Adc_initGroup(&g_vadcBackgroundScan.adcGroup, &adcGroupConfig);
}
/* The input channels to be used are setup and the VADC is set into run mode */
void vadcBackgroundScanRun(void)
{
/* Initialize the channel configuration of application handle g_vadcBackgroundScan with default values */
IfxVadc_Adc_initChannelConfig(&g_vadcBackgroundScan.adcChannelConfig, &g_vadcBackgroundScan.adcGroup);
g_vadcBackgroundScan.adcChannelConfig.channelId = (IfxVadc_ChannelId)CHANNEL_ID;
g_vadcBackgroundScan.adcChannelConfig.resultRegister = (IfxVadc_ChannelResult)CHANNEL_RESULT_REGISTER;
g_vadcBackgroundScan.adcChannelConfig.backgroundChannel = TRUE;
/* Initialize the channel of application handle g_VadcBackgroundScan using the channel configuration */
IfxVadc_Adc_initChannel(&g_vadcBackgroundScan.adcChannel, &g_vadcBackgroundScan.adcChannelConfig);
/* Enable background scan for the channel */
IfxVadc_Adc_setBackgroundScan(&g_vadcBackgroundScan.vadc,
&g_vadcBackgroundScan.adcGroup,
(1 << (IfxVadc_ChannelId)CHANNEL_ID),
(1 << (IfxVadc_ChannelId)CHANNEL_ID));
/* Start background scan conversion */
IfxVadc_Adc_startBackgroundScan(&g_vadcBackgroundScan.vadc);
}
4.主程序首先是串口,pwm,ADC等模块初始化,然后在while(1)内循环运行adc值采集函数,并通过获得的ADC值控制控制LED闪烁周期,详细代码如下
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
#include "GTM_TOM_PWM.h"
#include "Bsp.h"
#include "ADC_Single_Channel.h"
#include "UART_VCOM.h"
/*********************************************************************************************************************/
/*------------------------------------------------------Macros-------------------------------------------------------*/
/*********************************************************************************************************************/
#define WAIT_TIME 10 /* Number of milliseconds to wait between each duty cycle change */
IfxCpu_syncEvent g_cpuSyncEvent = 0;
int 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);
/* Initialize a time variable */
// Ifx_TickTime ticksFor10ms = IfxStm_getTicksFromMilliseconds(BSP_DEFAULT_TIMER, WAIT_TIME);
/* Initialize VADC */
vadcBackgroundScanInit();
/* Start the background scan */
vadcBackgroundScanRun();
/* Initialize GTM TOM module */
initGtmTomPwm();
init_UART(); /* Initialize the module */
while(1)
{
get_adc_Value();
}
return (1);
}
四.结果与总结
4.1结果
板子连接上电脑后,打开AURIX™ Development Studio软件,把程序下载到板子里,打开串口监视器串口波特率设置为115200,通过旋钮控制LED灯,LED灯的闪烁周期发生了变化,同时采集到的ADC值在电脑上的串口助手成功显示,如图四所示。
图四.串口助手接受到的信息
4.2总结
很高兴参加硬禾学堂和得捷电子举办的这一期的活动,学习了英飞凌 AURIX TM TC275 lite 套件如何快速开发的相关知识,主要包括GPIO模块,ADC模块,串口模块,PWM模块等,同时更加熟悉了AURIX™ Development Studio软件的使用,锻炼了阅读芯片手册的能力,以及快速搭建开发环境的能力。