我在将arduino网络实现Atmega328计时器时遇到问题

时间:2019-11-18 21:24:24

标签: networking arduino

我正在尝试通过两个arduinos之间的r / f通信实现纠错。我尝试向其中添加一个计时器,以创建重发数据包,但是只要它超过了第一次发送,它就会开始打印垃圾广告无穷大,而不是进行计时器中断。

我尝试弄乱内部循环条件,并试图弄清楚计时器出了什么问题,但我无法弄清楚。该问题似乎发生在第一次串行打印附近,这很奇怪,因为该部分代码大部分未更改。 (数据包是两个整数的结构)

#include <ELECHOUSE_CC1101.h>
#include "packets.h"

// These examples are from the Electronics Cookbook by Simon Monk
// Connections (for an Arduino Uno)
// Arduino          CC1101
// GND              GND
// 3.3V             VCC
// 10               CSN/SS   **** Must be level shifted to 3.3V
// 11               SI/MOSI  **** Must be level shifted to 3.3V
// 12               SO/MISO
// 13               SCK      **** Must be level shifted to 3.3V
// 2                GD0

const int n = 61;
unsigned short int sequence = 0;
byte buffer[n] = "";


void setup() {
  Serial.begin(9600);
  Serial.println("Set line ending to New Line in Serial Monitor.");
  Serial.println("Enter Message");
  ELECHOUSE_cc1101.Init(F_433); // set frequency - F_433, F_868, F_965 MHz
  // initialize timer1 

  noInterrupts();           // disable all interrupts

  TCCR1A = 0;

  TCCR1B = 0;

  TCNT1 = 0;


  OCR1A = 0xFFFF; // Max value for overflow for now

  TCCR1B |= (1 << CS12);    // 256 prescaler 



  interrupts();             // enable all interrupts

}
Packet pckt, recieve;

ISR(TIMER1_OVR_vect){          // timer compare interrupt service routine
    //Resend packet
    ELECHOUSE_cc1101.SendData(buffer, pckt.data + pckt.seqNum);
    int len = ELECHOUSE_cc1101.ReceiveData(buffer);
    buffer[len] = '\0';
    recieve.seqNum = buffer[n];
    Serial.println("Interrupt");


}


void loop() {
  if (Serial.available()) {
    pckt.data = Serial.readBytesUntil('\n', buffer, n);
    pckt.seqNum = sequence;
    buffer[pckt.data] = '\0';
    buffer[n-1] = pckt.seqNum;
    Serial.println((char *)buffer);

    ELECHOUSE_cc1101.SendData(buffer, pckt.data + pckt.seqNum);
    TCNT1 = 0; // clear timer
    TIMSK1 |= (1 << TOIE0);  // enable timer compare interrupt
    int len = ELECHOUSE_cc1101.ReceiveData(buffer);
    while (recieve.seqNum <= sequence) {

    }
    TIMSK1 &= ~(1 << TOIE0); // turn off the timer interrupt

  }
}

1 个答案:

答案 0 :(得分:1)

发送数据对于中断而言花费的时间太长。您应该在loop()函数调用树中保留用于发送和接收数据缓冲区的调用。例如,通过UART以9600波特发送12字节消息可能需要大约12ms。

您可以使用计时器中断来减少超时计数器,这通常是在微控制器上完成的,或者可以使用millis()函数来处理定时,这在Arduino上很容易做到。

我建议您使用millis()函数来计算超时。

示例:

/* ...  */

// I could not figure out what you were trying to do with 
// pckt.seqNum....  Putting it at the end of the buffer 
// makes no sense, so I've left it out.
// Moreover, its size is 2, so placing it at buffer[n-1] overflows the buffer...

enum machineState {
    waitingForSerial, 
    waitingForResponse,
};

unsigned int time_sent;  // Always use unsigned for variables holding millis()
                         // can use unsigned char for timeouts of 255  
                         // milliseconds or less. unsigned int is good for about 
                         // 65.535 seconds or less.

machineState state = waitingForSerial;

void loop()
{
    switch(state)
    {
    case waitingForSerial:
        pckt.data = Serial.readBytesUntil('\n', buffer, sizeof(buffer));
        if (pckt.data > 0)
        {
            ++pckt.seqNum;
            Serial.write(buffer, pckt.data);
            ELECHOUSE_cc1101.SetReceive();
            ELECHOUSE_cc1101.SendData(buffer, pckt.data);
            time_sent = millis();
            state = waitingForResponse;
       }
       break;

    case waitingForResponse:
        if (ELECHOUSE_cc1101.CheckReceiveFlag())
        {
            auto len = ELECHOUSE_cc1101.ReceiveData(buffer))  // can use C++17 with duinos!!!

            Serial.print("cc1101: ");
            Serial.write(buffer, len);
            state = waitingForSerial;  // wait for another command from PC
        }
        //  1 second timeout, note the cast and subtraction, this is to avoid any 
        //  issues with rollover of the millis() timestamp.
        else if ((unsigned int)millis() - time_sent > 1000)
        {
            // resend ...  stays stuck this way.
            Serial.println("Retrying :(");
            ELECHOUSE_cc1101.SendData(buffer, pckt.data);
            time_sent = millis();
        }
        break;

    default:
        state = waitingForSerial;
        Serial.println("unhandled state");
        break;
    }
}