parovoZZ

Философия аппаратного SPI - чем занять МК?

69 сообщений в этой теме

BARS_    882
1 час назад, parovoZZ сказал:

В любом другом случае эффективнее самим опрашивать аппаратный флаг счетчика и самим же его сбрасывать.

Если в программе нет ничего, кроме опроса флага, то эффективнее. В противном случае нет.

 

1 час назад, parovoZZ сказал:

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
parovoZZ    1
6 минут назад, BARS_ сказал:

И как это делать без прерываний?

Я где-то писал, что это надо делать без прерываний? Вопрос был про флаги.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
BARS_    882
1 час назад, parovoZZ сказал:

Что мешает точно также опросить аппаратный флаг?

Например то, что в одном прерывании можно выставлять разные флаги. Есть, к примеру, таймер. Тикает пусть раз в 100мс. Прописываем ему счетчики, которые будут досчитывать в разное время. Пусть будет 500мс, 1с, 5с. По счетчикам выставляем флаги, которые будут мониториться в главном цикле и по которым будут выполняться операции некритичные к времени. Или если вернуться к UART, пусть МК принимает большой пакет данных, например от GPS приемника в NMEA формате. Затем он их парсит для получения требуемых параметров. Алгоритм приема будет примерно такой:

  1. Упали в прерывание
  2. Приняли байт
  3. Положили в буфер
  4. Обнулили счетчик времени
  5. Пнули таймер
  6. вышли из прерывания

В конце концов пакет закончится и будет иметь размер байт 100. Таймер дотикает, выставит программный флаг о готовности пакета и вырубится. Как только МК освободится, он увидит флаг и займется парсингом пакета. при этом все другие прерывания останутся активными. А вот если кинуться парсить пакет сразу в прерывании таймера, то прерывания будут заблокированы до конца парсинга (не все, только более с более низким приоритетом). 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

да о чем речь) может быть ситуация когда флаг не нужен, может быть когда нужен) может быть когда флага вообще нет)

моет быть когда в схеме нет мк :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
parovoZZ    1
3 минуты назад, BARS_ сказал:

Есть, к примеру, таймер. Тикает пусть раз в 100мс. Прописываем ему счетчики, которые будут досчитывать в разное время. Пусть будет 500мс, 1с, 5с.

У счетчика же есть цифровые компараторы? Или есть МК, в которых их нет? К черту такой МК. Выставляем значение, которое нам нужно и всё. А дальше хоть флаг компаратора опрашивай, хоть в прерывание уходи. Зачем усложнять себе жизнь?

Вот у меня работает АЦП, а также есть PCINT прерывание. Когда я ничего не делаю, я либо в IDLE, либо ADC_NOISE. Вот тут мне без доп флагов никак, т.к. обработчики прерываний совершенно пустые. А без них никак - тупо по флангам МК не просыпается. Для флага я использую регистр GPIOR.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
BARS_    882
43 минуты назад, parovoZZ сказал:

У счетчика же есть цифровые компараторы?

При чем тут компараторы (и не компаратор, а регистр сравнения)? Один таймер будет формировать только один клок, а с помощью флагов я могу получить с него хоть десяток. Смысл мне тупо для формирования временных интервалов крутить десяток таймеров?

Изменено пользователем BARS_

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
parovoZZ    1
26 минут назад, BARS_ сказал:

и не компаратор, а регистр сравнения

Output Compare Units, как гласит даташит для младших AVR.

26 минут назад, BARS_ сказал:

крутить десяток таймеров?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
BARS_    882
2 минуты назад, parovoZZ сказал:

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

Менять регистр сравнения таймера не вариант. Все клоки должны идти все время.  И 100мс, и 500мс и любые другие.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
parovoZZ    1
16 минут назад, BARS_ сказал:

Все клоки должны идти все время.  И 100мс, и 500мс и любые другие.

Тогда Attiny 861 в помощь =)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    520
57 минут назад, BARS_ сказал:

пусть МК принимает большой пакет данных, например от GPS приемника в NMEA формате. Затем он их парсит для получения требуемых параметров. Алгоритм приема будет примерно такой:

Для маломерок типа AVR ваш алгоритм в чистом виде не подойдет. GPS выпихивает слишком много данных, чтобы их все принять в буфер, а потом парсить. Великоват буфер будет, а ОЗУ мало. В конкретном случае с NMEA надо алгоритм модфицировать: в прерывании ждать начала того пакета, который нужен, и затем принимать в буфер уже только его - так буфер будет короче во много раз. Но  это нюансы, конечно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
BARS_    882

При чем тут тини вообще? Речь идет про любой МК. Таймеры работают +/- одинаково везде, по крайней мере базовые функции. Речь про то, что один таймер может выставлять флаги для десятка событий. Например:

  • Каждые 100 мс опрос кнопок
  • Каждые 200 мс обновление дисплея, если есть соответствующие данные
  • Каждые 500 мс мигать светодиодом (или толпой светодиодов)
  • Каждую 1с отсылать данные по тому же ЛАН
  • и т.д. и т.п.

Задействовать под каждое событие отдельный таймер как минимум нерационально, поэтому ставятся программные флаги и все. А таймер просто вываливается в прерывание каждые 100 мс и все.

4 минуты назад, ARV сказал:

Для маломерок типа AVR ваш алгоритм в чистом виде не подойдет

Верно, но с ними я уже давно завял в силу их убогости:crazy: Так да, можно ждать нужный пакет, но это не сильно удобно, т.к. начала пакетов очень похожи и проверку заголовка надо делать по 3-4 символам, следующим друг за другом. А на STM я спокойно могу принять пакет размером хоть 1024 байт без ущерба для ОЗУ. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alexeyslav    643
10 часов назад, DrobyshevAlex сказал:

Разве в прерывании аппаратный не сбросится? ну точнее после прерывания?

Смотря о чем вы говорите. Флаг переполнения - НЕ СБРОСИТСЯ, но выставленный этим флагом флаг прерывания - он СБРОСИТСЯ при входе в обработчик прерывания, при этом флаг переполнения не будет тронут.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1 час назад, Alexeyslav сказал:

флаг прерывания

естественно о нем, речь же была о том зачем ставить свой флаг по прерыванию если есть аппаратный флаг прерывания)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alexeyslav    643

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
parovoZZ    1
В 21.01.2019 в 19:51, ARV сказал:

// правильный подход - минимальное ожидание uint8_t spi(uint8_t d){ while(!(SPSR & (1<<UDRE)); uint8_t res = UDR; UDR = d; return res; }

Вот здесь косячокс - если в регистре ничего нет, то и работать не будет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    520

Нет никакого косячка: кода UDR пуст, бит UDRE всегда установлен.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
parovoZZ    1

На32u4 на этой проверке все и застряло почему-то. Пока разбираться некогда.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
parovoZZ    1
В 10.02.2019 в 09:41, ARV сказал:

Нет никакого косячка: кода UDR пуст, бит UDRE всегда установлен.

Что-то я тупанул. Это же речь про UART/ А тема вроде про SPI.

Ну раз такие дела, то придется UART в качестве SPI погонять)

Изменено пользователем parovoZZ

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    520

С SPI то же самое. Вероятно, тупанул и я, назвав не тот регистр и флаг, но все идентично. Правда, с точностью до наоборот: если есть флаг - пусто, и можно писать.

	for(uint8_t i=0; i < CNT; i++){
		while(bit_is_clear(SPSR, SPIF));
		SPDR = *data++; 
	}

Вот таким кодом 100 лет пользуюсь - как видите, ждем флаг SPIF, и как встал - пихаем :) Прям по жизни все.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ваша публикация должна быть проверена модератором

Гость
Вы не авторизованы. Если у вас есть аккаунт, пожалуйста, войдите.
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Восстановить форматирование

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

Загрузка...

  • Похожие публикации

    • Автор: parovoZZ
      AREF  - внутренний ИОН 1.1в
      Вот такой код снятия результатов:
      temp = ADC; if (ADCH & (1<<ADCH1)) // Если значение отрицательное { temp |= 0xFC00; temp = (~temp) + 1; } Value_current_lsb = (uint8_t)(temp >> 2); Никак не пойму - на выбранные дифф. входы надо подать 85 мВ, чтобы АЦП выдал 0. Но это могу списать на внутренний ОУ в виде УГ. Если подаю  -1,1 в - то получаю 127.  Здесь все верно. Но при подаче положительного смещения те же 127 получаю уже при 0,72в. Что за ерунда? Неужели ОУ на столько УГ? Либо же где-то теряется разряд?
    • Автор: parovoZZ
      Ну, собственно, сабж. Питание - от 2.4 и до 3.6. На сигнальном выводе необходима половина напряжения питания (по постоянке, разумеется).
    • Автор: parovoZZ
      Не секрет, что адресация глобальных переменных прямая, а переменных в стеке - косвенная. Стек в AVR программный, то бишь откусывается от ОЗУ. Так вот вопрос - при передаче в функцию (и обратно) больших объемов данных (которые невозможно передать через РОН) все же что будет производительнее - через глобальные переменные или через параметры? Понятно, что в функцию вида
      uint8_t My_super_function (uint8_t data); переменные уйдут через РОН,  а вот в такую
      void My_super_function (uint8_t *data, uint8_t *ret); через стек? Так может ну его нафик, стек этот?
    • Автор: parovoZZ
      Поставил LUFA, следом абсолютно не нужный мне ASF. Но в упор не понимаю - как создать проект на базе этой библиотеки из студии? Приходится вручную копировать папку с заголовочниками LUFA, прописывать пути в makefile, лишние телодвижения по добавлению папки в свойства проекта. Если я это делаю всё вручную, то тогда для чего это расширение? Примеры я могу и так покрутить. ЗЫ - не слишком высокий скилл в юзании Atmel Studio/
  • Сообщения

    • Здравствуйте! В разделе Ардуино не нашел подходящей темы,  да в принципе и не совсем по ардуино вопрос. Ниже приведена часть схемы прозвонки, которая может показывать как  напряжение, так и сопротивление. Измерение напряжение происходит посредством делителя, сопротивления-знаем напряжение стабилизатора и сопротивление прецизионного резистора, и через падение напряжения Ардуино вычисляет сопротивление участка. А теперь проблема, коммутация входов происходит через реле, которое управляется кнопкой. Программно была поставлена блокировка, чтоб реле не срабатывало если есть напряжение, но увы это не помогло. Спасет ли схему от случайного попадания напряжения  (~220-380В) если я поставлю диод VD2 (чтоб защитить источник стабилизированного напряжения) и VD4 (чтоб не спалить ардуино). По сути вход ардуино высокоомный и простой стабилитрон должен выдержать.
    • Заменил, поставил новые с магазина. Да еще не сказал плоттер включается, переходит по меню и сохраняет настройки.
    • Гораздо проще применить уже готовое решение не подключая дисплея например. Я, по своей неопытности, готовые исходники с atmega8 на atmega328p примерно 2 месяца переводил. А Вы хотите, что бы кто-то взялся за неизвестный ему МК под который пишется неизвестно на чём.
    • А куда верхний полигон силовой земли потеряли? Или плата трехслойная? Если нет, то плата в принципе нерабочая.
    • Существует формула для расчёта теплового сопротивления теплоотвода:
      Q=(T2-T1)/P-Q1-Q2, где
      Т2 - максимальная температура кристалла транзистора по справочнику,
      Т1 - максимально допустимая температура в коробке с нашим устройством, 
      P - рассеиваемая на транзисторе мощность,
      Q1 - тепловое сопротивление кристалл-корпус по справочнику, 
      Q2 - тепловое сопротивление корпус-радиатор. Освежите память.