如何在Arduino代码中进行基于时间的内部中断?

时间:2018-06-29 16:16:34

标签: arduino ide

我需要创建一个中断系统,该系统每隔x间隔更新一次PWM寄存器。但是,从attachinterrupt()函数来看,似乎没有基于时间的选项,而是只有上升沿或下降沿检测输入。是否可以通过基于重复时间的启动来中断?

这是我的代码,我基本上需要将for循环和microdelay()替换为基于时间的中断:

int D4 = 6;

byte arr[] = {0x06, 0x0C, 0x12, 0x18, 0x1E, 0x2A, 0x30, 0x36, 0x3C, 0x40, 0x3C, 0x36, 0x30, 0x2A, 0x1E, 0x18, 0x12, 0x0C, 0x06};

void setup() {
  CLKPR = (1<<CLKPCE)|(0<<CLKPS3)|(1<<CLKPS2)|(1<<CLKPS1)|(1<<CLKPS0);
  DDRC = (1<<DDC7)|(1<<DDC6);
  TCCR4A = (0<<COM4A1)|(1<<COM4A0)|(1<<PWM4A);
  TCCR4B = (0<<DTPS41)|(0<<DTPS40)|(0<<CS43)|(0<<CS42)|(0<<CS41)|(1<<CS40); 
  TCCR4D = (0<<WGM41)|(0<<WGM40);
  pinMode(D4, OUTPUT);
}

void loop() {
  OCR4C = 0x40;
 for (int i = 0; i <= sizeof(arr) ; i++ ){

  OCR4A= arr[i];
  delayMicroseconds(100);
 }
}

2 个答案:

答案 0 :(得分:0)

我猜您很长一段时间以来一直在使用Atmel控制器,并且对Arduino来说还很陌生。

使用此处描述的计时器库。 https://playground.arduino.cc/Code/Timer1

或者您可以使用micros实现状态空间类型的程序。例子

long nextUpdateTime=micros();
loop(){
    if(nextUpdateTime<micros())
        return;
    nextUpdateTime=micros()+100; //Change 100 to what ever delay you want.
    // Write your required code here. This code will be called every 100 (Or whatever you set) us.
}

然后,您可以只使用analogWrite函数来生成您要生成的任何pwm。我不确定您要做什么,但是我相信了解该功能会有所帮助。链接在这里 https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/

我希望这会有所帮助。祝你有美好的一天。

答案 1 :(得分:0)

您可以使用计时器中断,该中断将以恒定的时间间隔中断整个程序,执行称为ISR(中断服务程序)的代码块,然后返回到程序其余部分停止的代码。延迟通常是不好的,因为它们会使处理器停止执行任何有用的操作。调整到适合您的处理器,我想它看起来像是arduino Mega,我添加的代码可能会起作用,但最初是为arduino Uno上的atmega 328设计的。检查数据表!

int D4 = 6,i = 0;

byte arr[] = {0x06, 0x0C, 0x12, 0x18, 0x1E, 0x2A, 0x30, 0x36, 0x3C, 0x40, 0x3C, 0x36, 0x30, 0x2A, 0x1E, 0x18, 0x12, 0x0C, 0x06};

void setup(){
    CLKPR = (1<<CLKPCE)|(0<<CLKPS3)|(1<<CLKPS2)|(1<<CLKPS1)|(1<<CLKPS0);
    DDRC = (1<<DDC7)|(1<<DDC6);
    TCCR4A = (0<<COM4A1)|(1<<COM4A0)|(1<<PWM4A);
    TCCR4B = (0<<DTPS41)|(0<<DTPS40)|(0<<CS43)|(0<<CS42)|(0<<CS41)|(1<<CS40); 
    TCCR4D = (0<<WGM41)|(0<<WGM40);
    pinMode(D4, OUTPUT);

    TCCR0A = (1<<WGM01); //setup timer 0 to clear its counter when it reaches the OCR0A
    TCCR0B = (1<<CS00)|(1<<CS01); //prescaler 1/64 to divide the 16 MHz clock by 64
    TIMSK0 = (1<<OCIE0A); //setup the timer to toggle the ISR flag A
    OCR0A = 25; //every 25 counts will represent 100 microseconds
}

ISR(TIMER0_COMPA_vect){ //This is the ISR routine itself, triggered by compare flag A of timer 0
  OCR4A = arr[i];
  ++i;
  if(i>sizeof(arr)) i = 0;
}

void loop(){
    OCR4C = 0x40;
}