Прерывание по поступлению байта, USART прерывание - Arduino mega 2560

b707
Offline
Зарегистрирован: 26.05.2017

brokly пишет:

Аааа, понял :) Ну тогда ch=*(char*)&"\n" .

не, до такого яб не додумался :) 

как я уже выше отвечал детсимену - я бы просто ch = 0x0A написал бы

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

b707 пишет:

не, до такого яб не додумался :) 

как я уже выше отвечал детсимену - я бы просто ch = 0x0A написал бы

А че... и туда тоже можно ! Лучше сh=10.

 

b707
Offline
Зарегистрирован: 26.05.2017

brokly пишет:

А че... и туда тоже можно ! Лучше сh=10.

 

низя! 10 - это обычное число. А в этой строчке нужен символ :)

kolyn
Offline
Зарегистрирован: 18.01.2019

Про бинарные 1010 забыли. Контроллер без перевода поймет))

alexbmd
Offline
Зарегистрирован: 15.01.2016

brokly пишет:

Может стоит написать  char ch='\n' ?

это не мне если что.  там переписка выше про в ногу.

brokly пишет:

3 варианта...

4.. в линуксе по другому например , putty тоже не как ардуино шлёт и т.д.

alexbmd
Offline
Зарегистрирован: 15.01.2016

b707 пишет:

низя! 10 - это обычное число.

http://arduino.ru/forum/programmirovanie/preryvanie-po-postupleniyu-bait...

alexbmd
Offline
Зарегистрирован: 15.01.2016

а буквы цифры это не обычное число ? чем ескейп отличается ?... лдано проехали :)

b707
Offline
Зарегистрирован: 26.05.2017

brokly пишет:

b707 пишет:

а оно такое есть? - \n\r

Конечно !  Еще как.  Даже в терминалке ИДЕ имеет место быть и это не с проста :)

Брукли, нет там такого:

только три варианта - "Newline" = \n, "Carriage return" = CR = \r и "NL + CR both", что, на саом деле, является \r\n.

Варианта \n\r я не встречал нигде за свои 30 лет работы с компами. Думаю, что такого не бывает вовсе. Покажите мне пример, где такое используется.

rkit
Онлайн
Зарегистрирован: 23.11.2016

b707 пишет:

 '\n' - это непонятно что, ни два ни полтора, ибо эскейп-последовательности работают только в двойных кавычках.

нет

b707
Offline
Зарегистрирован: 26.05.2017

rkit пишет:

нет

опоздал. уже выяснили. Лучше про \n\r напиши, если знаешь

alexbmd
Offline
Зарегистрирован: 15.01.2016

putty только \r

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

b707 пишет:

Варианта \n\r я не встречал нигде за свои 30 лет работы с компами. Думаю, что такого не бывает вовсе. Покажите мне пример, где такое используется.

по русски - возврат каретки, перевод строки, могу на пальцах рассказать почему так, так как наследие печатающих машинок, в кодах 0x0D, 0x0A

b707
Offline
Зарегистрирован: 26.05.2017

alexbmd пишет:

putty только \r

В какой ОС?

скорее всего, как обычно, путаешь.

Открыл путти - по умолчанию там '\n'. Но в настройках можно выставить и \r\n

Green
Offline
Зарегистрирован: 01.10.2015

Это обычные символы. \r - carriage return, возврат каретки по нашему, в терминале он вызывает возврат на начало строки.
\n - new line, понятно, в терминале переходит курсор на новую строку в той же позиции. Так было изначально, как на печатающей машинке. Никто не мешает поменять их местами, результат не изменится - курсор будет в начале следующей строки.
Уже в дальнейшем, начались вариации, типа, \r - возврат с переводом, так же как и \n.
Escape последовательности - начинаются с ESC, он же '\e', он же \0x1b, второй символ обычно '[', ну и дальше последовательность может быть достаточно длинной, например '\e','[','\5',';','\0','H' - это прямая адресация курсора.

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

Green пишет:

Это обычные символы. \r - carriage return, возврат каретки по нашему, в терминале он вызывает возврат на начало строки.
\n - new line, понятно, в терминале переходит курсор на новую строку в той же позиции. Так было изначально, как на печатающей машинке. Никто не мешает поменять их местами, результат не изменится - курсор будет в начале следующей строки.
Уже в дальнейшем, начались вариации, типа, \r - возврат с переводом, так же как и \n.
Escape последовательности - начинаются с ESC, он же '\e', он же \0x1b, второй символ обычно '[', ну и дальше последовательность может быть достаточно длинной, например '\e','[','\5',';','\0','H' - это прямая адресация курсора.

Quick Help по Си:  C escape sequences:

 

 

Green
Offline
Зарегистрирован: 01.10.2015

А я о терминальных ESC последовательностях.) Вроде о них у нас речь или нет?

Green
Offline
Зарегистрирован: 01.10.2015

Да, для компилятора С/С++ \r или \0x0d это тоже последовательность, но на выходе получается один символ. Почему ESC? Наверно потому что Escape - это экранировать с английского, наиболее подходящее по смыслу значение.

alexbmd
Offline
Зарегистрирован: 15.01.2016

b707 пишет:

В какой ОС?

Win.
Как понимаю стандарта нету и каждый пляшет як хочет.

nik182
Онлайн
Зарегистрирован: 04.05.2015

Ввёл escape в гугле. Получил кучу вариантов. Среди вариантов экранировать не присутствует. А то думал может чего упустил. 

"escape": варианты перевода
имя сущ.
побег
escape, shoot, runaway, flight, sprout, getaway
выход
output, exit, out, outlet, escape, entrance
бегство
escape, flight, getaway, stampede, evasion, bolt
спасение
salvation, rescue, saving, escape, salvage, redemption
утечка
leakage, leak, escape, outflow, seepage, wastage
истечение
expiration, expiry, outflow, issue, efflux, escape
избавление
deliverance, disposal, release, escape, riddance, rescue
выделение
discharge, excretion, liberation, secretion, allotment, assignment
переход
transition, conversion, jump, passage, crossing, junction
выпуск
issue, edition, output, issuance, outlet, emission
уход от действительности
escape
выпускное отверстие
outlet, nozzle, discharge, spout, tap, escape
одичавшее культурное растение
escape
глагол
бежать
run, escape, flee, race, scoot, course
вырваться
break, escape, break away, break forth, shoot up, fetch away
избавиться
escape, dispose of, kick, offload, liquidate, kill off
отделаться
get off, escape, dispose of, freeze out, can
убегать
run away, escape, run, run off, skidoo, outrun
ускользать
escape, elude, slip, evade
спасаться
escape, save oneself, get off
избегать
avoid, shun, escape, evade, steer clear of, eschew
миновать
pass, escape, clear, be over, overblow, blow over
вырываться
escape
избежать опасности
escape, shun danger
совершать побег
escape
улетучиваться
volatilize, escape, evaporate, melt away
смываться
wash off, disappear, run off, slip away, come off, scoot
давать утечку
escape
утечь
leak, escape
имя прил.
спасательный
lifesaving, rescuing, escape, wrecking, salvaging

 

 

alexbmd
Offline
Зарегистрирован: 15.01.2016

Пожалуйста просвятите. К примеру у нас такая функция по обработке поступающего байта
 

unsigned char USART_Receive (void){
 /* Wait for data to be received */
 while (!(UCSRnA & (1<<RXCn)));
 /* Get and return received data from buffer */
 switch (c) {
 case 'A':  do something very long;
 }
}

И к примеру оброботчик у нас очень длиный и долгий.

Что будет со следующим байтом в буфере ?  Пропадет ? через сколько ? перезапишется ? через сколько ?
Как много байт может храниться в буфере? или только один ?

alexbmd
Offline
Зарегистрирован: 15.01.2016

nik182 пишет:

экранировать не присутствует.


Это пошло издавна и не только в Си. Везде где есть спец символы в РУнете обычно пишут и говорят экранировать... отчего так не знаю

nik182
Онлайн
Зарегистрирован: 04.05.2015

Я не про экранирование. Я про перевод слова escape. В Си управляющие последовательности начинаются с \ . Это тоже экранирование и ни какого отношения к escape не имеет. 

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

alexbmd пишет:

И к примеру оброботчик у нас очень длиный и долгий.

Что будет со следующим байтом в буфере ?  Пропадет ? через сколько ? перезапишется ? через сколько ?
Как много байт может храниться в буфере? или только один ?

Так а зачем в обработке прерывания делать что то долго? Нужно принять байт, положить его в кольцевой буфер и сдвинуть указатель головы. А обрабатывать уже не в прерывании, вытаскивая символы из этого буфера и сдвигая указатель на хвост. Сравнялись указатели хвоста и головы - буфер пуст.

Аппаратного буфера у AVR нет, есть место под принятый байт. Не успели забрать, перепишется следующим пришедшим.    

 

b707
Offline
Зарегистрирован: 26.05.2017

alexbmd пишет:

И к примеру оброботчик у нас очень длиный и долгий.

Что будет со следующим байтом в буфере ?  Пропадет ? через сколько ? перезапишется ? через сколько ?

дальше фразы про "длинный и долгий обработчик" можно не читать.

Алекс, ты не о том беспокоишься. Потеря байта?... ерунда. "Очень длинный и долгий" обработчик прерывания приведет не только к остановке чтения из UART - это приведет к блокировке всех других прерываний в системе, включая любые другие шины (I2C SPI), а так же таймеры, включая SYSTick

Вывод - "длинный и долгий обработчик" вообще не стоит обсуждать. это гавнокод и его в программе просто быть не должно. В обработчике ты только принимаешь байт и кладешь в буфер, а длинная и долгая обработка вся должна быть в основном цикле программы, а не в прерывании

 

alexbmd
Offline
Зарегистрирован: 15.01.2016

SergeiL пишет:

Так а зачем в обработке прерывания делать что то долго?

 

это не прерывание это функция.  под словом обработчик я имел ввиду код обрабатывающий полученный символ из UDR [которй мы можем получить и через обычную функцию внутри лупа]

alexbmd
Offline
Зарегистрирован: 15.01.2016

b707 не не это не обработчик. про ISR всё понятно что долго и длино.

 и вообще я долго и длино фразу использовал чтоб поднять вопросы которые я там спросил. понятно что надо писать быстро и коротко. суть не в этом. суть в вопросах .  как долго храниться/что потом и т.д.

b707
Offline
Зарегистрирован: 26.05.2017

alexbmd пишет:

это не прерывание это функция.  под словом обработчик я имел ввиду код обрабатывающий полученный символ из UDR [которй мы можем получить и через обычную функцию внутри лупа]

это проще, потому что не станет вешать весь МК. Тем не менее рекомендации те же - разделить прием и обработку. В обработке ты только читаешь байт из регистра и кладешь в буфер, а обрабатывающую функцию запускаешь отдельно. И функция твоя должна регулярно прерываться и читать из регистра очередной пришедший байт

b707
Offline
Зарегистрирован: 26.05.2017

alexbmd пишет:

суть не в этом. суть в вопросах .  как долго храниться/что потом и т.д.

как раз это не суть. От того, хранится ли один байт или например 8 или 16 - мало что меняется. если обработка действительно "долгая" - рано или поздно буфер переполнится и произойдет потеря информации

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

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

b707 пишет:
как раз это не суть. От того, хранится ли один байт или например 8 или 16 - мало что меняется. если обработка действительно "долгая" - рано или поздно буфер переполнится и произойдет потеря информации

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

Меняется, особенно, когда Flow Control реализован.

Но я понимаю, что это не тот случай. 

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

Вставило, решил вспомнить - проверить.

При записи в файл, в MS-DOS и Windows  по '\n' писалось 0x0D, 0x0A.

При записи в файл '\r' писалось только 0x0D.

А в Unix, как мне вспоминается, 0x0A было, но могу и ошибаться, более 30 лет прошло. 

alexbmd
Offline
Зарегистрирован: 15.01.2016

b707, SergeiL оно понятно что надо постояно записывать из поступающего буфера и т.д.

тут вопрос больше позновательный а не посыл к действию...  хочется понять  (если приём без буфера.  ведь впринципе можем реализоват и без. понятно что с оговрками  и не везде)  как долго будет байт в буфере и что потом если не заберём..

пропадут все остальные пока это не заберем.. если такой вариант то через сколько времени прилетит следующий чтобы понять сколько у нас времени в запасе...

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

b707
Offline
Зарегистрирован: 26.05.2017

alexbmd пишет:

через сколько времени прилетит следующий
 

Когда ты выставляешь скорость порта, например так:

Serial.begin(9600);

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

nik182
Онлайн
Зарегистрирован: 04.05.2015

А пишите то в какой среде? Если в ардуне - то она уже позаботилась о кольцевом буфере и по прерыванию туда собственно и скидывает. А все процедуры ардуиновские достают из буфера а не из регистра МК. Если где то ещё, то пока не встречал МК у которого в стандартных примерах производителя нет кольцевого буфера на UART. Зачем изобретать велосипед? Может проще на кошках учиться? ((С) Операция Ы....) 

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

nik182 пишет:
А пишите то в какой среде? Если в ардуне - то она уже позаботилась о кольцевом буфере и по прерыванию туда собственно и скидывает.

alexbmd пишет:

это не прерывание это функция.  под словом обработчик я имел ввиду код обрабатывающий полученный символ из UDR [которй мы можем получить и через обычную функцию внутри лупа]

Тоже не понимаю почему стандартный Сериал не устраивает. 

alexbmd
Offline
Зарегистрирован: 15.01.2016

всем устраивает (ну кроме размера конечно)..  так интересуюсь для изучения и расширения познаний

если правильно посчитал при скорости 57600 уходит 1мс на байт...  осталось не понятным след байт перезаписывает тот что в регистре или пропадает, ну если регистр не успели считать..

nik182
Онлайн
Зарегистрирован: 04.05.2015

Как то не правильно посчитали 1сек/57600*11 = 190 мкс или 0.19 мс.

alexbmd
Offline
Зарегистрирован: 15.01.2016

Пожалуйста подскажите. Наверно успускаю какуюто важную деталь , никак не пойму какую. Плата Nano

class USART {

  private:
    typedef uint8_t T;
    volatile T C = 0;

  public:
    inline void begin(const uint16_t ubrr = 9600, const uint8_t format = 6) {
      cli();
      UCSR0A |= bit(U2X0);
      UBRR0H = (uint8_t)((F_CPU / 8L / ubrr - 1) >> 8);
      UBRR0L = (uint8_t)((F_CPU / 8L / ubrr - 1) & 0xFF);
      // Enable receiver, transmitter, interrupt
      UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0) | (0 << TXCIE0) | (0 << UDRIE0);
      // Set frame format 8N1
      UCSR0C = format;
      sei();
    }

    inline bool rx_interrupt() {
      // Wait while UDR buffer is empty. RXC0 = 1 has unread data
      while (!(UCSR0A & (1 << RXC0)));
      C = UDR0;
    }

    inline bool write(const T c) {
      // Wait until buffer is empty. UDRE0 = 1 can receive new data. TXC0 = 1 transmit completed
      while (!(UCSR0A & (1 << UDRE0)));
      // Put data into buffer
      UDR0 = c;
      return (UCSR0A & (1 << UDRE0));
    }

    inline bool write(const char *s) {
      bool b = (strlen(s)) ? true : false;
      while (b && *s) b = write(*s++);
      return b;
    }

    inline T read() {
      return C;
    }

};

USART serial;
int flag = 1;

void setup() {
  DDRB |= (1 << 5);
  serial.begin(19200);
}

void loop() {
  if (flag) {
    serial.write("begin..\r\n");
    flag = 0;
  }
  static uint32_t t = 0;
  if (UCSR0A & bit(U2X0)) {
    if ( millis() - t > 2000 ) {
      PORTB ^=  (1 << 5);
      t = millis();
    }
  }
  char c = serial.read();
  if (c > 31) serial.write(c);

}

ISR(USART_RX_vect) {
  serial.rx_interrupt();
}

2 проблемы

1) ни как не пойму почему строчка 56 печатается только be. стр 28 проверяем если готовы принять следующий символ. по идее не должно быть печати в "нахлёст" или "съеденных" букв. ни как не пойму почему только два символа.

2) если мы в инпут отправляем строку, например "Hello world" то напечать выводит "HHHello world". можно подумать что скетч слишком быстрый и успевает прочесть один и тот же символ дважды/трижды но нет. это происходит только с первым сиволом даже на длинной строке.

подскажите плиз как без буфера исправить данные баги?

alexbmd
Offline
Зарегистрирован: 15.01.2016

первый вопрос решил. остался второй. есть идеи ?