第21章_瑞萨MCU零基础入门系列教程之事件链接控制器ELC

2023-11-04

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id=728461040949

配套资料获取:https://renesas-docs.100ask.net

瑞萨MCU零基础入门系列教程汇总https://blog.csdn.net/qq_35181236/article/details/132779862


第21章 事件链接控制器ELC

本章目标

  • 了解ELC基本概念和RA6M5处理器的ELC模块;
  • 学会使用RASC配置ELC链接不同外设,并触发设备工作;

21.1 ELC简介

21.1.1 ELC的特征

ELC:Event Link Controller,事件链接控制器。它用于链接芯片上两个不同的外设,通过外设A的某个中断事件触发外设B去执行某个动作,这个过程是通过芯片内部硬件信号的连接完成的,不需要占用CPU资源。因而ELC可以帮助开发者完成许多同步触发的工作,而不会引起CPU资源的过多浪费。

ELC支持的事件类型多达219种。当产生了一个ELC事件的时候,也可以触发激活DTC功能。

21.1.2 ELC的系统框图

ECL的系统框图如下图所示:

  1. 事件控制器

  2. ELC相关寄存器:用户可以配置和观察这些寄存器来调试ELC。

  3. ELC支持连接的事件:并不是所有的中断事件都能够用于ELC,只有框图中显示的这些中断事件可以。

1.1.1 支持的事件

ELC支持互相连接触发的外设模块见下表:

  • 外部中断IRQ触发定时器GPT开始计数;
  • 定时器开始计数后,当计数溢出事件产生时,同步触发ADC转换和CTSU的测量模式;
  • 串口中断触发DTC开启数据传输;

这所有的触发操作都是无需CPU干预处理。

21.2 ELC模块的配置

21.2.1 配置ELC模块

ELC本身只是一个连接控制器,不涉及双方设备的设置。具体模块的触发条件,需要去设置该模块。因而在RASC中,ELC的配置很简单,只需要在FSP的“Stacks”中添加ELC的Stack即可,无需额外配置,如下图所示:

击“New Stack”后在“System”中找到“Event Link Controller(r_elc)”添加ELC模块即可(在用户代码里,再去打开、使能它即可)。

对于ELC的Stack配置,只能设置它的名字(使用默认值即可):

21.2.2 配置信息解读

使用RASC配置ELC并生成代码后,在common_data.c中生成一个elc_instance_t结构体类型的全局变量g_elc,它包括ELC控制参数成员、ELC配置信息、ELC控制接口成员。代码如下:

const elc_instance_t g_elc = {
    .p_ctrl = &g_elc_ctrl,
    .p_api  = &g_elc_on_elc,
    .p_cfg  = &g_elc_cfg
};
  • g_elc_ctrl:elc_instance_ctrl_t结构体类型,表明ELC的状态,原型如下:
typedef struct st_elc_instance_ctrl
{
    uint32_t     open;
    void const * p_context;
} elc_instance_ctrl_t;
  • g_elc_on_elc:ELC的控制接口,elc_api_t结构体指针,指向g_elc_on_elc结构体。g_elc_on_elc在r_elc.c中实现:
const elc_api_t g_elc_on_elc =
{
    .open                  = R_ELC_Open,
    .close                 = R_ELC_Close,
    .softwareEventGenerate = R_ELC_SoftwareEventGenerate,
    .linkSet               = R_ELC_LinkSet,
    .linkBreak             = R_ELC_LinkBreak,
    .enable                = R_ELC_Enable,
    .disable               = R_ELC_Disable,
};

这些控制API将会在下一小节进行介绍讲解。

  • g_elc_cfg:ELC的控制配置信息,它是elc_cfg_t结构体指针,此结构体原型如下:
typedef struct st_elc_cfg
{
    elc_event_t const link[ELC_PERIPHERAL_NUM]; ///< Event link register (ELSR) settings
} elc_cfg_t;

此结构体在elc_data.c中生成,以本章外部中断触发定时器开始计数为例,生成的列表内容如下:

const elc_cfg_t g_elc_cfg = {
    .link[ELC_PERIPHERAL_GPT_A] = ELC_EVENT_ICU_IRQ6, /* ICU IRQ6 (External pin interrupt 6) */
    .link[ELC_PERIPHERAL_GPT_B] = ELC_EVENT_ICU_IRQ1, /* ICU IRQ1 (External pin interrupt 1) */
    .link[ELC_PERIPHERAL_GPT_C] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_GPT_D] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_GPT_E] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_GPT_F] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_GPT_G] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_GPT_H] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_ADC0] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_ADC0_B] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_ADC1] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_ADC1_B] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_DAC0] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_DAC1] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_IOPORT1] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_IOPORT2] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_IOPORT3] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_IOPORT4] = ELC_EVENT_NONE, /* No allocation */
    .link[ELC_PERIPHERAL_CTSU] = ELC_EVENT_NONE, /* No allocation */
};
  • 第02行:IRQ6触发ELC_GPTA类事件;
  • 第03行:IRQ1触发ELC_GPTB类事件;

ELC_GPT_A~H是指ELC允许的GPT事件类型名称,如下表所示:

21.2.3 API接口及其使用

在上一小节已经了解到ELC的控制接口,其原型是elc_api_t结构体,如下:

typedef struct st_elc_api
{
    fsp_err_t (* open)(elc_ctrl_t * const p_ctrl, 
                       elc_cfg_t const * const p_cfg);
    fsp_err_t (* close)(elc_ctrl_t * const p_ctrl);
    fsp_err_t (* softwareEventGenerate)(elc_ctrl_t * const p_ctrl, 
                                        elc_software_event_t event_num);
    fsp_err_t (* linkSet)(elc_ctrl_t * const p_ctrl, 
                          elc_peripheral_t peripheral, 
                          elc_event_t signal);
    fsp_err_t (* linkBreak)(elc_ctrl_t * const p_ctrl, 
                            elc_peripheral_t peripheral);
    fsp_err_t (* enable)(elc_ctrl_t * const p_ctrl);
    fsp_err_t (* disable)(elc_ctrl_t * const p_ctrl);
} elc_api_t;

本小节就对这些操作API进行一一介绍讲解。

  1. 打开ELC设备
fsp_err_t (* open)(elc_ctrl_t * const p_ctrl, 
                   elc_cfg_t const * const p_cfg);
  • p_ctrl:elc_ctrl_t结构体类型,此结构体实际上是void类型,实际会指向elc_instance_ctrl_t结构体全局变量g_elc_ctrl;
  • p_cfg:elc_cfg_t结构体类型,实际会指向elc_cfg_t全局常量g_elc_cfg;

open函数的主要功能就是将事件连接列表的设置值,用来初始化ELC模块。可以参考以下代码来初始化ELC设备:

fsp_err_t err = g_elc.p_api->open(g_elc.p_ctrl, g_elc.p_cfg);
if(FSP_SUCCESS != err)
{
    printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);
    return;
}
  1. 关闭ELC设备
fsp_err_t (* close)(elc_ctrl_t * const p_ctrl);

关闭ELC函数实现的功能比较简单,就是将代表ELC的状态成员变量设置为CLOSED,并且失能ELC设备:

/* Set state to closed */
p_instance_ctrl->open = ELC_CLOSED;

/* Globally disable the operation of the Event Link Controller */
R_ELC->ELCR = ELC_ELCR_ELCON_DISABLE;
  1. 使能和失能ELC功能
fsp_err_t (* enable)(elc_ctrl_t * const p_ctrl);
fsp_err_t (* disable)(elc_ctrl_t * const p_ctrl);

只有在使能了ELC的情况下,外设模块的事件触发才能生效。而使能、失能ELC实际上就是对ELC的ELCR寄存器进行控制:

/* Globally enable ELC function */
R_ELC->ELCR = ELC_ELCR_ELCON_ENABLE;

/* Globally disable ELC function */
R_ELC->ELCR = ELC_ELCR_ELCON_DISABLE;
  1. 设置事件链接
fsp_err_t (* linkSet)(elc_ctrl_t * const p_ctrl, 
                      elc_peripheral_t peripheral, 
                      elc_event_t signal);

在初始化设置列表之后,如果要额外添加事件,可以使用这个API。支持的外设列表在r_elc_api.h中的elc_peripheral_t枚举中定义,支持的事件信号类型在bsp_elc.h中的elc_event_t枚举定义。

用户可以参考以下代码使用这个函数:

fsp_err_t err = R_ELC_LinkSet(&g_elc_ctrl, ELC_PERIPHERAL_DAC0, ELC_EVENT_ICU_IRQ10);
if(FSP_SUCCESS != err)
{
    printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);
    return;
}
  1. 断开事件链接
fsp_err_t (* linkBreak)(elc_ctrl_t * const p_ctrl, 
                        elc_peripheral_t peripheral);

断开连接只需要传入需要断开连接的设备序号即可。

  1. 件触发产生事件
fsp_err_t (* softwareEventGenerate)(elc_ctrl_t * const p_ctrl, 
                                    elc_software_event_t event_num);

ELC支持的软件触发事件只有两种,在r_elc_api.h中定义的elc_software_event_t枚举类型里列出了这2种事件:

typedef enum e_elc_software_event
{
    ELC_SOFTWARE_EVENT_0,              ///< Software event 0
    ELC_SOFTWARE_EVENT_1,              ///< Software event 1
} elc_software_event_t;

21.3 外部中断触发GPT启停

本实验会使用到按键外部中断、串口的printf和GPT,请读者阅读前面的章节参考配置相关外设模块。

21.3.1 设计目的

使用两个外部中断来触发GPT定时器计数的开始和停止,让用户了解ELC的使用方法。

21.3.2 模块配置

  1. 外部中断

外部中断在FSP的“Pins”中选好ICU的引脚后,配置各自的Stack如下图示:

本次实验选用的外部中断是IRQ1和IRQ6,使用的引脚是P205和P000。通过ELC使用IRQ触发GPT计数,是通过内部硬件的信号连接来实现的,所以不需要使用外部中断的中断服务函数及其中断回调函数。

  1. LC外设

在前文已经说明,ELC的配置除了模块名称外,并不需要做额外配置。

  1. GPT定时器

GPT定时器的配置除了通道、周期值、计数类型等常规配置如下图所示:

本章的实验还需要配置GPT模块的Input项中关于开启计数触发源和停止计数触发源的设置:

对于开启触发源和停止触发源,里面的可选项是一样的,本次实验使用IRQ6触发定时器开始计数,使用IRQ1触发定时器停止计数,因而“Start Source”和“Stop Source”的配置如下图所示:

image12

21.3.3 驱动程序

  1. 外部中断

外部中断IRQ信号会直接链接触发GPT,因而只需要在RASC中配置IRQ模块,不需要在代码中初始化IRQ。

  1. GPT初始化函数

对于GPT的初始化,只需要调用open、enable函数指针:

void GPTDrvInit(void)
{
    {
        fsp_err_t err = g_timer0.p_api->open(g_timer0.p_ctrl, g_timer0.p_cfg);
        if(FSP_SUCCESS != err)
            printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);
    }
    {
        fsp_err_t err = g_timer0.p_api->enable(g_timer0.p_ctrl);
        if(FSP_SUCCESS != err)
            printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);
    }
}

瑞萨对于GPT的enable函数解释是:“Enables external event triggers that start, stop, clear, or capture the counter.”,也就是使能外部中断事件触发计数器的开始、停止、清除和捕获。

  1. GPT中断回调函数和溢出等待函数

GPT的中断回调函数,只是设置一个溢出标志值,函数代码如下:

static volatile bool gGPTOverflow = false;
/* Callback function */
void gpt_timer0_callback(timer_callback_args_t *p_args)
{
    /* TODO: add your own code here */
    if(p_args->event == TIMER_EVENT_CYCLE_END)
        gGPTOverflow = true;
}

void GPTDrvWaitOverflow(void)
{
    while(!gGPTOverflow);
    gGPTOverflow = false;
}
  1. ELC初始化函数

对于ELC的初始化,只需要调用open、enable函数指针,代码如下:

void ELCDrvInit(void)
{
    {
        fsp_err_t err = g_elc.p_api->open(g_elc.p_ctrl, g_elc.p_cfg);
        if(FSP_SUCCESS != err)
        {
            printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);
            return;
        }
    }
    {
        fsp_err_t err = g_elc.p_api->enable(g_elc.p_ctrl);
        if(FSP_SUCCESS != err)
        {
            printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);
            return;
        }
    }
}`

21.3.4 测试程序

本次实验的测试程序比较简单,每次GPT计数溢出后就计数一次,串口将计数值打印,代码如下:

void ELCAppTest(void)
{
    ELCDrvInit();
    UARTDrvInit();
    GPTDrvInit();
    
    printf("\r\nStart ELC Test!\r\n");
    uint32_t tick = 0;
    while(1)
    {
        GPTDrvWaitOverflow();
        printf("Tick: %d\r", (int)tick++);
    }
}

21.3.5 测试结果

在hal_entry.c中的hal_entry()函数中调用测试函数,将编译出来的二进制文件烧写到板子上运行。按下开发板的按键后,就会触发开启定时器开始计数,将开发板的P205引脚和GND短接后就会触发定时器停止计数:


本章完
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第21章_瑞萨MCU零基础入门系列教程之事件链接控制器ELC 的相关文章

  • python笔记:3.2.2.8pandas数据操作_时间序列范围和偏移量

    coding utf 8 Created on Fri May 24 14 47 40 2019 author User import pandas as pd print n 月末时序索引 pd date range start 2017
  • 浅谈游戏业务遭遇攻击的防护措施

    很多人不禁问DDoS攻击是什么 尤其是对刚入行的新手小白来说 对于这方面完全不懂 那么今天我们就来讲讲它是什么又会造成什么危害 该如何防御 DDoS攻击也叫分布式拒绝服务 Distributed Denial of Service 简称DD
  • Loadrunner 8.1 安装 & 卸载收藏(转载)

    Loadrunner 8 1 安装 1 下载Loadrunner8 1 官方英文版 2 安装Loadrunner8 1 3 破解 http download csdn net source 1348756 l 具体安装操作步骤如下 用虚拟光
  • 华为OD机试 - 数组拼接(Java)

    题目描述 现在有多组整数数组 需要将它们合并成一个新的数组 合并规则 从每个数组里按顺序取出固定长度的内容合并到新的数组中 取完的内容会删除掉 如果该行不足固定长度或者已经为空 则直接取出剩余部分的内容放到新的数组中 继续下一行 输入描述
  • Kali-Linux下载安装

    文章目录 下载 安装 准备 Kali Linux Live U盘安装过程 下载 1 进入kali逛网下载镜像文件kali官网 在Downloads中选择Download Kali Linux 如下图所示 2 根据电脑配置 选择适合自己的版本

随机推荐

  • Svg五角星、太阳花、多边形的绘制

    我们在学习平面几何中 学到了多边形的概念 有多少条边就有多少个顶点 本篇我们介绍一下如何用svg来绘制规则的多边形 比如三角形 五角星和任意多边形 在此 我们用到polygon标签
  • Blender 批量给材质

    妈咪妈咪哄 1 选中需要批量上材质的物体 2 ctrl 加选有目标材质的物体 3 复制材质至选中
  • 神经网络 AI torch 构造自己的数据集(包含标签或者不包含标签)

    AI learning 用于学习train 验证val的图片目录结构形式如下 一般为自己构造的图像数据的目录 这是一个简单的图像二分类问题 两个类别为正常 normal 或者异常 abnormal 数据集分为 train 训练集 val 验
  • 筛选(数组里竖向都为0的删除)

    let arr 0 0 0 0 0 1 5 6 0 0 0 0 0 0 0 0 3 1 5 6 0 0 0 0 0 0 0 0 0 1 5 6 0 4 0 0 0 0 1 0 0 1 5 6 0 0 3 0 0 0 0 0 2 1 5 6
  • VMware-tools安装以及找不到共享文件夹的解决办法

    VMware tools安装以及找不到共享文件夹的解决办法 一 安装VMWare tools 1 以root身份进入linux 2 点击VMWare虚拟机栏目下的安装VMwaretools选项 如果安装过该工具 这个选项会显示为重新安装或者
  • 表的内连接、外连接

    1 内连接 内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选 是使用的最多的连接查询 select 字段 from 表1 inner join 表2 on 连接条件 and 其他条件 一般的写法 select ename d
  • api接口、RPC、WebService分别解决什么问题?

    api接口 RPC WebService分别解决什么问题
  • 深度学习中的迁移学习介绍

    迁移学习 Transfer Learning 的概念早在20世纪80年代就有相关的研究 这期间的研究有的称为归纳研究 inductive transfer 知识迁移 knowledge transfer 终身学习 life long lea
  • Java中的DatagramPacket与DatagramSocket的初步

    1 基本概念 a DatagramPacket与DatagramSocket位于java net包中 b DatagramPacket表示存放数据的数据报 DatagramSocket表示接受或发送数据报的套接字 c 由这两个类所有构成的网
  • 安装GPU版本的pytorch

    前言 最近新建了一个虚拟环境 但是在跑代码的时候出现问题 libc10 cuda so cannot open shared object file No such file or directory 去网上搜了一下 说是安装的pytorc
  • 浅析消费金融风控之贷中、贷前、贷后风控(风控模型、决策引擎)

    消费金融迎来 爆发增长 期 预计到2020年 我国消费信贷总市场规模将达到45万亿元 年复合增长率将达到18 前景广阔的消费金融市场 将成为我国经济发展的重要内驱力 业务痛点 征信体系缺失 分支风控标准不一 欺诈手段层出不穷 多头借贷现象普
  • 谈谈「数据仓库构建与分层」

    1 先导知识之 数据库与ER建模 1 1 数据库 DataBase 数据库是按照数据结构来组织 存储和管理数据的仓库 是一个长期存储在计算机内的 有组织的 可共享的 统一管理的大量数据的集合 数据库是以一定方式储存在一起 能与多个用户共享
  • CentOS7搭建Redis Cluster

    目录 什么是Redis Cluster Redis集群介绍 Redis 集群的数据分片 Redis 集群的主从复制模型 Redis 一致性保证 搭建Redis Cluster 三主三从 准备工作 启动所有节点服务 建立集群关系 验证 集群状
  • 找回误删除的文件

    author skate time 2009 11 19 今天在网上帮个美女恢复数据 他昨天不小心 把重要文件删除 而今天又急用 于是我就帮个小忙用两款数据维护软件DiskGenius EasyRecovery帮其恢复 这两个软件结合使用
  • python自定义标识符_python自定义异常

    python自定义异常 try 异常在try块里抛 如果会产生多个异常 捕捉第一个 匹配except 后边的不再捕捉 except 抓异常 else try无异常 才会执行else finally 无论try块是否抛异常 永远执行的代码 通
  • ZYNQ产品生产拷机问题思考

    目前设计的ZYNQ产品支持QSPIFLASH SDka EMMC启动 主要启动方式主要有以下几种 全部启动文件存放在QSPIFLASH ZYNQ支持的QSPIFLASH为16MB大小 如果UBOOT 内核 设备树 文件系统全部存放在QSPI
  • 爬虫破解js加密破解(二) 有道词典js加密参数 sign破解

    在爬虫过程中 经常给服务器造成压力 比如耗尽CPU 内存 带宽等 为了减少不必要的访问 比如爬虫 网页开发者就发明了反爬虫技术 常见的反爬虫技术有封ip user agent 字体库 js加密 验证码 字符验证码 滑动验证码 点触式验证码等
  • Qt中如何让Widget窗体等子控件随边框自适应缩放

    实现的原则很简单 一切子控件都要在布局中添加 如果是widget作控件 widget内部也要有布局 本文将通过Qt Designer和代码化UI设计两种途径讲解实现方法 一 以Qt Designer为例 想要在这个Widget窗体内部再添加
  • Nginx反向代理与conf原理

    Nginx主要功能 Webservice 反向代理 负载均衡 逻辑上 nginx和server的关系是这样的 Nginx和路由器 交换机有什么区别 路由器是物理网关 nginx是应用层网关 物理上 他们的关系是下图这样的 Nginx hap
  • 第21章_瑞萨MCU零基础入门系列教程之事件链接控制器ELC

    本教程基于韦东山百问网出的 DShanMCU RA6M5开发板 进行编写 需要的同学可以在这里获取 https item taobao com item htm id 728461040949 配套资料获取 https renesas do