USART Arduino MEGA 1280

olegjan
Offline
Зарегистрирован: 05.03.2015

Здравствуйте, пишу программу для управления устройством с использованием контроллера AVR на базе ARDUINO MEGA 1280 (далее - МК) в сочетании с ПК.

Дело обстоит так:

1) ПК посылает один байт МК (1 или 2) по USART_0. 

2) МК выяснив что это за байт - выполняет инструкцию, которая заключается в передаче устройству двух байт синхронизации (7 и 128) по USART_1 и последующем ожидании одного байта синхронизации по USART_1 от устройства (88).

3) Устройство передаёт байт синхронизации MK (88) по USART_1.

4) Приняв байт синхронизации от устройства (88) по USART_1, МК выдаёт устройству ещё пару байт, на включение опций (7,16 или 7,18) по USART_1.



Проблема возникла на 4-ом шаге. Байт синхронизации МК принимает, но не может выдать последние два байта устройству. Хотя при выполнении 2-го шага, всё передалось без проблем.

вот код:

#define F_CPU 16000000UL
#define BAUD 38400
#define UBRR_VAL F_CPU/16/BAUD-1
 
unsigned char my_com;
 
void usart0_init (unsigned int my_speed)                       // Инициализация модуля USART_0
{
  UBRR0H = (unsigned char)(my_speed >> 8);                // Установка BAUDRATE
  UBRR0L = (unsigned char) my_speed;                         
  UCSR0A = 0x00;
  UCSR0B |= (1 << TXEN0);                                       // Разрешение работы передатчика  
  UCSR0B |= (1 << RXEN0);                                       // Разрешение работы приемника
  UCSR0C |= (1 << UCSZ01)|(1 << UCSZ00);               // 8 бит 
}
 
void usart1_init (unsigned int my_speed)                     // Инициализация модуля USART_1
{
  UBRR1H = (unsigned char)(my_speed >> 8);              // Установка BAUDRATE
  UBRR1L = (unsigned char) my_speed;                       
  UCSR1A = 0x00;
  UCSR1B |= (1 << RXEN1);                                      // Разрешение работы приемника
  UCSR1B |= (1 << TXEN1);                                      // Разрешение работы передатчика
  UCSR1C |= (1 << UCSZ11)|(1 << UCSZ10);               // 8 бит  
}
 
void setup() 
{
  usart0_init (UBRR_VAL);
  usart1_init (UBRR_VAL);
  my_com = 0;
}
 
void loop() 
{
  while(UCSR0A & (1 << RXC0))           // жду пока в регистре UDR0 появится байт
  {
    my_com = UDR0;                          // если появился - присвоил переменной
    if (my_com == 1) 
    {
      UDR1 = 7;                                 //1-й байт синхронизации от МК к Устройству
      UDR1 = 128;                              //2-й байт синхронизации от МК к Устройству
      if (UDR1 == 88)                          //байт синхронизации от Устройства
      {
        UDR1 = 7;                               //вот здесь проблема..
        UDR1 = 18;                             // эти байты не отправляются
      }
    }
    
    if (my_com == 2) 
    {
      UDR1 = 7;                                //1-й байт синхронизации от МК к Устройству
      UDR1 = 128;                             //2-й байт синхронизации от МК к Устройству
      if (UDR1 == 88)                         //байт синхронизации от Устройства
      {
        UDR1 = 7;                               //вот здесь проблема..
        UDR1 = 16;                             // эти байты не отправляются
      }
    }
  }
 }

 

помогите плиз!!

Datak
Offline
Зарегистрирован: 09.10.2014

olegjan пишет:

... выполняет инструкцию, которая заключается в передаче устройству двух байт синхронизации (7 и 128) по USART_1 и последующем ожидании одного байта синхронизации по USART_1 ...

В этом проблема.
Никакого ожидания на самом деле нет - байт из UDR1 считывается сразу после передачи двух байт в него. Ответ от устройства ещё не пришёл, регистр UDR1 в этот момент "пуст".

Если не верите, проверьте бит RXC1 в регистре UCSR1A.

olegjan
Offline
Зарегистрирован: 05.03.2015

насколько я понимаю, байт в регистре остается до тех пор пока его не прочитают..(UDR1 == 88) - вот этим и читаю, после этого регистр - пустой, а в доказательство того, воткнул в каждое из условий Serial.print, откуда очевидно, что байт синхронизации от устройства приходит, и МК его воспринимает должным образом..

olegjan
Offline
Зарегистрирован: 05.03.2015

Выявил ещё вот, что у МК при указанном раскладе вообще не получается передать более 2 байт, то есть если во 2-м шаге передать устройству не 2 (как изначально) а один байт, то МК получит байт синхронизации и передаст в ответ 1 байт (из двух положеных)..

Datak
Offline
Зарегистрирован: 09.10.2014

Строго говоря, читать регистр UDR можно только после того, как вы убедитесь, что в нём уже есть данные для чтения.

Вы же проверяете регистр UCSR0A перед чтением UDR0:

      while(UCSR0A & (1 << RXC0))              // жду пока в регистре UDR0 появится байт

Абсолютно то же самое нужно делать перед проверкой регистра UDR1:

      while( !( UCSR1A & ( 1 << RXC1 ) ) );    // ждём пока в регистре UDR1 появится байт

      if (UDR1 == 88)                          // байт синхронизации от Устройства
      {
        UDR1 = 7;                              //
        UDR1 = 18;                             //
      }

Вот так оно, может быть, и заработает.

Хотя, для полной правильности, перед записью байта тоже неплохо бы убедиться в готовности UART'а к приёму данных:

      while( !( UCSR1A & ( 1 << RXC1 ) ) );    // ждём пока в регистре UDR1 появится байт

      if (UDR1 == 88)                          // байт синхронизации от Устройства
      {
        while( !( UCSR1A & ( 1 << UDRE1 ) ) ); // ждём готовности UDR1 к приёму данных
        UDR1 = 7;                              //
        while( !( UCSR1A & ( 1 << UDRE1 ) ) ); // ждём готовности UDR1 к приёму данных
        UDR1 = 18;                             //
      }