0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何利用计时器中断来保持一切正常运转

454398 来源:网络整理 作者:网络整理 2019-11-27 16:45 次阅读

设置

对于本指南中的所有示例,将使用以下接线:

如何利用计时器中断来保持一切正常运转

什么是中断?

中断是一个信号,告诉处理器立即停止其正在执行的操作并处理一些高优先级的处理。这种高优先级处理称为中断处理程序。

中断处理程序与任何其他void函数一样。如果编写一个并将其附加到中断,则在触发该中断信号时将调用该中断。当您从中断处理程序返回时,处理器将返回以继续之前的操作。

它们来自何处?

可以生成中断

来自一个Arduino定时器的定时器中断。

外部中断由于外部中断引脚之一的状态改变而引起的外部中断。

Pin-change中断是由于一组引脚中任何一个引脚的状态改变。

它们有什么用?

使用中断,您无需编写循环代码即可连续检查高优先级中断条件。您不必担心由于长时间运行的子例程而反应迟钝或错过了按键操作。

当中断发生时,处理器将自动停止正在执行的操作并调用中断处理程序。您只需编写代码以响应中断。

定时器中断

请勿致电给我们,我们会打电话给您

在本系列的第1部分中,我们学习了如何使用millis()进行计时。但是为了进行这项工作,我们每次都要在循环中调用millis()来查看是否该做某事了。一毫秒多次调用millis()只是发现时间没有改变,这是一种浪费。如果只需要每毫秒检查一次,那会不会很好?

计时器和计时器中断让我们可以做到这一点。我们可以设置一个计时器来每毫秒中断一次。计时器实际上会打电话给我们,让我们知道现在该检查时钟了!

Arduino计时器

Arduino Uno有3个计时器:Timer0,Timer1和Timer2。已经将Timer0设置为生成毫秒中断,以更新millis()报告的毫秒计数器。既然这就是我们要寻找的东西,我们也将得到Timer0来为我们生成一个中断!

频率和计数

定时器是简单的计数器,它们以从16MHz系统时钟。您可以配置时钟分频器以更改频率和各种不同的计数模式。您还可以将它们配置为在计时器达到特定计数时生成中断。

Timer0是8位,从0到255计数,并在溢出时生成中断。默认情况下,它使用64的时钟分频比为我们提供976.5625 Hz的中断率(就我们的目的而言,足够接近1KHz)。我们不会弄乱Timer0的频率,因为那样会破坏breakmillis()!

比较寄存器

Arduino定时器具有许多配置寄存器。可以使用Arduino IDE中定义的特殊符号来读取或写入这些符号。 有关所有这些寄存器及其功能的详细说明,请参见下面的“ 进一步阅读”中的链接。

我们将建立一个《计时器0的strong》比较寄存器(该寄存器称为OCR0A),在该计数中间的某个位置产生另一个中断。在每次滴答时,计时器计数器都会与比较寄存器进行比较,并且当它们相等时,将产生一个中断。

只要计数器值超过0xAF,下面的代码就会产生一个“ TIMER0_COMPA”中断。

下载:文件

复制代码

// Timer0 is already used for millis() - we‘ll just interrupt somewhere

// in the middle and call the “Compare A” function below

OCR0A = 0xAF;

TIMSK0 |= _BV(OCIE0A); // Timer0 is already used for millis() - we’ll just interrupt somewhere

// in the middle and call the “Compare A” function below

OCR0A = 0xAF;

TIMSK0 |= _BV(OCIE0A);

然后,我们将为定时器中断向量(称为“ TIMER0_COMPA_vect”)定义一个中断处理程序。在此中断处理程序中,我们将完成循环中所有的工作。

下载:文件

复制代码

// Interrupt is called once a millisecond,

SIGNAL(TIMER0_COMPA_vect)

{

unsigned long currentMillis = millis();

sweeper1.Update(currentMillis);

//if(digitalRead(2) == HIGH)

{

sweeper2.Update(currentMillis);

led1.Update(currentMillis);

}

led2.Update(currentMillis);

led3.Update(currentMillis);

} // Interrupt is called once a millisecond,

SIGNAL(TIMER0_COMPA_vect)

{

unsigned long currentMillis = millis();

sweeper1.Update(currentMillis);

//if(digitalRead(2) == HIGH)

{

sweeper2.Update(currentMillis);

led1.Update(currentMillis);

}

led2.Update(currentMillis);

led3.Update(currentMillis);

}

这给我们留下了一个完全空的循环。

下载:文件

复制代码

void loop()

{

} void loop()

{

}

您现在可以在循环中做任何您想做的事情。您甚至可以decade废并使用delay()!闪光灯和扫地机将不在乎。无论如何,它们仍然会每毫秒被调用一次!

进一步阅读:

这只是计时器可以执行的简单示例。有关不同类型的计时器及其配置方式的更多详细信息,请查看“库和链接”页面。

源代码:

以下是整个代码,包括闪光灯和扫地机:

下载:文件

复制代码

#include

class Flasher

{

// Class Member Variables

// These are initialized at startup

int ledPin; // the number of the LED pin

long OnTime; // milliseconds of on-time

long OffTime; // milliseconds of off-time

// These maintain the current state

int ledState; // ledState used to set the LED

unsigned long previousMillis; // will store last time LED was updated

// Constructor - creates a Flasher

// and initializes the member variables and state

public

Flasher(int pin, long on, long off)

{

ledPin = pin;

pinMode(ledPin, OUTPUT);

OnTime = on;

OffTime = off;

ledState = LOW;

previousMillis = 0;

}

void Update(unsigned long currentMillis)

{

if((ledState == HIGH) && (currentMillis - previousMillis 》= OnTime))

{

ledState = LOW; // Turn it off

previousMillis = currentMillis; // Remember the time

digitalWrite(ledPin, ledState); // Update the actual LED

}

else if ((ledState == LOW) && (currentMillis - previousMillis 》= OffTime))

{

ledState = HIGH; // turn it on

previousMillis = currentMillis; // Remember the time

digitalWrite(ledPin, ledState); // Update the actual LED

}

}

};

class Sweeper

{

Servo servo; // the servo

int pos; // current servo position

int increment; // increment to move for each interval

int updateInterval; // interval between updates

unsigned long lastUpdate; // last update of position

public:

Sweeper(int interval)

{

updateInterval = interval;

increment = 1;

}

void Attach(int pin)

{

servo.attach(pin);

}

void Detach()

{

servo.detach();

}

void Update(unsigned long currentMillis)

{

if((currentMillis - lastUpdate) 》 updateInterval) // time to update

{

lastUpdate = millis();

pos += increment;

servo.write(pos);

if ((pos 》= 180) || (pos 《= 0)) // end of sweep

{

// reverse direction

increment = -increment;

}

}

}

};

Flasher led1(11, 123, 400);

Flasher led2(12, 350, 350);

Flasher led3(13, 200, 222);

Sweeper sweeper1(25);

Sweeper sweeper2(35);

void setup()

{

sweeper1.Attach(9);

sweeper2.Attach(10);

// Timer0 is already used for millis() - we‘ll just interrupt somewhere

// in the middle and call the “Compare A” function below

OCR0A = 0xAF;

TIMSK0 |= _BV(OCIE0A);

}

// Interrupt is called once a millisecond, to update the LEDs

// Sweeper2 s not updated if the button on digital 2 is pressed.

SIGNAL(TIMER0_COMPA_vect)

{

unsigned long currentMillis = millis();

sweeper1.Update(currentMillis);

if(digitalRead(2) == HIGH)

{

sweeper2.Update(currentMillis);

led1.Update(currentMillis);

}

led2.Update(currentMillis);

led3.Update(currentMillis);

}

void loop()

{

} #include

class Flasher

{

// Class Member Variables

// These are initialized at startup

int ledPin; // the number of the LED pin

long OnTime; // milliseconds of on-time

long OffTime; // milliseconds of off-time

// These maintain the current state

int ledState; // ledState used to set the LED

unsigned long previousMillis; // will store last time LED was updated

// Constructor - creates a Flasher

// and initializes the member variables and state

public:

Flasher(int pin, long on, long off)

{

ledPin = pin;

pinMode(ledPin, OUTPUT);

OnTime = on;

OffTime = off;

ledState = LOW;

previousMillis = 0;

}

void Update(unsigned long currentMillis)

{

if((ledState == HIGH) && (currentMillis - previousMillis 》= OnTime))

{

ledState = LOW; // Turn it off

previousMillis = currentMillis; // Remember the time

digitalWrite(ledPin, ledState); // Update the actual LED

}

else if ((ledState == LOW) && (currentMillis - previousMillis 》= OffTime))

{

ledState = HIGH; // turn it on

previousMillis = currentMillis; // Remember the time

digitalWrite(ledPin, ledState); // Update the actual LED

}

}

};

class Sweeper

{

Servo servo; // the servo

int pos; // current servo position

int increment; // increment to move for each interval

int updateInterval; // interval between updates

unsigned long lastUpdate; // last update of position

public:

Sweeper(int interval)

{

updateInterval = interval;

increment = 1;

}

void Attach(int pin)

{

servo.attach(pin);

}

void Detach()

{

servo.detach();

}

void Update(unsigned long currentMillis)

{

if((currentMillis - lastUpdate) 》 updateInterval) // time to update

{

lastUpdate = millis();

pos += increment;

servo.write(pos);

if ((pos 》= 180) || (pos 《= 0)) // end of sweep

{

// reverse direction

increment = -increment;

}

}

}

};

Flasher led1(11, 123, 400);

Flasher led2(12, 350, 350);

Flasher led3(13, 200, 222);

Sweeper sweeper1(25);

Sweeper sweeper2(35);

void setup()

{

sweeper1.Attach(9);

sweeper2.Attach(10);

// Timer0 is already used for millis() - we’ll just interrupt somewhere

// in the middle and call the “Compare A” function below

OCR0A = 0xAF;

TIMSK0 |= _BV(OCIE0A);

}

// Interrupt is called once a millisecond, to update the LEDs

// Sweeper2 s not updated if the button on digital 2 is pressed.

SIGNAL(TIMER0_COMPA_vect)

{

unsigned long currentMillis = millis();

sweeper1.Update(currentMillis);

if(digitalRead(2) == HIGH)

{

sweeper2.Update(currentMillis);

led1.Update(currentMillis);

}

led2.Update(currentMillis);

led3.Update(currentMillis);

}

void loop()

{

}

外部中断

最好是退出循环

与定时器中断不同的是,外部事件会触发外部中断。例如,当按下按钮或从旋转编码器接收到脉冲时。但是,就像计时器中断一样,您不需要继续轮询GPIO引脚以进行更改。

Arduino UNO有2个外部中断引脚。在此示例中,我们将按钮附加到其中一个按钮,并使用它来重置我们的清扫器。首先,在我们的清除程序类中添加一个“ reset()”函数。 reset()函数将位置设置为0,并立即将伺服器放置在此处:

下载:文件

复制代码

void reset()

{

pos = 0;

servo.write(pos);

increment = abs(increment);

} void reset()

{

pos = 0;

servo.write(pos);

increment = abs(increment);

}

接下来,我们将添加对AttachInterrupt()的调用以连接外部中断

在UNO上,中断0与数字引脚2相关联。我们告诉它在该引脚上寻找信号的“ FALLING”沿。当按下按钮时,信号从HIGH降到LOW,并调用“重置”中断处理程序。

下载:文件

复制代码

pinMode(2, INPUT_PULLUP);

attachInterrupt(0, Reset, FALLING); pinMode(2, INPUT_PULLUP);

attachInterrupt(0, Reset, FALLING);

这是“重置”中断处理程序。它仅调用清除程序重置功能:

下载:文件

复制代码

void Reset()

{

sweeper1.reset();

sweeper2.reset();

} void Reset()

{

sweeper1.reset();

sweeper2.reset();

}

现在,每当您按下按钮时,伺服器就会停止其正在执行的操作,并立即寻找到零位置。

源代码:

这是带有计时器和外部中断的完整草图:

下载:文件

复制代码

#include

class Flasher

{

// Class Member Variables

// These are initialized at startup

int ledPin; // the number of the LED pin

long OnTime; // milliseconds of on-time

long OffTime; // milliseconds of off-time

// These maintain the current state

volatile int ledState; // ledState used to set the LED

volatile unsigned long previousMillis; // will store last time LED was updated

// Constructor - creates a Flasher

// and initializes the member variables and state

public:

Flasher(int pin, long on, long off)

{

ledPin = pin;

pinMode(ledPin, OUTPUT);

OnTime = on;

OffTime = off;

ledState = LOW;

previousMillis = 0;

}

void Update(unsigned long currentMillis)

{

if((ledState == HIGH) && (currentMillis - previousMillis 》= OnTime))

{

ledState = LOW; // Turn it off

previousMillis = currentMillis; // Remember the time

digitalWrite(ledPin, ledState); // Update the actual LED

}

else if ((ledState == LOW) && (currentMillis - previousMillis 》= OffTime))

{

ledState = HIGH; // turn it on

previousMillis = currentMillis; // Remember the time

digitalWrite(ledPin, ledState); // Update the actual LED

}

}

};

class Sweeper

{

Servo servo; // the servo

int updateInterval; // interval between updates

volatile int pos; // current servo position

volatile unsigned long lastUpdate; // last update of position

volatile int increment; // increment to move for each interval

public:

Sweeper(int interval)

{

updateInterval = interval;

increment = 1;

}

void Attach(int pin)

{

servo.attach(pin);

}

void Detach()

{

servo.detach();

}

void reset()

{

pos = 0;

servo.write(pos);

increment = abs(increment);

}

void Update(unsigned long currentMillis)

{

if((currentMillis - lastUpdate) 》 updateInterval) // time to update

{

lastUpdate = currentMillis;

pos += increment;

servo.write(pos);

if ((pos 》= 180) || (pos 《= 0)) // end of sweep

{

// reverse direction

increment = -increment;

}

}

}

};

Flasher led1(11, 123, 400);

Flasher led2(12, 350, 350);

Flasher led3(13, 200, 222);

Sweeper sweeper1(25);

Sweeper sweeper2(35);

void setup()

{

sweeper1.Attach(9);

sweeper2.Attach(10);

// Timer0 is already used for millis() - we‘ll just interrupt somewhere

// in the middle and call the “Compare A” function below

OCR0A = 0xAF;

TIMSK0 |= _BV(OCIE0A);

pinMode(2, INPUT_PULLUP);

attachInterrupt(0, Reset, FALLING);

}

void Reset()

{

sweeper1.reset();

sweeper2.reset();

}

// Interrupt is called once a millisecond,

SIGNAL(TIMER0_COMPA_vect)

{

unsigned long currentMillis = millis();

sweeper1.Update(currentMillis);

//if(digitalRead(2) == HIGH)

{

sweeper2.Update(currentMillis);

led1.Update(currentMillis);

}

led2.Update(currentMillis);

led3.Update(currentMillis);

}

void loop()

{

} #include

class Flasher

{

// Class Member Variables

// These are initialized at startup

int ledPin; // the number of the LED pin

long OnTime; // milliseconds of on-time

long OffTime; // milliseconds of off-time

// These maintain the current state

volatile int ledState; // ledState used to set the LED

volatile unsigned long previousMillis; // will store last time LED was updated

// Constructor - creates a Flasher

// and initializes the member variables and state

public:

Flasher(int pin, long on, long off)

{

ledPin = pin;

pinMode(ledPin, OUTPUT);

OnTime = on;

OffTime = off;

ledState = LOW;

previousMillis = 0;

}

void Update(unsigned long currentMillis)

{

if((ledState == HIGH) && (currentMillis - previousMillis 》= OnTime))

{

ledState = LOW; // Turn it off

previousMillis = currentMillis; // Remember the time

digitalWrite(ledPin, ledState); // Update the actual LED

}

else if ((ledState == LOW) && (currentMillis - previousMillis 》= OffTime))

{

ledState = HIGH; // turn it on

previousMillis = currentMillis; // Remember the time

digitalWrite(ledPin, ledState); // Update the actual LED

}

}

};

class Sweeper

{

Servo servo; // the servo

int updateInterval; // interval between updates

volatile int pos; // current servo position

volatile unsigned long lastUpdate; // last update of position

volatile int increment; // increment to move for each interval

public:

Sweeper(int interval)

{

updateInterval = interval;

increment = 1;

}

void Attach(int pin)

{

servo.attach(pin);

}

void Detach()

{

servo.detach();

}

void reset()

{

pos = 0;

servo.write(pos);

increment = abs(increment);

}

void Update(unsigned long currentMillis)

{

if((currentMillis - lastUpdate) 》 updateInterval) // time to update

{

lastUpdate = currentMillis;

pos += increment;

servo.write(pos);

if ((pos 》= 180) || (pos 《= 0)) // end of sweep

{

// reverse direction

increment = -increment;

}

}

}

};

Flasher led1(11, 123, 400);

Flasher led2(12, 350, 350);

Flasher led3(13, 200, 222);

Sweeper sweeper1(25);

Sweeper sweeper2(35);

void setup()

{

sweeper1.Attach(9);

sweeper2.Attach(10);

// Timer0 is already used for millis() - we’ll just interrupt somewhere

// in the middle and call the “Compare A” function below

OCR0A = 0xAF;

TIMSK0 |= _BV(OCIE0A);

pinMode(2, INPUT_PULLUP);

attachInterrupt(0, Reset, FALLING);

}

void Reset()

{

sweeper1.reset();

sweeper2.reset();

}

// Interrupt is called once a millisecond,

SIGNAL(TIMER0_COMPA_vect)

{

unsigned long currentMillis = millis();

sweeper1.Update(currentMillis);

//if(digitalRead(2) == HIGH)

{

sweeper2.Update(currentMillis);

led1.Update(currentMillis);

}

led2.Update(currentMillis);

led3.Update(currentMillis);

}

void loop()

{

}

库和链接

有关计时器的更多信息

可以将计时器配置为以各种频率运行并以不同的模式运行。除了产生中断,它们还用于控制PWM引脚。以下链接是了解如何配置和使用计时器的出色资源:

Arduino PWM的机密

计时器/PWM速查表

计时器库

网上有许多Arduino``计时器‘’库可用与本系列第1部分中所做的一样,许多人仅监视millis()并要求进行持续轮询。但是实际上有一些配置可以让您配置定时器以生成中断。

Paul Stoffregan出色的TimerOne和TimerThree库处理了许多定时器中断配置的低级细节。 (请注意,TimerThree不适用于UNO。它可以与Leonardo,Mega和某些Teensy板一起使用)

TimerOne和Timer 3库

引脚更改中断

对于2个不足的情况

Arduino UNO只有2个外部中断引脚。但是,如果您需要两个以上的中断,该怎么办?幸运的是,Arduino UNO在所有引脚上都支持“引脚更改”中断。

引脚更改中断类似于外部中断。区别在于,在8个相关引脚中的任何一个引脚上都会因状态变化而产生一个中断。这些操作要稍微复杂一点,因为您必须跟踪所有8个引脚的最后一个已知状态,以找出8个引脚中的哪个导致了中断。

Arduino Playground的PinChangeInt库实现了一个方便的引脚更改中断接口:http://playground.arduino.cc/Main/PinChangeInt

PinChangeInt库

计时器和中断礼仪

中断就像超市的快速通道。考虑周全,将其保持在10件以下,一切都会顺利进行。

如果一切都是高水平的,那么没有什么是高度优先的。

中断处理程序应仅用于处理高优先级,对时间敏感的事件。请记住,在中断处理程序中时,禁用了中断。如果您尝试在中断级别执行过多操作,则会降低对其他中断的响应。

一次仅一个中断。

ISR,中断被禁用。这有两个非常重要的含义:

在ISR中完成的工作应保持简短,以免丢失任何中断。

在ISR中的代码不应调用任何需要激活中断(例如delay()或使用i2c总线的任何中断)。这将导致程序挂起。

将冗长的处理推迟到循环中。

如果您需要进行大量处理以响应中断,请使用中断处理程序仅执行必要的操作,然后设置易失性状态变量(参见下文)以指示需要进一步处理。当您从循环中调用更新功能时,请检查状态变量以查看是否需要任何后续处理。

重新配置计时器之前需要检查 《计时器是一种有限的资源。 UNO上只有3个,它们用于许多用途。如果您弄乱了计时器配置,则其他某些功能可能不再起作用。例如,在Arduino UNO上:

Timer0 -用于引脚5和6上的millis(),micros(),delay()和PWM

Timer1 -用于Servos,WaveHC库和引脚9和10上的PWM

Timer2 -由Tone和PWM引脚上使用11&13

安全共享数据

因为中断将暂停,无论处理器正在处理该中断如何,我们必须小心在中断处理程序和循环中的代码之间共享数据。

易失性变量

有时,编译器会尝试优化代码以提高速度。有时,这些优化会将常用变量的副本保留在寄存器中以便快速访问。问题是,如果这些变量之一在中断处理程序和循环代码之间共享,则其中一个变量最终可能会查看陈旧的副本而不是真实的副本。将变量标记为易失性会告诉编译器不要对优化进行潜在的危险操作。

保护较大的变量

Evan标记变量 volatile 是不够的如果它的变量大于整数(例如字符串,数组,结构等)。较大的变量需要几个指令周期来更新,并且如果在更新的中间发生中断,则数据可能会被破坏。如果您具有与中断处理程序共享的较大变量或结构,则在从循环中更新中断时应禁用中断。 (默认情况下,已在中断处理程序中禁用了中断。)
责任编辑:wv

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 中断
    +关注

    关注

    5

    文章

    898

    浏览量

    41463
  • 计时器
    +关注

    关注

    1

    文章

    420

    浏览量

    32686
  • Arduino
    +关注

    关注

    188

    文章

    6468

    浏览量

    186913
收藏 人收藏

    评论

    相关推荐

    单个 MSP430™ 计时器模块的多时基应用说明

    电子发烧友网站提供《单个 MSP430™ 计时器模块的多时基应用说明.pdf》资料免费下载
    发表于 09-13 11:09 0次下载
    单个 MSP430™ <b class='flag-5'>计时器</b>模块的多时基应用说明

    TLC555 LinCMOS™技术计时器数据表

    电子发烧友网站提供《TLC555 LinCMOS™技术计时器数据表.pdf》资料免费下载
    发表于 08-20 11:15 0次下载
    TLC555 LinCMOS™技术<b class='flag-5'>计时器</b>数据表

    LMC555 CMOS计时器数据表

    电子发烧友网站提供《LMC555 CMOS计时器数据表.pdf》资料免费下载
    发表于 08-20 09:16 0次下载
    LMC555 CMOS<b class='flag-5'>计时器</b>数据表

    CW32L083 IAP跳转后中断无响应是怎么回事?

    最近做个项目,需要IAP。按照官方的教程一切顺利,软件APP跳转一切正常,但是跳转后中断没有响应。搜索了堆资料,APP在mian中找开了
    发表于 07-26 07:17

    ESP8266EX连接到WIFI AP时,是否需要执行些特殊程序?

    ESP8266EX处于 STATION 模式。我正在使用 0.9.2 SDK 和 lubuntu 构建。 1.当模块上电后首次连接到WIFI AP时,一切正常。 2. 当我关闭我的 WIFI
    发表于 07-15 07:57

    为什么ESP8266EX再次从WIFI AP获取IP时,它会在几秒钟后断开TCP客户端连接?

    我制作了个自定义固件连接到 TCP 套接字服务一切正常,直到 WIFI 失去连接并再次重新连接。我将尝试解释: 1. ESP8266EX启动,当它连接到我的 AP 时(我在
    发表于 07-15 06:17

    spi_flash期间的计时器中断导致崩溃怎么解决?

    解决。但是,如果我已经在 user_init() 中启动定时中断,我会遇到类似的问题:如果我这样做,esp 将重新启动。只有当我在 ESP 连接到 wifi 网络后启用计时器中断时,
    发表于 07-12 11:54

    双路精密计时器选购指南:准确选择,高效工作

    在快节奏的现代生活中,准确的时间管理对于个人和团队的成功至关重要。双路精密计时器作为种高效的计时工具,受到了越来越多人的青睐。那么,如何选购款适合自己的双路精密
    的头像 发表于 06-26 16:06 356次阅读

    求助,关于PSoC 6上的ADC中断问题求解

    ,除 adc 外一切正常。 问题: 我把问题缩小到应用程序 cm4 侧的 cyhal_adc_read() 函数上。 Adc init 正常,但程序在执行该功能时停止。 中断没有启动,但我不确定
    发表于 05-29 07:37

    tle9879中断异常的原因?

    在24us的时候一切正常,29us的时候出现了异常,如图片所示。one-match中断跟period中断的时序好像不对了。
    发表于 05-28 07:43

    计时器触发的中断中使用了HAL_I2C_Mem_Read函数(I2C数据读取)导致代码卡死怎么解决?

    计时器触发的中断中使用了HAL_I2C_Mem_Read函数(I2C数据读取)导致代码卡死,这有什么解决办法吗?十分感谢,个人猜测是中断优先级问题,但是不知如何设置 以下是计时器相关
    发表于 05-20 07:34

    STM32F407VET6 TIM1定时中断,低频中断正常,高频中断异常时间不对是哪里的问题?

    。设置PWM频率12.5Mhz时,仿真查看cnt,有参数显示,但while(1)内容未执行。调整为100KZ时,一切正常
    发表于 03-27 06:16

    利用systick计时器对LED等延时的时候,for循环中的ms和systick–&gt;LOAD的值为什么不是同个?

    我们在利用systick计时器对LED等延时的时候,这里的for循环中的ms和我们的systick–>LOAD的值不是同个,那当for循环结束以后,为啥我的systick–&
    发表于 03-25 07:57

    使用ST-link V2的过程中电脑插入读卡设备后无法正常识别ST-link V2的原因?

    配合cubeIDE使用一切正常,电脑插入读卡设备后无法正常识别ST-link V2,但在电脑的设备管理中还是可以找到ST-link,同时升级ST-link还可以
    发表于 03-11 06:30

    ModusToolbox™生成时如何调用systick计时器ISR?

    我无法理解当项目由 ModusToolbox™生成时如何调用 systick 计时器 ISR。 通常,当您设置系统计时器并启用其中断时,系统会直接从中断向量调用 Systick_Han
    发表于 01-18 09:16