运行下面的代码,当我发送串行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");
}
}
Run Code Online (Sandbox Code Playgroud)
Gab*_*les 13
设置TCCR1A和B的方式都是正确的.
请参阅660-pg ATmega328数据表.132~135如需了解更多帮助和信息,如果您想了解从现在开始的低级别帮助.
但是,您有2个主要问题,1个小问题和1个推荐.
将其添加到代码的底部:
ISR(TIMER1_COMPA_vect)
{
//insert your code here that you want to run every time the counter reaches OCR1A
}
Run Code Online (Sandbox Code Playgroud)
如果您设置OCR1A = 20,并按上述方法添加ISR代码,您的代码将运行正常.
在配置剩余的定时器后,最好设置OCR1A ,否则在某些情况下定时器可能无法开始计数(请参阅"Thorsten"的评论:http://www.righto.com/2009/07/secrets -of-arduino-pwm.html)
所以,移动OCR1A = 20; 到后您的最后TCCR1B线和之前你TIMSK1线.
摆脱"noInterrupts"和"中断".这里不需要它们.
现在,这是我写的代码,它将更好地展示你正在尝试做什么,以及我在说什么:
/*
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++;
}
Run Code Online (Sandbox Code Playgroud)
运行它,看看你的想法.
证明上面的"主要问题1"是真实的(至少据我所知 - 并且基于对Arduino Nano的测试,使用IDE 1.6.0):
下面的代码编译,但不会继续打印" 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
//}
Run Code Online (Sandbox Code Playgroud)
另一方面,下面的代码有效,"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
}
Run Code Online (Sandbox Code Playgroud)
我在这里写的文章的底部有一个最有用的Arduino资源的运行列表:http://electricrcaircraftguy.blogspot.com/2014/01/the-power-of-arduino.html.去看一下.
特别是看看Ken Shirriff和Nick Gammon在"高级"部分下的第一个链接.他们很棒!
如果它能解决您的问题,请将此答案投票,并接受为正确的答案; 谢谢!
此致,
Gabriel Staples
http://www.ElectricRCAircraftGuy.com/
| 归档时间: |
|
| 查看次数: |
5430 次 |
| 最近记录: |