我需要创建一个中断系统,该系统每隔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);
}
}
答案 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;
}