Как работает последовательная связь с Arduino?

Что касается Arduino Uno, Mega2560, Leonardo и подобных плат:

  • Как работают последовательные коммуникации?
  • Как быстро последователен?
  • Как подключиться между отправителем и получателем?

Обратите внимание: это задание в качестве справочного вопроса.

11 голосов | спросил Nick Gammon 20 Jam1000000amWed, 20 Jan 2016 05:45:05 +030016 2016, 05:45:05

1 ответ


12

Асинхронная последовательная (обычно называемая последовательной) связь используется для отправки байтов с одного устройства на другое. Устройство может быть одним или несколькими из следующих:

  • Arduino
  • PC
  • GPS
  • Устройство чтения RFID
  • ЖК-дисплей
  • Модем
  • Другое

Частота и выборка данных

В отличие от последовательной связи SPI /USB /I2C нет тактового сигнала. Часы выборки - это согласованная частота дискретизации (известная как скорость передачи). Как отправитель, так и приемник должны быть настроены так, чтобы использовать ту же скорость, или получатель получит бессмысленные данные (из-за того, что биты не отбираются с той же скоростью, в какой они были отправлены).

Передача асинхронная , которая в основном означает, что байты могут быть отправлены в любое время, с между ними разный промежуток. Этот график иллюстрирует отправку одного байта:

 Последовательные сообщения - отправка одного байта

На рисунке выше показана буква «F». В ASCII это 0x46 (в шестнадцатеричном) или 0b01000110 (в двоичном формате). Сначала передается значительный (младший) бит , поэтому в приведенном выше графике вы видите биты, поступающие в порядке: 01100010.

«Время ожидания» между байтами передается как непрерывные «1» биты (фактически, линия передачи удерживается высоко непрерывно).

Чтобы указать начало байта, Начальный бит всегда указывается, потянув линию на низком уровне, как показано на графике. Как только приемник увидит стартовый бит, он ожидает в 1,5 раза больше времени выборки, а затем отображает бит данных. Он ждет 1,5 раза, чтобы он:

  • Пропускает стартовый бит
  • Образцы на полпути через следующий бит

Если скорость передачи в бодах составляет, например, 9600 бод, тогда частота дискретизации будет 1/9600 = 0.00010416 секунд (104,16 Âμs).

Таким образом, при 9600 бодах, после приема стартового бита приемник ждет 156,25 Âμs, а затем образцы каждые 104,16 Âμs.

 Время начала бит

Цель Стопового бит заключается в том, чтобы определенно было 1 бит между каждым байтом. Без стопового бита, если байт закончил с нулем, тогда аппаратное обеспечение не сможет определить разницу между этим и стартовым битом следующего байта.

Чтобы создать вышеупомянутый вывод в Uno, вы можете написать этот код:

 void setup()
  {
      Serial.begin(9600);
      Serial.print("F");
  }

void loop ()
  {
  }

Число бит данных

Чтобы сохранить время передачи (в прежние дни, хех), вам было разрешено указывать разные количества бит данных. Аппарат AtMega поддерживает биты данных с номерами от 5 до 9. Ясно, что чем меньше бит данных, тем меньше информации вы можете отправить, но тем быстрее будет.


Биты четности

Вы можете иметь бит четности. Это вычисляется, если требуется, путем подсчета количества символов 1 в символе, а затем для уверенности, что это число нечетно или даже, если необходимо установить бит четности в 0 или 1.

Например, для буквы «F» (или 0x46 или 0b01000110) вы можете видеть, что там есть 3 (в 01000110). Таким образом, мы уже имеем нечетную четность. Таким образом, бит четности будет следующим:

  • Нет четности: опущен
  • Четность: a 1 (3 + 1 четно)
  • Нечетная четность: a 0 (3 + 0 нечетно)

Бит четности, если он присутствует, появляется после последнего бита данных, но до стопового бита.

Если получатель не получает правильный бит четности, это называется «ошибкой четности». Это указывает на некоторую проблему. Возможно, отправитель и получатель настроены на использование разных скоростей бод (бит), или на линии был шум, который превратил ноль в один или наоборот.

В некоторых ранних системах также использовалась четность «отметки» (где бит четности всегда был 1 независимо от данных) или «косвенная» четность (где бит четности всегда был 0 независимо от данных).


9-разрядная передача

В некоторых коммуникационных устройствах используются 9-битные данные, поэтому в этих случаях бит четности преобразуется в 9-й бит. Существуют специальные методы для отправки этого 9-го бита (регистры являются 8-битными регистрами, поэтому 9-й бит должен быть помещен где-то еще).


Число стоповых бит

Раннее оборудование, как правило, было несколько медленнее в электронном виде, поэтому, чтобы дать приемнику время для обработки входящего байта, иногда указывалось, что отправитель отправит два стоповых бита. Это в основном добавляет больше времени, когда линия данных удерживается высоко (еще одно бит) до того, как появится следующий стартовый бит. Это дополнительное время бит дает время приемника для обработкипоследний входящий байт.

Если приемник не получает логический 1, когда предполагается бит стопа, это называется «ошибкой кадрирования». Это указывает на некоторую проблему. Вполне возможно, что отправитель и получатель настроены на использование разных скоростей бод (бит).


нотации

Обычно последовательная связь указывается указанием скорости, количества бит данных, типа четности и количества стоповых бит, например:

 9600/8-N-1

Это говорит нам:

  • 9600 бит в секунду
  • 8 бит данных
  • Нет четности (вы можете видеть вместо этого: E = четный, O = нечетный)
  • 1 стоповый бит

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


Pin-аутов

В Arduino Uno имеются цифровые контакты 0 и 1 для серийного оборудования:

 Arduino Uno serial pins

Чтобы подключить два Arduinos, вы замените Tx и Rx следующим образом:

 Подключение двух Arduinos вместе


Speed ​​

Поддерживается широкий диапазон скоростей (см. рисунок ниже). «Стандартные» скорости обычно кратные 300 бод (например, 300/600/1200/2400 и т. Д.).

Другие «нестандартные» скорости могут быть обработаны путем установки соответствующих регистров. Класс HardwareSerial делает это за вас. например.

 Serial.begin (115200);  // set speed to 115200 baud

Как правило, если вы используете 8-битные данные, вы можете оценить количество байтов, которое вы можете передавать в секунду, разделив скорость передачи на 10 (из-за стартового бита и стопового бита) .

Таким образом, при 9600 бодах вы можете передавать 960 байт (9600 / 10 = 960) в секунду.


Ошибки скорости передачи

Скорость передачи на Atmega генерируется путем деления системных часов и последующего подсчета до заданного числа. Эта таблица из таблицы показывает значения регистра и процент ошибок для тактовой частоты 16 МГц (например, для Arduino Uno).

 Ошибка скорости передачи

бит U2Xn влияет на делитель тактовой частоты (0 = деление на 16, 1 = деление на 8). Регистр UBRRn содержит число, на которое рассчитывается процессор.

Итак, из приведенной выше таблицы видно, что мы получаем 9600 бод с тактовой частотой 16 МГц следующим образом:

 16000000 / 16 / 104 = 9615

Мы делим на 104, а не на 103, потому что счетчик равен нулю. Таким образом, здесь возникает ошибка 15 / 9600 = 0.0016, которая близка к тому, что сказано выше в таблице (0.02%).

Вы заметите, что некоторые скорости обмена имеют более высокое количество ошибок, чем другие.

В соответствии с таблицей данных максимальный процент ошибки для 8 бит данных находится в диапазоне от 1,5% до 2,0% (подробнее см. техническое описание).


Ардуино Леонардо

У Arduino Leonardo и Micro есть другой подход к последовательной связи, поскольку они напрямую подключаются через USB к главному компьютеру, а не через последовательный порт.

Из-за этого вы должны дождаться, когда Serial станет «готовым» (поскольку программное обеспечение устанавливает соединение USB), с дополнительными парами строк, например:

 void setup()
  {
      Serial.begin(115200);
      while (!Serial)
      {}  // wait for Serial comms to become ready
      Serial.print("Fab");
  }

void loop ()
  {
  }

Однако, если вы хотите действительно общаться через контакты D0 и D1 (а не через USB-кабель), вам нужно использовать Serial1, а не Serial. Вы делаете это так:

 void setup()
  {
      Serial1.begin(115200);
      Serial1.print("Fab");
  }

void loop ()
  {
  }

Уровни напряжения

Обратите внимание, что Arduino использует уровни TTL для последовательной связи. Это означает, что он ожидает:

  • Бит «нуль» равен 0 В
  • «Один» бит + 5 В

Старое серийное оборудование, предназначенное для подключения к последовательному порту ПК, возможно, использует уровни напряжения RS232, а именно:

  • Бит «нуля» равен +3 +15 В
  • «Один» бит - от 3 до 15 вольт.

Не только это «инвертировано» по отношению к уровням TTL («один» более отрицателен, чем «нуль»), Arduino не может обрабатывать отрицательные напряжения на своих входных выводах (а не положительные значения более 5 В).

Таким образом вам нужна интерфейсная схема для связи с такими устройствами. Только для входа (только для Arduino) простой транзистор, диод и пара резисторов будут делать это:

 Инвертирование буфера

Для двусторонней связи вы должны иметь возможность генерировать отрицательные напряжения, поэтому требуется более сложная схема. Например, чип MAX232 будет делать это в сочетании с четырьмя конденсаторами емкостью 1 мкФ, чтобы действовать как схемы зарядного насоса.


Программное обеспечение Serial

Существует библиотека под названием SoftwareSerial, которая позволяет выполнять последовательную связь (вплоть до точки) в программном обеспечении, а не в аппаратном обеспечении. Это имеет то преимущество, что вы можете использовать различные конфигурации контактов для последовательной связи. Недостатком является то, что выполнение серийного программного обеспечения является более интенсивным с точки зрения процессора и более подверженным ошибкам. Подробнее см. Software Serial .


Mega2560

Arduino «Mega» имеет 3 дополнительных аппаратных последовательных порта. Они помечены на плате как Tx1 /Rx1, Tx2 /Rx2, Tx3 /Rx3. Они должны использоваться, если это возможно, в предпочтении SoftwareSerial. Чтобы открыть эти другие порты, вы используете имена Serial1, Serial2, Serial3, например:

 Serial1.begin (115200);  // start hardware serial port Tx1/Rx1
Serial2.begin (115200);  // start hardware serial port Tx2/Rx2
Serial3.begin (115200);  // start hardware serial port Tx3/Rx3

Прерывания

Как отправка, так и получение с использованием библиотеки HardwareSerial используют прерывания.

Отправка

Когда вы выполняете Serial.print, данные, которые вы пытаетесь распечатать, помещаются во внутренний буфер передачи. Если у вас 1024 байта или более ОЗУ (например, на Uno), вы получаете 64-байтовый буфер, иначе вы получите 16-байтовый буфер. Если в буфере есть место, то Serial.print немедленно возвращается, что не задерживает ваш код. Если нет места, тогда он «блокирует», ожидая, что буфер будет опустошен настолько, чтобы там было место.

Затем, когда каждый байт передается аппаратным обеспечением, вызывается прерывание (прерывание «USART, Data Register Empty»), а процедура прерывания отправляет следующий байт из буфера из последовательного порта.

Прием

При приеме входящих данных вызывается процедура прерывания (прерывание «USART Rx Complete»), а входящий байт помещается в буфер приема (такого же размера, как упомянутый выше буфер передачи).

Когда вы вызываете Serial.available, вы узнаете, сколько байтов доступно в этом буфере приема. Когда вы вызываете Serial.read, байт удаляется из буфера приема и возвращается в ваш код.

В Arduinos с объемом памяти 1000 байт или более, нет необходимости спешить с удалением данных из буфера приема, если вы не позволите ему заполнить. Если он заполняется, любые дальнейшие входящие данные отбрасываются.

Обратите внимание, что из-за размера этого буфера нет смысла ожидать появления большого количества байтов, например:

 while (Serial.available () < 200)
  { }  // wait for 200 bytes to arrive

Это никогда не будет работать, потому что буфер не может удержать это.


Советы

  • Перед чтением всегда убедитесь, что данные доступны. Например, это неверно:

     if (Serial.available ())
      {
          char a = Serial.read ();
          char b = Serial.read ();  // may not be available
      }
    

    Тест Serial.available только гарантирует наличие одного байта, однако код пытается прочитать два. Он может работать, если в буфере есть два байта, если вы не получите -1, который будет выглядеть как «Ã¿», если будет напечатан.

  • Помните, сколько времени требуется для отправки данных. Как упоминалось выше, при 9600 бодах вы передаете только 960 байт в секунду, поэтому попытка отправить 1000 показаний с аналогового порта на скорости 9600 бод не будет очень успешной.


Ссылки

ответил Nick Gammon 20 Jam1000000amWed, 20 Jan 2016 05:45:05 +030016 2016, 05:45:05

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132