截图:

链接:
https://wokwi.com/projects/413880919557075969
代码:
// 此程序仅供cslg单片机课程1624221,1624222演示用
// 在Arduino Mega 2560(或任何其他基于AVR微控制器的Arduino板)上,
// 中断函数(Interrupt Service Routine, ISR)中使用延时函数(如delay())是不推荐的,
// 甚至可能是危险的。
const int ledPin = 13; // 定义LED连接的引脚为13
const int buttonPin = 2; // 定义按钮连接的引脚为2,对应interrupt 0
char ledc = 0, leda = 8, ledi = 0, leds = 0; // 定义快闪中断配置变量
volatile boolean buttonState = LOW; // 定义一个易失性布尔变量,用于在ISR和主程序之间传递状态
// 自定义延时函数,将毫秒转换为微秒并分段延时
void zhangrelaydelay(unsigned int delay_ms) {
// 将毫秒转换为微秒
unsigned long delay_us = delay_ms * 1000;
// 定义每次delayMicroseconds()调用的最大微秒数
// (根据平台可能有所不同,但通常1000或更少是安全的)
const unsigned int max_micros_per_call = 1000;
// 循环直到达到所需的总延时
while (delay_us > 0) {
// 计算本次循环应该延时的微秒数
unsigned int current_delay_us = min(delay_us, max_micros_per_call);
// 使用delayMicroseconds()进行延时
delayMicroseconds(current_delay_us);
// 更新剩余的延时
delay_us -= current_delay_us;
}
}
void setup() {
pinMode(ledPin, OUTPUT); // 设置LED引脚为输出模式
pinMode(buttonPin, INPUT_PULLUP); // 设置按钮引脚为输入模式,并启用内部上拉电阻
// 设置外部中断,当buttonPin引脚状态变化时调用buttonISR函数
attachInterrupt(digitalPinToInterrupt(buttonPin), buttonISR, CHANGE);
}
void loop() {
digitalWrite(ledPin, HIGH); // 慢闪烁5s亮
delay(5000); // 延时5秒
digitalWrite(ledPin, LOW); // 5s灭
delay(5000); // 延时5秒
}
// 中断服务程序(ISR)
void buttonISR() {
// 在ISR中切换快闪状态
leds = digitalRead(ledPin); // 读取当前LED状态
for (ledc = 0; ledc < leda; ledc++) { // 循环控制快闪次数(由leda决定)
digitalWrite(ledPin, HIGH); // 中断触发时LED亮
for (ledi = 0; ledi < leda; ledi++) { // 内部循环控制亮的时间(由leda决定,但此处延时固定为100ms)
zhangrelaydelay(100); // 延时100ms
}
digitalWrite(ledPin, LOW); // LED灭
for (ledi = 0; ledi < leda; ledi++) { // 内部循环控制灭的时间(由leda决定,但此处延时固定为10000ms即10s,逻辑上可能不合理)
zhangrelaydelay(10000); // 延时10000ms(10秒)
}
}
digitalWrite(ledPin, leds); // 恢复LED到中断前的状态
}
中文注释说明:
- 全局变量:
ledPin
:定义LED连接的引脚。buttonPin
:定义按钮连接的引脚。ledc
,leda
,ledi
,leds
:用于控制快闪模式的变量,其中leda
可能用于控制循环次数,ledc
和ledi
为循环计数器,leds
用于保存LED中断前的状态。buttonState
:用于在ISR和主程序之间传递按钮状态(虽然在此代码中未实际使用)。
- 自定义延时函数:
zhangrelaydelay
:将毫秒转换为微秒,并分段使用delayMicroseconds
进行延时,以避免在ISR中直接使用delay
函数。
setup
函数:- 设置LED引脚为输出模式。
- 设置按钮引脚为输入模式,并启用内部上拉电阻。
- 绑定外部中断,当按钮引脚状态变化时调用
buttonISR
函数。
loop
函数:- 实现LED的慢闪烁,每5秒亮灭一次。
buttonISR
函数:- 中断服务程序,当按钮状态变化时触发。
- 读取当前LED状态并保存。
- 通过嵌套循环控制LED的快闪模式,但内部循环的延时设置可能不符合实际需求(如灭的时间固定为10秒,可能过长)。
- 恢复LED到中断前的状态。
注意事项:
- 在ISR中使用延时函数(即使是自定义的
zhangrelaydelay
)仍然是不推荐的,因为这可能导致主程序响应延迟或其他不可预测的行为。 buttonISR
中的快闪逻辑可能需要根据实际需求进行调整,特别是灭的时间设置。leda
变量在此代码中用于控制循环次数,但其具体作用可能需要根据实际代码逻辑进一步确认。
Wokwi Arduino Mega 2560 外部中断案例:KeyInterrupt
项目概述
本案例演示了如何在Arduino Mega 2560上使用外部中断来控制LED的闪烁模式。当按下连接到特定引脚的按钮时,会触发中断服务程序(ISR),从而改变LED的闪烁状态。此示例中,主程序让LED以5秒的间隔慢闪烁,而中断服务程序则让LED快速闪烁一段时间,然后恢复到原来的状态。
硬件需求
- Arduino Mega 2560
- LED
- 按钮(开关)
- 电阻(如10kΩ,用于上拉电阻,如果使用内部上拉则不需要)
- 面包板和连接线
电路连接
- LED连接:
- 将LED的正极(长引脚)连接到Arduino Mega 2560的数字引脚13。
- 将LED的负极(短引脚)连接到Arduino的GND。
- 按钮连接:
- 将按钮的一端连接到Arduino的数字引脚2。
- 将按钮的另一端连接到Arduino的GND。
- 如果不使用内部上拉电阻,可以在按钮和Arduino的5V之间连接一个10kΩ的电阻。
软件实现
以下是完整的Arduino代码,包括详细注释:
cpp复制代码
// 此程序仅供cslg单片机课程1624221,1624222演示用 | |
// 在Arduino Mega 2560上,中断函数中使用延时函数是不推荐的,但本例用于演示目的 | |
const int ledPin = 13; // 定义LED连接的引脚为13 | |
const int buttonPin = 2; // 定义按钮连接的引脚为2,对应interrupt 0 | |
char ledc = 0, leda = 8, ledi = 0, leds = 0; // 定义快闪中断配置变量 | |
volatile boolean buttonState = LOW; // 定义一个易失性布尔变量,用于在ISR和主程序之间传递状态(本例中未实际使用) | |
// 自定义延时函数,将毫秒转换为微秒并分段延时 | |
void zhangrelaydelay(unsigned int delay_ms) { | |
unsigned long delay_us = delay_ms * 1000; | |
const unsigned int max_micros_per_call = 1000; | |
while (delay_us > 0) { | |
unsigned int current_delay_us = min(delay_us, max_micros_per_call); | |
delayMicroseconds(current_delay_us); | |
delay_us -= current_delay_us; | |
} | |
} | |
void setup() { | |
pinMode(ledPin, OUTPUT); // 设置LED引脚为输出模式 | |
pinMode(buttonPin, INPUT_PULLUP); // 设置按钮引脚为输入模式,并启用内部上拉电阻 | |
// 设置外部中断,当buttonPin引脚状态变化时调用buttonISR函数 | |
attachInterrupt(digitalPinToInterrupt(buttonPin), buttonISR, CHANGE); | |
} | |
void loop() { | |
digitalWrite(ledPin, HIGH); // 慢闪烁5s亮 | |
delay(5000); // 延时5秒 | |
digitalWrite(ledPin, LOW); // 5s灭 | |
delay(5000); // 延时5秒 | |
} | |
// 中断服务程序(ISR) | |
void buttonISR() { | |
leds = digitalRead(ledPin); // 读取当前LED状态 | |
for (ledc = 0; ledc < leda; ledc++) { // 循环控制快闪次数(由leda决定) | |
digitalWrite(ledPin, HIGH); // 中断触发时LED亮 | |
for (ledi = 0; ledi < leda; ledi++) { // 内部循环控制亮的时间(此处延时固定为100ms) | |
zhangrelaydelay(100); // 延时100ms | |
} | |
digitalWrite(ledPin, LOW); // LED灭 | |
for (ledi = 0; ledi < leda; ledi++) { // 内部循环控制灭的时间(此处延时固定为10000ms即10s) | |
zhangrelaydelay(10000); // 延时10000ms(10秒),注意:这可能导致ISR执行时间过长 | |
} | |
} | |
digitalWrite(ledPin, leds); // 恢复LED到中断前的状态 | |
} |
注意事项
-
中断中的延时:在中断服务程序中使用延时函数(即使是自定义的)通常是不推荐的,因为它会阻塞其他中断的执行,并可能导致系统响应延迟。在本例中,为了演示目的而使用了延时,但在实际应用中应尽量避免。
-
中断逻辑:中断服务程序中的快闪逻辑可能需要根据实际需求进行调整。特别是灭的时间设置为10秒可能过长,导致LED长时间保持熄灭状态。
-
硬件去抖动:按钮在按下和释放时可能会产生抖动,导致中断多次触发。在实际应用中,可能需要添加硬件去抖动电路或软件去抖动逻辑。
-
Wokwi仿真:在Wokwi等在线仿真平台上测试此代码时,请注意仿真环境可能无法完全模拟实际硬件行为,特别是中断响应时间和延时函数的准确性。
结论
本案例展示了如何在Arduino Mega 2560上使用外部中断来控制LED的闪烁模式。通过按下按钮触发中断服务程序,可以改变LED的闪烁状态。然而,在实际应用中,应谨慎使用中断中的延时函数,并考虑添加去抖动逻辑以提高系统的稳定性和可靠性。
Wokwi Arduino Mega 2560 中断系统详细课程教程
一、课程概述
本课程将详细介绍 Arduino Mega 2560 的中断系统,包括中断的基本概念、中断引脚、中断模式、中断服务程序(ISR)的编写,以及如何在 Wokwi 平台上进行中断系统的仿真和调试。通过本课程的学习,学员将掌握如何利用中断系统实现实时响应外部事件的功能。
二、课程内容
1. 中断系统基础
- 中断的概念:中断是单片机在执行主程序的过程中,由于某种外部或内部事件的需要,暂时中止当前程序的执行,转而执行一段特定的处理程序(ISR),处理完毕后再返回原程序继续执行的过程。
- 中断的优点:
- 实时控制:能够立即响应外部事件。
- 分时操作:提高 CPU 的利用率。
- 故障处理:及时响应和处理系统故障。
2. Arduino Mega 2560 中断引脚
- 外部中断引脚:Arduino Mega 2560 支持 6 个外部中断引脚,分别是 2(中断 0)、3(中断 1)、18(中断 5)、19(中断 4)、20(中断 3)、21(中断 2)。
- 中断编号:每个中断引脚对应一个中断编号,用于在程序中配置和触发中断。
3. 中断模式
- LOW:低电平触发。
- CHANGE:电平变化触发(从低电平到高电平或从高电平到低电平)。
- RISING:上升沿触发(从低电平到高电平)。
- FALLING:下降沿触发(从高电平到低电平)。
4. 中断服务程序(ISR)
- ISR 的定义:ISR 是中断发生时执行的特定代码段,用于处理中断事件。
- ISR 的编写要求:
- ISR 必须没有参数和返回值。
- ISR 应尽可能简短,避免使用延时函数(如
delay()
)。 - ISR 中可以使用全局变量来传递数据。
5. 中断配置函数
attachInterrupt()
函数:用于配置中断引脚和中断模式。- 语法:
attachInterrupt(interrupt, ISR, mode)
- 参数说明:
interrupt
:中断编号。ISR
:中断服务程序名。mode
:中断触发模式。
- 语法:
detachInterrupt()
函数:用于关闭中断。- 语法:
detachInterrupt(interrupt)
- 参数说明:
interrupt
:中断编号。
- 语法:
6. 定时中断
- 定时中断的概念:利用单片机内部的定时器产生的中断,称为定时中断。
- 定时中断库:Arduino 没有直接的定时中断设置,需要使用第三方库,如
FlexiTimer2
或MsTimer2
。 - 定时中断的配置:
- 设置定时中断周期。
- 使能或禁止定时中断。
7. Wokwi 平台中断系统仿真
- 创建项目:在 Wokwi 平台上选择 Arduino Mega 2560 型号,创建新的项目。
- 编写代码:使用
attachInterrupt()
函数配置中断引脚和中断模式,编写 ISR。 - 仿真运行:观察中断事件触发时,ISR 的执行情况。
- 调试工具:使用串口监视器查看中断触发时的调试信息。
8. 实例项目
- 项目一:外部中断控制 LED 闪烁
- 使用外部中断引脚和按钮,实现按下按钮时 LED 闪烁的功能。
- 项目二:定时中断控制 LED 亮度调节
- 使用定时中断库,实现 LED 亮度随时间逐渐变化的功能。
三、课程总结
- 回顾知识点:总结中断系统的基本概念、中断引脚、中断模式、ISR 的编写要求等。
- 强调实践:鼓励学员在 Wokwi 平台上进行中断系统的仿真和调试,通过实例项目加深对中断系统的理解。
- 展望未来:介绍中断系统在更复杂项目中的应用前景,如智能家居、环境监测、机器人控制等。
四、学习资源
- 官方文档:Arduino 官方网站的中断系统相关文档。
- 在线教程:Wokwi 平台的教程和 Arduino 中文社区的教程。
- 书籍推荐:《Arduino 编程从入门到实践》、《Arduino 高级编程》等。