gpt4 book ai didi

timer - Timer1 arduino使Serial不起作用

转载 作者:行者123 更新时间:2023-12-03 10:23:56 25 4
gpt4 key购买 nike

运行以下代码,当我在串行arduino中发送任何字符时,未打印回“ a”。我认为timer1代码有问题,但是应该可以正常工作,因为该代码是由我的C类老师给出的。

void setup() {

Serial.begin(115200);

//http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS
noInterrupts();
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for 1000000hz increments with 8 bits prescaler
OCR1A = 1;// = (16*10^6) / (1000000*8) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS11 bit for 8 prescaler. Each timer has a different bit code to each prescaler
TCCR1B |= (1 << CS11);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
interrupts();

}

void loop() {

if (Serial.available()) {

Serial.println("a");

}

}

最佳答案

设置TCCR1A和B的方式都是正确的。

参见660-pg ATmega328数据表pgs。如果您想从现在开始寻找底层的帮助,请在132〜135中获取更多帮助和信息。

但是,您有2个主要问题,1个次要问题和1个推荐。

这是两个完全破坏您的代码的主要问题:


由于启用了定时器比较匹配1A中断(“ TIMSK1 | =(1 << OCIE1A);”),因此,您还必须定义中断服务程序(ISR),该程序在发生时将被调用,否则您将运行时(但不是编译时)问题。也就是说,如果您没有为输出比较匹配A定义ISR,则一旦发生输出比较A中断,处理器就会陷入编译器为您创建的无限,空的虚拟ISR中,并且主循环不会继续进行(请参见下面的代码以证明这一点)。


将此添加到代码的底部:

ISR(TIMER1_COMPA_vect)
{
//insert your code here that you want to run every time the counter reaches OCR1A
}



进入ISR需要花费几微秒的时间,而走出ISR则需要花费几微秒的时间,再加上在ISR中运行代码所需的时间,您需要使用足够大的ICR值,即使ISR有时间执行,而不是被连续调用如此之快,以至于您永远不会退出ISR(这实际上会将您的代码锁定到无限循环中……在您的情况下也是如此)。
我建议您每隔10us拨打一次ISR的频率不高。由于您使用的是CTC模式(比较匹配时清除计时器),预分频器为8,因此我建议将OCR1A设置为不小于20左右。 OCR1A = 20将每10us调用一次ISR。 (预分频器为8意味着每个Timer1滴答花费0.5us,因此OCR1A = 20将每20 * 0.5 = 10us调用一次ISR)。


如果将OCR1A设置为20,并如上所述添加ISR代码,则代码将正常运行。

1个小问题:

在配置完其余计时器后,最好设置OCR1A,否则在某些情况下计时器可能无法开始计数(请参见此处的“ Thorsten's”注释: http://www.righto.com/2009/07/secrets-of-arduino-pwm.html

因此,将OCR1A = 20;至最后一条TCCR1B行之后和TIMSK1行之前。

1条建议:

摆脱“ noInterrupts”和“ interrupts”。这里不需要它们。

现在,这是我编写的代码,可以更好地演示您正在尝试做的事情以及我在说什么:

/*
timer1-arduino-makes-serial-not-work.ino
-a demo to help out this person here: http://stackoverflow.com/questions/28880226/timer1-arduino-makes-serial-not-work
By Gabriel Staples
http://electricrcaircraftguy.blogspot.com/
5 March 2015
-using Arduino 1.6.0
*/

//Note: ISR stands for Interrupt Service Routine

//Global variables
volatile unsigned long numISRcalls = 0; //number of times the ISR is called

void setup()
{
Serial.begin(115200);

//http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS
// noInterrupts(); //Not necessary
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for 1000000hz increments with 8 bits prescaler
OCR1A = 20;// = (16*10^6) / (1000000*8) - 1 (must be <65536) //better to put this line AFTER configuring TCCR1A and B, but in Arduino 1.6.0 it appears to be ok here (may crash code in older versions, see comment by "Thorsten" here: http://www.righto.com/2009/07/secrets-of-arduino-pwm.html
// turn on CTC mode [Clear Timer on Compare match---to make timer restart at OCR1A; see datasheet pg. 133]
TCCR1B |= (1 << WGM12);
// Set CS11 bit for 8 prescaler [0.5us ticks, datasheet pg. 135]. Each timer has a different bit code to each prescaler
TCCR1B |= (1 << CS11);
// enable timer compare match 1A interrupt; NOW YOU *MUST* SET UP THE CORRESPONDING ISR OR THIS LINE BREAKS THE CODE
TIMSK1 |= (1 << OCIE1A);

// OCR1A = 20;// = (16*10^6) / (1000000*8) - 1 (must be <65536) //SETTING OCR1A TO 1 OR 2 FOR SURE BREAKS THE CODE, as it calls the interrupt too often
// interrupts();

Serial.println("setup done, input a character");
}

void loop()
{
if (Serial.available())
{
Serial.read(); //read and throw away the first byte in the incoming serial buffer (or else the next line will get called every loop once you send the Arduino a char)
Serial.println("a");

//also print out how many times OCR1A has been reached by Timer 1's counter
noInterrupts(); //turn off interrupts while reading non-atomic (>1 byte) volatile variables that could be modified by an ISR at any time--incl while reading the variable itself.
unsigned long numISRcalls_copy = numISRcalls;
interrupts();
Serial.print("numISRcalls = "); Serial.println(numISRcalls_copy);
}

// Serial.println("test");
// delay(1000);
}

//SINCE YOU ARE ENABLING THE COMPARE MATCH 1A INTERRUPT ABOVE, YOU *MUST* INCLUDE THE CORRESPONDING INTERRUPT SERVICE ROUTINE CODE
ISR(TIMER1_COMPA_vect)
{
//insert your code here that you want to run every time the counter reaches OCR1A
numISRcalls++;
}


运行它,看看您的想法。

证明上面的“重大问题1”是真实的(至少据我所知-并且基于使用IDE 1.6.0在Arduino Nano上的测试):
下面的代码可以编译,但不会继续打印“ a”(但是,它可能只打印一次)。请注意,为简单起见,我注释掉了等待串行数据的部分,并简单地告诉它每半秒打印一个“ a”:

void setup() {

Serial.begin(115200);

//http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for 1000000hz increments with 8 bits prescaler
OCR1A = 20;// = (16*10^6) / (1000000*8) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS11 bit for 8 prescaler. Each timer has a different bit code to each prescaler
TCCR1B |= (1 << CS11);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
}

void loop() {
//if (Serial.available()) {
// Serial.println("a");
//}

Serial.println("a");
delay(500);
}

//ISR(TIMER1_COMPA_vect)
//{
// //insert your code here that you want to run every time the counter reaches OCR1A
//}


另一方面,下面的代码有效,并且“ a”将继续打印。该代码与上面的代码唯一的区别是,该代码的底部没有注释ISR声明:

void setup() {

Serial.begin(115200);

//http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for 1000000hz increments with 8 bits prescaler
OCR1A = 20;// = (16*10^6) / (1000000*8) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS11 bit for 8 prescaler. Each timer has a different bit code to each prescaler
TCCR1B |= (1 << CS11);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
}

void loop() {
//if (Serial.available()) {
// Serial.println("a");
//}

Serial.println("a");
delay(500);
}

ISR(TIMER1_COMPA_vect)
{
//insert your code here that you want to run every time the counter reaches OCR1A
}


额外资源:


我在这里写的文章的底部列出了最有用的Arduino资源的运行清单: http://electricrcaircraftguy.blogspot.com/2014/01/the-power-of-arduino.html。去看一下。
特别要看Ken Shirriff和Nick Gammon在“高级”部分下的第一个链接。他们很棒!


如果可以解决您的问题,请对此答案投票,并接受它作为正确答案;谢谢!

真诚的
加布里埃尔·斯台普斯
http://www.ElectricRCAircraftGuy.com/

关于timer - Timer1 arduino使Serial不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28880226/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com