MEGA 2560. Прерывания по окончанию приема по UART

Тема в разделе "Arduino & Shields", создана пользователем @Anatoly, 16 апр 2015.

  1. @Anatoly

    @Anatoly Нерд

    День добрый.
    Соединены пo UART две ардуинки (Uno и Mega).
    Схема соединения:
    UNO ___ MEGA
    +5 В -> +5 В
    GND -> GND
    TX(1)->RX(0)
    RX(0)->TX(1)

    В MEGA выполняется некоторая задача, но при получении по UART от UNO сообщения необходимо в MEGA прервать выполнении основной программы и обработать пришедшее сообщение.

    Скетч UNO
    Код (Text):
    int dT = 2000;
    char str[128];

    void setup()
    {
      Serial.begin(9600);
    }

    void loop()
    {
      Serial.write("on");
      delay(dT);
      Serial.write("of");
      delay(dT);
    }
    Скетч MEGA
    Код (Text):
    #include <avr/interrupt.h> //библиотека прерываний

    char s[2];//Массив для приема байтов
    int i=0;//счетчик принятых байтов
    int ledpin = 13;

    void USART_Init(int baudrate ) //Функция инициализации USART
    {
      /* Set baud rate */
      UBRR0H = baudrate>>8;
      UBRR0L = baudrate;
      //Разрешение на прием и на передачу через USART, прерывания по поступлению и по опустошению
      UCSR0B = (1<<RXCIE0)|(1<<RXEN0);
      UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); //размер слова 8 разрядов
      sei();
     
    } // USART_Init

    void setup() {              
      // initialize the digital pin as an output.
      pinMode(ledpin, OUTPUT);  
    USART_Init(103);// число 103 соответствует baudrate 9600 при 16MHz. смотреть datasheet нa ATMega 2560
    }

    //Обрабатываем прерывание по поступлению байта
    ISR(USART0_RX_vect)
    {
      s[i]=UDR0;//принимаем байт в массив char
      i++;
      if (i == 2)//если приняли 2 байта
      {
        if (s[0] == 'o' and s[1] == 'n')//проверяем что приняли, если команду "on"
          {
            digitalWrite(ledpin, HIGH);//зажигаем светодиод
       

          }
         
        if (s[0] == 'o' and s[1] == 'f')//проверяем что приняли, если команду "of"
          {
            digitalWrite(ledpin, LOW);//гасим светодиод
         
          }
        // сбрасываем все
        i=0;
        s[0]='0';
        s[1]='0';
      }
    }


    // the loop routine runs over and over again forever:
    void loop() {
               
    }
     
    В данном случае работает прерывание по окончанию приема сообщения в MEGA.

    Но как быть если необходимо в MEGA использовать не Serial0, а Serial1 ?
    Менял ISR(USART0_RX_vect) на ISR(USART1_RX_vect), но прерывание не работает.
     
  2. X-Dron

    X-Dron Гик

    Дак, наверно менять нужно не только USART0, но, и UDR0, и
    перелопачивать функцию USART_Init на UART1
     
  3. @Anatoly

    @Anatoly Нерд

    Это логично. Вопрос как ее поменять?
    Гуглил, но никакой информации не смог найти...
     
  4. iglooshtosser

    iglooshtosser Гик

    Может ерунду пишу...

    Но Serial1 он, того, программный. Там фунции библиотеки дергают за пины сами. А значит инициализировать его как аппаратный (только другой порт) не получится.
     
  5. @Anatoly

    @Anatoly Нерд

    Сам разобрался:)
    Вот скетч на прием байт по Serial1.

    Код (Text):
    #include <avr/interrupt.h> //библиотека прерываний

    char s[2];//Массив для приема байтов
    int i=0;//счетчик принятых байтов
    int ledpin = 13;

    void USART_Init(int baudrate ) //Функция инициализации USART
    {
      /* Set baud rate */
      UBRR1H = baudrate>>8;
      UBRR1L = baudrate;
      //Разрешение на прием и на передачу через USART, прерывания по поступлению и по опустошению
      UCSR1B = (1<<RXCIE1)|(1<<RXEN1);
      UCSR1C = (1<<UCSZ01)|(1<<UCSZ00); //размер слова 8 разрядов
      sei();
    } // USART_Init

    void setup() {          
      // initialize the digital pin as an output.
      pinMode(ledpin, OUTPUT);
    USART_Init(103);// число 103 соответствует baudrate 9600 при 16MHz. смотреть datasheet нa ATMega 2560
    }

    //Обрабатываем прерывание по поступлению байта
    ISR(USART1_RX_vect)
    {
      s[i]=UDR1;//принимаем байт в массив char
      i++;
      if (i == 2)//если приняли 2 байта
      {
        if (s[0] == 'o' and s[1] == 'n')//проверяем что приняли, если команду "on"
          {
            digitalWrite(ledpin, HIGH);//зажигаем светодиод


          }
     
        if (s[0] == 'o' and s[1] == 'f')//проверяем что приняли, если команду "of"
          {
            digitalWrite(ledpin, LOW);//гасим светодиод
     
          }
        // сбрасываем все
        i=0;
        s[0]='0';
        s[1]='0';
      }
    }


    // the loop routine runs over and over again forever:
    void loop() {
           
    }
     
     
    X-Dron нравится это.
  6. Unixon

    Unixon Оракул Модератор

    На меге целых 4 аппаратных UART, внутри Wiring это Serial, Serial1, Serial2 и Serial3.
     
    iglooshtosser нравится это.
  7. iglooshtosser

    iglooshtosser Гик

    Спасибо. Не держу ещё в голове отличия линеек и путаюсь.