大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦全系列MCU(包含Kinetis, LPC, i.MXRT, MCX)的GPIO电平中断设计差异。
在痞子衡旧文 《以i.MXRT1xxx的GPIO模块为例谈谈中断处理函数(IRQHandler)的标准流程》里,痞子衡主要介绍得是 GPIO 一般控制以及最常用的输入边沿中断相关知识。最近恩智浦官方社区有用户反映 i.MXRT1060 上 GPIO 中断状态寄存器(GPIO->ISR)在发生有效电平中断后的置位并不需要手动清零(W1C),其会在 I/O 输入电平状态切换后自动清零,这和手册里描述不一致。
首先在痞子衡的认知里 GPIO 输入电平中断没有什么具体应用场景,想象一下,如果 GPIO 中断事件由输入电平值来触发,如果发生了有效输入电平且其状态不改变,那么 GPIO 中断响应函数就会被不断重复执行(此时 CPU 时间片无法再分给主函数),什么样的任务需要这样的处理呢?暂且不论应用场景,痞子衡今天就从恩智浦全系列 MCU 这方面的行为角度来做一下对比吧。
恩智浦现有的经典 Arm Cortex-M MCU 产品线共有如下五大类,它们在 GPIO 一般控制和中断控制外设上是有差异的。首先 i.MXRT四位数/Kinetis/LPC 这三条线各自是完全不同的外设,然后 i.MXRT三位数是在 LPC 外设基础上做了增强,而最新的 MCX 系列则是组合了 Kinetis 和 LPC 外设。
| 芯片系列 | I/O一般控制 | I/O中断控制 |
|---|---|---|
| Kinetis | GPIO type1 | PORT |
| LPC | GPIO type2 | PINT |
| i.MXRT四位数 | GPIO type3 | GPIO type3 |
| i.MXRT三位数 | GPIO type2 | GPIO type2(增加interrupt A/B) PINT |
| MCX | GPIO type1 | GPIO type1(集成Kinetis PORT) PINT |
根据上一节外设情况我们知道,只要测试了 i.MXRT四位数/Kinetis/LPC 这三个系列的情况,剩下两个系列自然也就不用测试了。
Kinetis 系列分为 K/KL/KE/KS/KW/KV/KM/K32L 等若干子系列,但是它们关于 GPIO 中断设计这一块是一样的。痞子衡选取了 MKL03Z 这颗芯片来做的测试,查看其手册 PORTx->PCRn[ISF] 位或者 PORTx->ISFR 寄存器均标记了中断状态,并且标明了需要做 W1C 操作。
我们可以直接在 \SDK_2.3.1_FRDM-KL03Z\boards\frdmkl03z\driver_examples\gpio\input_interrupt 例程上做测试,只需要做简单修改,痞子衡摘取了主要代码如下。FRDM-KL03Z 板上 SW3 按键对应 PTB5 引脚(按下为低电平,松开为高电平),代码设计里按一次 SW3 便打印一次。测试结果来看,在 Kinetis 上即使是电平中断,PORTx->ISFR 寄存器也是必须要手动清零的,与手册描述一致。
| IRQ函数中是否清零Flag | SW3动作 | IRQ执行情况 | 打印输出结果 |
|---|---|---|---|
| 是 | 上电默认松开(高电平) | IRQ函数未触发 | 无 |
| SW3按下(低电平) | IRQ函数重复执行 | 无 | |
| SW3松开(高电平) | IRQ函数不再触发 | 出现一次打印 | |
| 否 | 上电默认松开(高电平) | IRQ函数未触发 | 无 |
| SW3按下(低电平) | IRQ函数重复执行 | 无 | |
| SW3松开(高电平) | IRQ函数重复执行 | 无 |
volatile bool g_ButtonPress = false;
void PORTB_IRQHandler(void)
{
// 清除中断标志
PORTB->ISFR = 1U << 5U;
g_ButtonPress = true;
}
int main(void)
{
// 省略 PTB5 引脚的 PINMUX 配置
gpio_pin_config_t sw_config = {
kGPIO_DigitalInput, 0,
};
// 仅需此处修改:将 GPIO 中断模式改为低电平触发
PORT_SetPinInterruptConfig(PORTB, 5U, kPORT_InterruptLogicZero);
NVIC_EnableIRQ(PORTB_IRQn);
GPIO_PinInit(GPIOB, 5U, &sw_config);
while (1)
{
if (g_ButtonPress)
{
delay();
PRINTF(" %s is pressed \r\n", "SW3");
g_ButtonPress = false;
}
}
}
i.MXRT四位数系列分为 RT1010/1015/1020/1040/1050/1060/1160/1170/1180 等若干子型号,但是它们关于 GPIO 中断设计是一样的。痞子衡选取了 i.MXRT1062 这颗芯片来做的测试,查看其手册 GPIOx->ISR 寄存器标记了中断状态,同样标明了需要做 W1C 操作。
我们可以直接在 \SDK_2_12_1_EVK-MIMXRT1060\boards\evkmimxrt1060\driver_examples\gpio\input_interrupt 例程上做测试,只需要做简单修改,主要代码如下。MIMXRT1060-EVK 板上 SW8 按键对应 WAKEUP_GPIO5[0] 引脚(按下为低电平,松开为高电平),代码设计里按一次 SW8 便打印一次。测试结果来看,在 i.MXRT 四位数上如果是电平中断,GPIOx->ISR 寄存器会在电平状态切换时自动清零,跟手册描述有点差异,不过这样的设计比 Kinetis 上看起来更合理。
| IRQ函数中是否清零Flag | SW8动作 | IRQ执行情况 | 打印输出结果 |
|---|---|---|---|
| 是/否 | 上电默认松开(高电平) | IRQ函数未触发 | 无 |
| SW8按下(低电平) | IRQ函数重复执行 | 无 | |
| SW8松开(高电平) | IRQ函数不再触发 | 出现一次打印 |
volatile bool g_InputSignal = false;
void GPIO5_Combined_0_15_IRQHandler(void)
{
// 清除中断标志
GPIO5->ISR = 1U << 0U;
g_InputSignal = true;
__DSB();
}
int main(void)
{
// 省略 WAKEUP 引脚的 PINMUX 配置
gpio_pin_config_t sw_config = {
kGPIO_DigitalInput,
0,
kGPIO_IntLowLevel, // 仅需此处修改:将 GPIO 中断模式改为低电平触发
};
GPIO_PortEnableInterrupts(GPIO5, 1U << 0U);
NVIC_EnableIRQ(GPIO5_Combined_0_15_IRQn);
GPIO_PinInit(GPIO5, 0U, &sw_config);
while (1)
{
if (g_InputSignal)
{
delay();
PRINTF(" %s is turned on. \r\n", "SW8");
g_InputSignal = false;
}
}
}
LPC系列分为 800/1x00/4000/4300/51Uxx/54000/5500 等若干子型号,但是它们关于 GPIO 中断设计是一样的。痞子衡选取了 LPC54114 这颗芯片来做的测试,查看其手册 PINT->IST 寄存器标记了中断状态,这里关于 W1C 操作做了边沿方式和电平方式的区别,其中对于电平方式,W1C 是切换有效电平逻辑。
我们可以直接在 \SDK_2_9_0_LPCXpresso54114\boards\lpcxpresso54114\driver_examples\pint\pin_interrupt 例程上做测试,只需要做简单修改,主要代码如下。LPCXpresso-54114 板上 SW1 按键对应 PIO0[24] 引脚(按下为低电平,松开为高电平),代码设计里按一次 SW1 便打印一次。测试结果来看,在 LPC 上如果是电平中断,PINT->IST 寄存器会在电平状态切换时自动清零,跟手册描述有点差异,并且中断处理函数里如果主动加上 W1C 操作其效果就变成了双边沿中断,这样的设计比 i.MXRT 四位数更进了一步。
| IRQ函数中是否清零Flag | SW1动作 | IRQ执行情况 | 打印输出结果 |
|---|---|---|---|
| 否 | 上电默认松开(高电平) | IRQ函数未触发 | 无 |
| SW1按下(低电平) | IRQ函数重复执行 | 无 | |
| SW1松开(高电平) | IRQ函数不再触发 | 出现一次打印 | |
| 是 | 上电默认松开(高电平) | IRQ函数未触发 | 无 |
| SW1按下(低电平) | IRQ函数执行一次 | 出现一次打印 | |
| SW1松开(高电平) | IRQ函数执行一次 | 出现一次打印 |
volatile bool g_ButtonPress = false;
void PIN_INT0_DriverIRQHandler(void)
{
uint32_t pmstatus = PINT_PatternMatchResetDetectLogic(PINT);
if (s_pintCallback[kPINT_PinInt0] != NULL)
{
s_pintCallback[kPINT_PinInt0](kPINT_PinInt0, pmstatus);
}
// 清除中断标志
PINT->IST = (1UL << (uint32_t)kPINT_PinInt0);
__DSB();
}
void pint_intr_callback(pint_pin_int_t pintr, uint32_t pmatch_status)
{
g_ButtonPress = true;
}
int main(void)
{
INPUTMUX_Init(INPUTMUX);
INPUTMUX_AttachSignal(INPUTMUX, kPINT_PinInt0, kINPUTMUX_GpioPort0Pin24ToPintsel);
PINT_Init(PINT);
// 仅需此处修改:将 GPIO 中断模式改为低电平触发
PINT_PinInterruptConfig(PINT, kPINT_PinInt0, kPINT_PinIntEnableLowLevel, pint_intr_callback);
PINT_EnableCallbackByIndex(PINT, kPINT_PinInt0);
while (1)
{
if (g_ButtonPress)
{
delay();
PRINTF(" %s Pin Interrupt event detected \r\n", "SW1");
g_ButtonPress = false;
}
}
}
至此,恩智浦全系列MCU的GPIO电平中断设计差异痞子衡便介绍完毕了,掌声在哪里~~~
文章会同时发布到我的 博客园主页、CSDN主页、知乎主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
基础版云数据库RDS的产品系列包括基础版、高可用版、集群版、三节点企业版,本文介绍基础版实例的相关信息。RDS基础版实例也称为单机版实例,只有单个数据库节点,计算与存储分离,性价比超高。说明RDS基础版实例只有一个数据库节点,没有备节点作为热备份,因此当该节点意外宕机或者执行重启实例、变更配置、版本升级等任务时,会出现较长时间的不可用。如果业务对数据库的可用性要求较高,不建议使用基础版实例,可选择其他系列(如高可用版),部分基础版实例也支持升级为高可用版。基础版与高可用版的对比拓扑图如下所示。优势 性能由于不提供备节点,主节点不会因为实时的数据库复制而产生额外的性能开销,因此基础版的性能相对于
我在我的项目中有一个用户和一个管理员角色。我使用Devise创建了身份验证。在我的管理员角色中,我没有任何确认。在我的用户模型中,我有以下内容:devise:database_authenticatable,:confirmable,:recoverable,:rememberable,:trackable,:validatable,:timeoutable,:registerable#Setupaccessible(orprotected)attributesforyourmodelattr_accessible:email,:username,:prename,:surname,:
我正在尝试创建密码规则来设计可恢复的密码更改。我通过passwords_controller.rb做了一个父类(superclass),但我需要在应用规则之前检查用户角色,但我所拥有的只是reset_password_token。 最佳答案 假设您的模型是用户:User.with_reset_password_token(your_token_here)Source 关于ruby-on-rails-设计通过reset_password_token获取用户,我们在StackOverflow