Funpack2-2 基于TC275的可调呼吸灯设计
基于TC275的呼吸灯,通过旋转板卡上的电位计,改变呼吸灯闪烁速率,同时将ADC采集的数据通过串口,发送到电脑上显示。
标签
嵌入式系统
Funpack
TC275
好喝的娃哈哈
更新2022-10-09
济南大学
444

内容介绍

Funpack2-2项目总结报告

1.板卡介绍

硬禾学堂官方介绍

TC275TP作为第一代 Aurix TC27xT系列产品,专为满足极高的安全标准,同时大幅提高性能而设计。采用创新多核心架构,三个独立的 32 位 TriCore CPU均可工作在200 MHz。可选择多种开发环境,包括Hightec/PLS/Infineon 的基于Eclipse的FreeEntryToolchain,或来自英飞凌基于Eslipse的免费IDE AURIX™ Development Studio,亦或是更多开发工具。

特性:

· 搭载了基于AURIX™ TriCore™ 单片三核微控制器TC275

· 板载Micro USB接口的miniWiggler调试器

· 两个Infineon Shield2Go扩展接口

· 兼容MikroBUS 和Arduino扩展连接

 

· 带有Infineon新一代CAN 收发器TLE9251VSJ ,可用于汽车和工业应用的HS CAN网络开发

· 已焊接可调旋转电位计,用于评估模拟电压的采集

· 一个用户输入按键

· 预留三个LED可作为工作指示灯

板卡图片:

FqoopsZiOw7Mcd2-JR1Ir4aCa8APFrpnxPyKi82_SChiDqbAcdJ4Hu2v

2.设计思路及关键代码

本次做的是任务二,通过旋转板卡上的电位计,改变呼吸灯闪烁速率,并将ADC数据显示在电脑上。对项目需求进行分析,需要控制的部分分为一下几个模块。

  • ADC数据采集
  • PWM波形生成
  • 串口发送

得益于TC275的丰富例程,使得以上几个模块的控制变得较为容易。

首先是ADC数据的采集,代码主要参考ADC_Single_Channel_1_KIT_TC275_LK例程。ADC数据的采集分为以下几个步骤

  • 确定电位器所在的通道及所在组
  • 模块初始化
  • 组初始化
  • 通道初始化
  • 最后循环采样,获取寄存器的值

由于tc275的adc初始化比较固定,只需要配置最后一个通道即可,这里主要参考了ADC_Single_Channel_1_KIT_TC275_LK的代码

初始化adc部分代码

void init_vadc(void)
{
    /* Create and initialize the module configuration */
    IfxVadc_Adc_Config adcConf;                             /* Define a configuration structure for the VADC module */
    IfxVadc_Adc_initModuleConfig(&adcConf, &MODULE_VADC);   /* Fill it with default values                          */

    IfxVadc_Adc_initModule(&g_vadc, &adcConf);              /* Apply the configuration to the module                */

    /* Create and initialize the group configuration */
    IfxVadc_Adc_GroupConfig adcGroupConf;                   /* Define a configuration structure for the VADC group  */
    IfxVadc_Adc_initGroupConfig(&adcGroupConf, &g_vadc);    /* Fill it with default values                          */

    /* Configuration of the group */
    adcGroupConf.groupId = IfxVadc_GroupId_0;               /* Select the group                                     */
    adcGroupConf.master = adcGroupConf.groupId;             /* Select the master group                              */

    adcGroupConf.arbiter.requestSlotScanEnabled = TRUE;     /* Enable scan source                                   */
    adcGroupConf.scanRequest.autoscanEnabled = TRUE;        /* Enable auto scan mode                                */

    /* Enable all gates in "always" mode (no edge detection) */
    adcGroupConf.scanRequest.triggerConfig.gatingMode = IfxVadc_GatingMode_always;

    IfxVadc_Adc_initGroup(&g_adcGroup, &adcGroupConf);      /* Apply the configuration to the group                 */

    /* Create and initialize the channels configuration */
    uint32 chnIx;

    /* Create channel configuration */
    IfxVadc_Adc_ChannelConfig adcChannelConf[N_CHANNELS]; /* Define a configuration structure for the VADC channels */

    for(chnIx = 0; chnIx < N_CHANNELS; ++chnIx)
    {
        IfxVadc_Adc_initChannelConfig(&adcChannelConf[chnIx], &g_adcGroup);     /* Fill it with default values      */

        adcChannelConf[chnIx].channelId = g_vadcChannelIDs[chnIx];              /* Select the channel ID            */
        adcChannelConf[chnIx].resultRegister = (IfxVadc_ChannelResult)(chnIx);  /* Use dedicated result register    */

        /* Initialize the channel */
        IfxVadc_Adc_initChannel(&g_adcChannel[chnIx], &adcChannelConf[chnIx]);

        /* Add the channel to the scan sequence */
        uint32 enableChnBit = (1 << adcChannelConf[chnIx].channelId);   /* Set the the corresponding input channel  */
        uint32 mask = enableChnBit;                                     /* of the respective group to take part in  */
        IfxVadc_Adc_setScan(&g_adcGroup, enableChnBit, mask);           /* the background scan sequence.            */
    }

    /* Start the scan */
    IfxVadc_Adc_startScan(&g_adcGroup);

adc的运行部分代码

void run_vadc(void)
{
    uint32 chnIx;

    /* Get the VADC conversions */
    for(chnIx = 0; chnIx < N_CHANNELS; ++chnIx)
    {
        Ifx_VADC_RES conversionResult;

        /* Wait for a new valid result */
        do
        {
            conversionResult = IfxVadc_Adc_getResult(&g_adcChannel[chnIx]);
        } while(!conversionResult.B.VF); /* B for Bitfield access, VF for Valid Flag */

        /* Print the conversion to the UART */
        send_vadc(chnIx, conversionResult.B.RESULT);
    }
}

其次是pwm波形的形成,PWM输出使用了GTM,也就是通用定时器的PWM模式输出。代码主要参考GTM_TOM_PWM_1_KIT_TC275_LK。

IfxGtm_Tom_Pwm_Config g_tomConfig;
IfxGtm_Tom_Pwm_Driver g_tomDriver;

void PWM_Init(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);
}

// duty should be between 0 and 100
void PWM_SetDuty(uint8_t dutyCycle) {
    g_tomConfig.dutyCycle = dutyCycle * PWM_PERIOD / 100;           /* Change the value of the duty cycle           */
    IfxGtm_Tom_Pwm_init(&g_tomDriver, &g_tomConfig);                /* Re-initialize the PWM                        */
}

然后是uart数据的发送,这个是主要参考了ASCLIN_UART_1_KIT_TC275_LK例程。

/* This function initializes the ASCLIN UART module */
void Uart_Init(void) {
    /* Initialize an instance of IfxAsclin_Asc_Config with default values */
    IfxAsclin_Asc_Config ascConfig;
    IfxAsclin_Asc_initModuleConfig(&ascConfig, &MODULE_ASCLIN0);

    /* Set the desired baud rate */
    ascConfig.baudrate.baudrate = 115200;

    /* ISR priorities and interrupt target */
    ascConfig.interrupt.txPriority = INTPRIO_ASCLIN0_TX;
    ascConfig.interrupt.rxPriority = INTPRIO_ASCLIN0_RX;
    ascConfig.interrupt.typeOfService = IfxCpu_Irq_getTos(IfxCpu_getCoreIndex());

    /* FIFO configuration */
    ascConfig.txBuffer = &g_ascTxBuffer;
    ascConfig.txBufferSize = UART_TX_BUFFER_SIZE;
    ascConfig.rxBuffer = &g_ascRxBuffer;
    ascConfig.rxBufferSize = UART_RX_BUFFER_SIZE;

    /* Pin configuration */
    const IfxAsclin_Asc_Pins pins = {
            .rx        = &UART_PIN_RX,
            .rxMode    = IfxPort_InputMode_noPullDevice,
            .tx        = &UART_PIN_TX,
            .txMode    = IfxPort_OutputMode_pushPull,
            .cts       = NULL_PTR,
            .ctsMode   = IfxPort_InputMode_noPullDevice,
            .rts       = NULL_PTR,
            .rtsMode   = IfxPort_OutputMode_pushPull,
            .pinDriver = IfxPort_PadDriver_cmosAutomotiveSpeed1
    };
    ascConfig.pins = &pins;

    IfxAsclin_Asc_initModule(&g_ascHandle, &ascConfig); /* Initialize module with above parameters */
}

void Uart_SendStr(char* str) {
    Ifx_SizeT len = (Ifx_SizeT)strlen(str);
    IfxAsclin_Asc_write(&g_ascHandle, str, &len, TIME_INFINITE);   /* Transmit data via TX */
}

最后就是将他们组合到一起,实现基本功能

    while(1) {
        // adc value should be between 0 and 4095
        // 基准时间:adc_val = 2048, 呼吸灯周期2s,每个占空比延时10ms
        // 最短周期:adc_val = 0, 呼吸灯周期0.5s,每个占空比延时2.5ms
        // 最长周期:adc_val = 4095,呼吸灯周期8s,每个占空比延时40ms
        // 每个占空比延时t = 2.5 + adc_val
        // 500ms上报ADC数值
        for (uint8_t i = 0; i < 100; i++) {
            PWM_SetDuty(i);
            adc_val = Adc_GetValue();
            delay = 2.5 * pow(2, adc_val / 1024.0);
            Timer_Delayms(delay);
            send_count += delay;
            if (send_count >= 500) {
                send_count -= 500;
                sprintf(ch, "adc_val:%d\r\n", (int)adc_val);
                Uart_SendStr(ch);
            }
        }
        for (uint8_t i = 100; i > 0; i--) {
            PWM_SetDuty(i);
            delay = 2.5 * pow(2, adc_val / 1024.0);
            Timer_Delayms(delay);
            send_count += delay;
            if (send_count >= 500) {
                send_count -= 500;
                sprintf(ch, "adc_val:%d\r\n", (int)adc_val);
                Uart_SendStr(ch);
            }
        }
    }

3.图片展示

FnxENy34r1ibS2ZF5gyGIvHUysL4FkB0-oG_Hwy9fnV92n9IsJ-r0wpj

 

4.活动总结

感谢硬禾学堂提供的这次机会,能够学到很多关于英飞凌板卡的应用,板卡具有三个核心,例程丰富,可以较快的完成开发。

附件下载

funpack.zip

团队介绍

好喝的娃哈哈

评论

0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号