打印
[通用 MCU]

TC264单片机---LED

[复制链接]
68|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本文介绍如何应用Infineon官方提供的免费IDE开发环境AURIX Development Studio和TC264开发板(龙邱科技提供)实现LED的闪烁。

1. AURIX Development Studio
AURIX Development Studio(下简称ADS), 是英飞凌推出在针对自家AURIX芯片的免费编译环境,软件使用无需license,长期免费。该开发环境基于业内流行的Eclipse打造而成,界面非常友好,对于刚刚接触英飞凌的朋友们而言更是易于上手。ADS集成了编译器、调试器、iLLD底层开发库等必备组件,无需开发者四处寻找调试器和底层库代码。ADS的编译器和调试器是基于TASKING编译器、调试器打造而成,稳定性上无需额外担心,调试器比较难用,全当是一个高阶版的下载器吧。

2. 硬件环境
本次实现的硬件环境是用龙邱科技提供的TC264核心板+母版+下载器:



3.代码
3.1新建工程
打开ADAS,选择工作区(略)之后,在File→New,新建AURIX工程



填写工程名称,选择Next下一步:



选择对应的芯片(TC26x B-Step),点击Finish:



在产生的结构树中新建一个“src”文件夹,用于存放自己写的代码:



建立以下代码文件:



3.2 关键代码
先说明下,以下为该开发板默认的LED接口:
LED0p P10_6 龙邱TC母板核心板上LED0 翠绿
LED1p P10_5 龙邱TC母板核心板上LED1 蓝灯
LED2p P20_6 龙邱TC母板上LED0
LED3p P20_7 龙邱TC母板上LED1

3.2.1 LQ_GPIO
为了实现对GPIO引脚的基本操作,先建立LQ_GPIO的头文件,LQ_GPIO主要目的是:

定义相关针脚枚举类GPIO_NAME,如P10_5 = 0xB005(B005的前两位B0实际是Module编号,05实际是PIN的编号)
该地址可参考英飞凌TC264用户手册第十四章《General Purpose I/O Ports and Peripheral I/O Lines (Ports)






如上表,每个Moudule的所有寄存器加起来需要的内存大小有256个字节(00-FF),以下为iLLD中IfxPort_regdef.h中对Port结构体的定义,可以看出共有256字节的相关的寄存器:

Port结构体:

/** \brief  Port object */
typedef volatile struct _Ifx_P
{
    Ifx_P_OUT OUT;                          /**< \brief 0, Port Output Register */
    Ifx_P_OMR OMR;                          /**< \brief 4, Port Output Modification Register */
    Ifx_P_ID ID;                            /**< \brief 8, Identification Register */
    unsigned char reserved_C[4];            /**< \brief C, \internal Reserved */
    Ifx_P_IOCR0 IOCR0;                      /**< \brief 10, Port Input/Output Control Register 0 */
    Ifx_P_IOCR4 IOCR4;                      /**< \brief 14, Port Input/Output Control Register 4 */
    Ifx_P_IOCR8 IOCR8;                      /**< \brief 18, Port Input/Output Control Register 8 */
    Ifx_P_IOCR12 IOCR12;                    /**< \brief 1C, Port Input/Output Control Register 12 */
    unsigned char reserved_20[4];           /**< \brief 20, \internal Reserved */
    Ifx_P_IN IN;                            /**< \brief 24, Port Input Register */
    unsigned char reserved_28[24];          /**< \brief 28, \internal Reserved */
    Ifx_P_PDR0 PDR0;                        /**< \brief 40, Port Pad Driver Mode 0 Register */
    Ifx_P_PDR1 PDR1;                        /**< \brief 44, Port Pad Driver Mode 1 Register */
    unsigned char reserved_48[8];           /**< \brief 48, \internal Reserved */
    Ifx_P_ESR ESR;                          /**< \brief 50, Port Emergency Stop Register */
    unsigned char reserved_54[12];          /**< \brief 54, \internal Reserved */
    Ifx_P_PDISC PDISC;                      /**< \brief 60, Port Pin Function Decision Control Register */
    Ifx_P_PCSR PCSR;                        /**< \brief 64, Port Pin Controller Select Register */
    unsigned char reserved_68[8];           /**< \brief 68, \internal Reserved */
    Ifx_P_OMSR0 OMSR0;                      /**< \brief 70, Port Output Modification Set Register 0 */
    Ifx_P_OMSR4 OMSR4;                      /**< \brief 74, Port Output Modification Set Register 4 */
    Ifx_P_OMSR8 OMSR8;                      /**< \brief 78, Port Output Modification Set Register 8 */
    Ifx_P_OMSR12 OMSR12;                    /**< \brief 7C, Port Output Modification Set Register 12 */
    Ifx_P_OMCR0 OMCR0;                      /**< \brief 80, Port Output Modification Clear Register 0 */
    Ifx_P_OMCR4 OMCR4;                      /**< \brief 84, Port Output Modification Clear Register 4 */
    Ifx_P_OMCR8 OMCR8;                      /**< \brief 88, Port Output Modification Clear Register 8 */
    Ifx_P_OMCR12 OMCR12;                    /**< \brief 8C, Port Output Modification Clear Register 12 */
    Ifx_P_OMSR OMSR;                        /**< \brief 90, Port Output Modification Set Register */
    Ifx_P_OMCR OMCR;                        /**< \brief 94, Port Output Modification Clear Register */
    unsigned char reserved_98[8];           /**< \brief 98, \internal Reserved */
    Ifx_P_LPCR0 LPCR0;                      /**< \brief A0, Port LVDS Pad Control Register 0 */
    Ifx_P_LPCR1 LPCR1;                      /**< \brief A4, Port LVDS Pad Control Register 1 */
    Ifx_P_LPCR2 LPCR2;                      /**< \brief A8, Port LVDS Pad Control Register 2 */
    unsigned char reserved_A4[76];          /**< \brief AC, \internal Reserved */
    Ifx_P_ACCEN1 ACCEN1;                    /**< \brief F8, Port Access Enable Register 1 */
    Ifx_P_ACCEN0 ACCEN0;                    /**< \brief FC, Port Access Enable Register 0 */
} Ifx_P;
定义GPIO的模式,本例最终用的是推挽输出模式
定义宏:根据GPIO_NAME获取Port的Module首地址
定义宏:根据GPIO_NAME获取PIN的编号
声明GPIO的PIN初始化函数_void PIN_InitConfig(GPIO_Name_t pin,IfxPort_Mode mode, uint8 output);_
声明GPIO的PIN的写入函数_void PIN_Write(GPIO_Name_t pin,uint8 output);_通过该函数来更新电平状态,(output为0则高电平,为1则低电平)
声明GPIO的PIN电平翻转函数void PIN_Reverse(GPIO_Name_t pin);


LQ_GPIO的头文件(.h文件)如下:

#ifndef SRC_LQ_GPIO_H_
#define SRC_LQ_GPIO_H_

#include "Platform_Types.h"
#include "IfxPort_regdef.h"
#include "IfxPort.h"

// GPIO Port No.
typedef enum //
{
    P21_4 = 0xC104,
    P21_5 = 0xC105,
    P20_8 = 0xC008,
    P20_9 = 0xC009,
}GPIO_Name_t;

//GPIO Mode
#define PIN_MODE_OUTPUT          IfxPort_Mode_outputPushPullGeneral    /*!< 推挽输出  */
#define PIN_MODE_OUTPUT_OD       IfxPort_Mode_outputOpenDrainGeneral   /*!< 开漏输出  */
#define PIN_MODE_INPUT           IfxPort_Mode_inputNoPullDevice        /*!< 浮空输入  */
#define PIN_MODE_INPUT_PULLUP    IfxPort_Mode_inputPullUp              /*!< 上拉输入  */
#define PIN_MODE_INPUT_PULLDOWN  IfxPort_Mode_inputPullDown            /*!< 下拉输入  */

// Get the GPIO Port Module Base Address
#define PIN_GetModule(GPIO_NAME)    (Ifx_P*)(0xF0030000u | (GPIO_NAME & 0xFF00))
// Get the GPIO Port Pin Index
#define PIN_GetIndex(GPIO_NAME)    (uint8)(GPIO_NAME & 0x000F)

void PIN_InitConfig(GPIO_Name_t pin,IfxPort_Mode mode, uint8 output);
void PIN_Write(GPIO_Name_t pin,uint8 output);
void PIN_Reverse(GPIO_Name_t pin);

#endif /* SRC_LQ_GPIO_H_ */
其中typedef enum中的地址为下图对应的地址



查看原理图,发现开发板的四个等分别是P21.4,P21.5,P20.8,P20.9所以0xC104,0xC105,0xC008,0xC009。这个根据自己开发板而定。



对应的实现源文件(.c文件)是:

#include "LQ_GPIO.h"

void PIN_InitConfig(GPIO_Name_t pin,IfxPort_Mode mode,uint8 output)
{
    Ifx_P *port = PIN_GetModule(pin);
    unsigned char pinIndex = PIN_GetIndex(pin);

    // 配置GPIO模式
    IfxPort_setPinMode(port, pinIndex, mode);
    IfxPort_setPinPadDriver(port, pinIndex, IfxPort_PadDriver_cmosAutomotiveSpeed2);

    /* GPIO输出模式时 输出状态 */
    if (0 == output)
    {
        IfxPort_setPinState(port, pinIndex, IfxPort_State_low);
    }
    else
    {
        IfxPort_setPinState(port, pinIndex, IfxPort_State_high);
    }
}


void PIN_Write(GPIO_Name_t pin,unsigned char output)
{
    Ifx_P *port = PIN_GetModule(pin);
    unsigned char pinIndex = PIN_GetIndex(pin);

    // GPIO output Mode
    if (output == 0)
    {
        IfxPort_setPinState(port, pinIndex, IfxPort_State_low);
    }
    else
    {
        IfxPort_setPinState(port, pinIndex, IfxPort_State_high);
    }
}

void PIN_Reverse(GPIO_Name_t pin)
{
    Ifx_P *port = PIN_GetModule(pin);
    unsigned char pinIndex = PIN_GetIndex(pin);

    IfxPort_togglePin(port, pinIndex);
}
3.2.2 LQ_GPIO_LED
建立LED与GPIO引脚的关系并定义相关操作,编写LQ_GPIO_LED头文件,该头文件主要目的是:

定义LED灯的编号枚举类LEDn_e
定义LED灯的状态枚举类LEDs_e
定义LED灯编号与PIN NAME的对应关系
声明LED初始化函数_void GPIO_LED_Init(void);_
声明LED控制函数_void LED_Ctrl(LEDn_e LEDn,LEDs_e LEDs);_
声明LED测试函数void Test_GPIO_LED(void);
相关头文件(.h文件):

#ifndef SRC_LQ_GPIO_LED_H_
#define SRC_LQ_GPIO_LED_H_

#include "LQ_GPIO.h"

// define enum for LED number
typedef enum
{
    LED0 = 0,
    LED1 = 1,
    LED2 = 2,
    LED3 = 3,
    LED_ALL = 4
} LEDn_e;

// define enum for LED state
typedef enum
{
    ON = 0,
    OFF = 1,
    RVS = 2
}LEDs_e;

// LED and Pin
#define LED0p   P20_8
#define LED1p   P20_9
#define LED2p   P21_4
#define LED3p   P21_5

void GPIO_LED_Init(void);
void LED_Ctrl(LEDn_e LEDn,LEDs_e LEDs);
void Test_GPIO_LED(void);

#endif /* SRC_LQ_GPIO_LED_H_ */
对应的源文件(.c文件):

#include "LQ_GPIO_LED.h"
#include "LQ_STM.h"


void GPIO_LED_Init(void)
{
    // 初始化,输入口,高电平
    PIN_InitConfig(LED0p, PIN_MODE_OUTPUT, 0);
    PIN_InitConfig(LED1p, PIN_MODE_OUTPUT, 0);
    PIN_InitConfig(LED2p, PIN_MODE_OUTPUT, 0);
    PIN_InitConfig(LED3p, PIN_MODE_OUTPUT, 0);
}


void LED_Ctrl(LEDn_e LEDno,LEDs_e sta)
{
    switch(LEDno)
    {
        case LED0:
            if(sta==ON)    PIN_Write(LED0p, 0);
            else if(sta==OFF)    PIN_Write(LED0p, 1);
            else if(sta==RVS)   PIN_Reverse(LED0p);
        break;

        case LED1:
          if(sta==ON)        PIN_Write(LED1p,0);
          else if(sta==OFF) PIN_Write(LED1p,1);
          else if(sta==RVS) PIN_Reverse(LED1p);
        break;

        case LED2:
          if(sta==ON)        PIN_Write(LED2p,0);
          else if(sta==OFF) PIN_Write(LED2p,1);
          else if(sta==RVS) PIN_Reverse(LED2p);
        break;

        case LED3:
          if(sta==ON)        PIN_Write(LED3p,0);
          else if(sta==OFF) PIN_Write(LED3p,1);
          else if(sta==RVS) PIN_Reverse(LED3p);
        break;

        case LED_ALL:
          if(sta==ON)
          {
              PIN_Write(LED0p,0);
              PIN_Write(LED1p,0);
              PIN_Write(LED2p,0);
              PIN_Write(LED3p,0);
          }
          else if(sta==OFF)
          {
              PIN_Write(LED0p,1);
              PIN_Write(LED1p,1);
              PIN_Write(LED2p,1);
              PIN_Write(LED3p,1);
          }
          else if(sta==RVS)
          {
              PIN_Reverse(LED0p);
              PIN_Reverse(LED1p);
              PIN_Reverse(LED2p);
              PIN_Reverse(LED3p);
          }
        break;
        default:
        break;
    }
}

void Test_GPIO_LED(void)
{
    GPIO_LED_Init();
    while(1)
    {
        LED_Ctrl(LED_ALL, RVS);
        delayms(100);
    }
}
3.2.3 LQ_STM
由于实现对LED的翻转闪烁控制,需要实现计时功能,即要借助于TC264的系统定时器(STM),并实现自己的定时功能,LQ_STM实现以下功能:

定义STM枚举类STM_t,包含STM0和STM1,其实这个对应于TC264两个CPU的时钟源,我们这里当然选STM0
声明微妙级的延时函数_void STM_DelayUs(STM_t stm, unsigned long us);_
声明毫秒级的延时函数_void delayms(unsigned short stmms);_


声明两个延时函数:第一个是通过调用iLLD中的IfxStm_getTicksFromMicroseconds函数实现精确的微妙级计时;第二个是调用汇编指令NOP(无操作)实现不怎么精确的计时。
本例中用#if条件汇编指令默认选用第一种方法

头文件(.h文件):

#ifndef LQ_STM_H_
#define LQ_STM_H_

#include "Platform_Types.h"
#include "IfxStm_regdef.h"
#include "IfxStm.h"
#include "IfxStm_cfg.h"

// STM Module enumerate
typedef enum{
    STM0 = 0,
    STM1 = 1
}STM_t;

void STM_DelayUs(STM_t stm, unsigned long us);
void delayms(unsigned short stmms);

# endif
对应的源文件(.c文件):

#include "LQ_STM.h"

// STM Delay
void STM_DelayUs(STM_t stm, uint32 us)
{
    Ifx_STM * STM = IfxStm_getAddress((IfxStm_Index)stm);
    uint32 tick = IfxStm_getTicksFromMicroseconds(STM, us);

    IfxStm_waitTicks(STM, tick);
}


// delay function
void delayms(unsigned short stmms)
{
    #if 1
    // Accurate Delay
    while(stmms--){
        STM_DelayUs(STM0,1000);
    }
    #else
    // Not accurate delay
    volatile unsigned long i = 0;
    while(stmms--)
    {
        for(i=0;i<16580;++i){
            __asm("NOP");
        }
    }
    #endif
}
3.2.4 Cpu0_Main.c
我们只利用Cpu0进行LED的控制,以下为源文件:

#include "LQ_GPIO_LED.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
#include "IfxScuCcu.h"
#include "LQ_STM.h"


IfxCpu_mutexLock mutexCpu0InitIsOk = 1; // Flag of Cpu0 initialization

int core0_main(void)
{
    // Close the CPU Interrupt
    IfxCpu_disableInterrupts();
    // Close the Watch Dog
    IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
    IfxScuWdt_disableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());
    // Initial LED
    GPIO_LED_Init();
    // Open CPU Interrupt
    IfxCpu_enableInterrupts();
    // Tell Cpu1, the Cpu0 finished initialization
    IfxCpu_releaseMutex(&mutexCpu0InitIsOk);

    while(1)
    {
        LED_Ctrl(LED_ALL,RVS);
        delayms(100);
    }
    return (1);
}
3.2.5 Cpu1_Main.c
对应的Cpu1的源文件:

#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"

extern IfxCpu_mutexLock mutexCpu0InitIsOk;

int core1_main(void)
{
    // 开启CPU总中断
    IfxCpu_enableInterrupts();
    // 关闭看门狗
    IfxScuWdt_disableCpuWatchdog (IfxScuWdt_getCpuWatchdogPassword ());
    // 等待CPU0 初始化完成
    while(!IfxCpu_acquireMutex(&mutexCpu0InitIsOk));
    while(1)//主循环
    {

    }
}
4. Build & Debug
注意:在这一步的编译和Debug中,如果提示“找不到FTD2××.dll”,都是因为开发板和电脑没有连接上,可以打开设备管理器,找到对应串口安装

4.1 编译
点击Build按钮,对代码进行编译:



编译结束后,务必保证无Error:



同时,在Debug文件夹下会产生.elf文件,用于debug和下载



4.2 Debug
Debug前,请务必用英飞凌的DAS工具确保硬件与PC通讯连接,连接方法本文不赘述。

点击debug按钮旁边的小三角,选择Debug Configurations



双击TASKING C/C++ Debugger:



① 选择出现的"LQ_GPIO_LED",② 选择默认出现的File,③ 将其删除 ④ 选择Add,在弹出的对话框中添加刚才的.elf文件 ⑤ 点击Debug



弹出对话框,选择“Switch”:



出现Debug界面,可以进行Debug:



4.3 烧录



点击这个就能烧录了。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/A469333242/article/details/134405827

使用特权

评论回复
沙发
suncat0504| | 2024-12-3 20:51 | 只看该作者
基于业内流行的Eclipse打造的话,应该好上手,方便。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

72

主题

4141

帖子

5

粉丝