Arduino CTC 定时器中断快 2 倍
Arduino CTC timer interrupt ~2x fast
下午大家
我正在寻找一些帮助,请解决我在尝试学习定时器中断时一直感到困惑的事情
你最好把我当成新手。我在这里没有特定的目标,除了学习一些我认为有用的东西来增加我的能力!
我写了下面的草图作为对以不同速率执行不同 fcns 的严格框架的尝试。我已经使用 millis() 做了类似的事情,虽然它起作用了,但我发现 a) 没有明显的方法来检查任务超限和备份执行率,以及 b) 处理器通过检查 millis( ) 每个程序周期。*
基本上我认为应该是 Timer2 上的 1ms 定时器中断(16MHz/64 预分频器/250 比较寄存器 =1000hz)在 0.5ms 左右出现。我已经为此困惑了几个小时,但我准备接受它可能是某种东西 fundamental/basic!
还有一个问题是,使用串行通信尝试调试更快的任务速率似乎会大大降低速度,所以我通过计算 1 毫秒的任务来调用 10,100 和 1000 毫秒来推断问题较慢级别的任务和调试。我想以 9600 波特的速度咀嚼几个字符可能很慢。**
我粘贴了下面的代码。任何指针高度赞赏。随心所欲地苛刻:)
干杯
铝
*虽然不是我感到困惑的地方 - 也欢迎对我的逻辑发表任何评论
** 虽然我不明白 Serial.println 是如何设法减慢程序速度的。它是由中断驱动的,因此它肯定应该只丢弃通信并执行下一个 ISR——实际上是任务超限。也欢迎在这里发表评论
//NOTES
//https://www.robotshop.com/letsmakerobots/arduino-101-timers-and-interrupts
//https://sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-atmega328
//http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf
//
//INITIALISE EVERYTHING
const int ledPin = 13;
volatile int nStepTask1ms = 0; // init 0 - to be used for counting number of 1ms tasks run and hence calling 10ms task
volatile int nStepTask10ms = 0;
volatile int nStepTask100ms = 0;
volatile int nStepTask1000ms = 0;
volatile int LEDFlashState = 0; // init 0 - variable to flip when LED on
volatile int millisNew = 0; // to store up to date time
volatile int millisOld = 0; // to store prev time
volatile int millisDelta = 0; // to store deltas
//
void setup()
{
Serial.begin(9600); //set up serial comms back to PC
pinMode(ledPin,OUTPUT); //to flash the embedded LED
noInterrupts(); //turn off interrupts while we set the registers
//set up TIMER first
TCCR2A = 0; //sets TCCR1A byte to zero, bits to be later individually mod'd
TCCR2B = 0; //sets TCCR1B byte to zero, bits to be later individually mod'd
TCNT2 = 0; //ensures counter value starting from zero
Serial.println("Timer1 vars reset");
TCCR2B |= (1<<WGM12); // bitwise or between itself and WGM12. TCCR2B = TCCR2B | 00001000. Sets WGM12 high. (CTC mode so WGM12=1, WGM 13,11,10 all 0)
Serial.println("Mode 4 CTC set");
Serial.println("TCCR2B=");
Serial.println(TCCR2B,BIN);
TCCR2B |= (1<<CS11); // sets CS11 high
TCCR2B |= (1<<CS10); // sets CS10 high (i.e. this and above give /64 prescaler)
Serial.println("Prescaler set to 64");
OCR2A = 250; //compare match register for timer2
Serial.println("Compare Register set");
Serial.println("OCR2A=");
Serial.println(OCR2A);
TIMSK2 |= (1 << OCIE2A); //enables interrupts - https://playground2014.wordpress.com/arduino/basics-timer-interrupts/
Serial.println("Interrupt Mask Register Set");
Serial.println("TIMSK2=");
Serial.println(TIMSK2);
interrupts(); //enable interrupts again - not sure if this is required given OCIE1A being set above?
}
//set up ISR for Timer2 - timer structure called every interrump (1ms) that subsequently calls 1,10,100 and 1000msec task fcns
ISR(TIMER2_COMPA_vect)
{
TASK_1ms();
if (nStepTask1ms>9)
{
TASK_10ms();
if (nStepTask10ms>9)
{
TASK_100ms();
if (nStepTask100ms>9)
{
TASK_1000ms();
}
}
}
}
void TASK_1ms()
{
// 1ms tasks here
nStepTask1ms++;
}
void TASK_10ms()
{
//10ms tasks here
nStepTask1ms=0;
nStepTask10ms++;
}
void TASK_100ms()
{
//100ms tasks here
nStepTask10ms=0;
nStepTask100ms++;
//Serial.println(nStepTask100ms);
}
void TASK_1000ms()
{
//1000ms tasks here
nStepTask100ms=0;
//do something
changeLEDFlashState();
//check timing tick of this task
millisNew=millis();
millisDelta=millisNew-millisOld;
Serial.println(millisDelta);
millisOld=millisNew;
nStepTask1000ms++;
}
void changeLEDFlashState()
{
if(LEDFlashState==0)
{
digitalWrite(ledPin,HIGH);
LEDFlashState=1;
//Serial.println("LED Turned On");
}
else
{
digitalWrite(ledPin,LOW);
LEDFlashState=0;
//Serial.println("LED Turned Off");
}
}
void loop()
{
// empty
}
这里有两行:
TCCR2B |= (1<<CS11); // sets CS11 high
TCCR2B |= (1<<CS10); // sets CS10 high (i.e. this and above give /64 prescaler)
这两行设置TCCR2B的低三位为011,即/32预分频器。
请注意,对于 Timer1 和 Timer2,预分频器设置与 Timer0 不同。
对于 Timer0,上面的设置将为您提供一个 /64 预分频器。
下午大家
我正在寻找一些帮助,请解决我在尝试学习定时器中断时一直感到困惑的事情
你最好把我当成新手。我在这里没有特定的目标,除了学习一些我认为有用的东西来增加我的能力!
我写了下面的草图作为对以不同速率执行不同 fcns 的严格框架的尝试。我已经使用 millis() 做了类似的事情,虽然它起作用了,但我发现 a) 没有明显的方法来检查任务超限和备份执行率,以及 b) 处理器通过检查 millis( ) 每个程序周期。*
基本上我认为应该是 Timer2 上的 1ms 定时器中断(16MHz/64 预分频器/250 比较寄存器 =1000hz)在 0.5ms 左右出现。我已经为此困惑了几个小时,但我准备接受它可能是某种东西 fundamental/basic!
还有一个问题是,使用串行通信尝试调试更快的任务速率似乎会大大降低速度,所以我通过计算 1 毫秒的任务来调用 10,100 和 1000 毫秒来推断问题较慢级别的任务和调试。我想以 9600 波特的速度咀嚼几个字符可能很慢。**
我粘贴了下面的代码。任何指针高度赞赏。随心所欲地苛刻:)
干杯
铝
*虽然不是我感到困惑的地方 - 也欢迎对我的逻辑发表任何评论 ** 虽然我不明白 Serial.println 是如何设法减慢程序速度的。它是由中断驱动的,因此它肯定应该只丢弃通信并执行下一个 ISR——实际上是任务超限。也欢迎在这里发表评论
//NOTES
//https://www.robotshop.com/letsmakerobots/arduino-101-timers-and-interrupts
//https://sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-atmega328
//http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf
//
//INITIALISE EVERYTHING
const int ledPin = 13;
volatile int nStepTask1ms = 0; // init 0 - to be used for counting number of 1ms tasks run and hence calling 10ms task
volatile int nStepTask10ms = 0;
volatile int nStepTask100ms = 0;
volatile int nStepTask1000ms = 0;
volatile int LEDFlashState = 0; // init 0 - variable to flip when LED on
volatile int millisNew = 0; // to store up to date time
volatile int millisOld = 0; // to store prev time
volatile int millisDelta = 0; // to store deltas
//
void setup()
{
Serial.begin(9600); //set up serial comms back to PC
pinMode(ledPin,OUTPUT); //to flash the embedded LED
noInterrupts(); //turn off interrupts while we set the registers
//set up TIMER first
TCCR2A = 0; //sets TCCR1A byte to zero, bits to be later individually mod'd
TCCR2B = 0; //sets TCCR1B byte to zero, bits to be later individually mod'd
TCNT2 = 0; //ensures counter value starting from zero
Serial.println("Timer1 vars reset");
TCCR2B |= (1<<WGM12); // bitwise or between itself and WGM12. TCCR2B = TCCR2B | 00001000. Sets WGM12 high. (CTC mode so WGM12=1, WGM 13,11,10 all 0)
Serial.println("Mode 4 CTC set");
Serial.println("TCCR2B=");
Serial.println(TCCR2B,BIN);
TCCR2B |= (1<<CS11); // sets CS11 high
TCCR2B |= (1<<CS10); // sets CS10 high (i.e. this and above give /64 prescaler)
Serial.println("Prescaler set to 64");
OCR2A = 250; //compare match register for timer2
Serial.println("Compare Register set");
Serial.println("OCR2A=");
Serial.println(OCR2A);
TIMSK2 |= (1 << OCIE2A); //enables interrupts - https://playground2014.wordpress.com/arduino/basics-timer-interrupts/
Serial.println("Interrupt Mask Register Set");
Serial.println("TIMSK2=");
Serial.println(TIMSK2);
interrupts(); //enable interrupts again - not sure if this is required given OCIE1A being set above?
}
//set up ISR for Timer2 - timer structure called every interrump (1ms) that subsequently calls 1,10,100 and 1000msec task fcns
ISR(TIMER2_COMPA_vect)
{
TASK_1ms();
if (nStepTask1ms>9)
{
TASK_10ms();
if (nStepTask10ms>9)
{
TASK_100ms();
if (nStepTask100ms>9)
{
TASK_1000ms();
}
}
}
}
void TASK_1ms()
{
// 1ms tasks here
nStepTask1ms++;
}
void TASK_10ms()
{
//10ms tasks here
nStepTask1ms=0;
nStepTask10ms++;
}
void TASK_100ms()
{
//100ms tasks here
nStepTask10ms=0;
nStepTask100ms++;
//Serial.println(nStepTask100ms);
}
void TASK_1000ms()
{
//1000ms tasks here
nStepTask100ms=0;
//do something
changeLEDFlashState();
//check timing tick of this task
millisNew=millis();
millisDelta=millisNew-millisOld;
Serial.println(millisDelta);
millisOld=millisNew;
nStepTask1000ms++;
}
void changeLEDFlashState()
{
if(LEDFlashState==0)
{
digitalWrite(ledPin,HIGH);
LEDFlashState=1;
//Serial.println("LED Turned On");
}
else
{
digitalWrite(ledPin,LOW);
LEDFlashState=0;
//Serial.println("LED Turned Off");
}
}
void loop()
{
// empty
}
这里有两行:
TCCR2B |= (1<<CS11); // sets CS11 high
TCCR2B |= (1<<CS10); // sets CS10 high (i.e. this and above give /64 prescaler)
这两行设置TCCR2B的低三位为011,即/32预分频器。
请注意,对于 Timer1 和 Timer2,预分频器设置与 Timer0 不同。 对于 Timer0,上面的设置将为您提供一个 /64 预分频器。