Обсуждаем контроллеры компании Atmel.
Ответить

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 00:04:44

зачем вешать дополнительно детали если с этим один МК может справиться
А затем, что
Время срабатывания по идее от 1,5 до 2 микросекунд
. Программа может просто пропустить подобные импульсы.

Это какую же микруху ИЛИ надо на 20 и более датчиков?
А кто сказал что микруху ? :)

Что хоть за датчики такие и где они стоЯт ? Вы с них напрямую в МК сигнал заводите ?

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 00:11:44

Допустим, сработало прерывание по схеме "или", в прерывании опрашиваем порты с датчиками, для 20 датчиков трёх портов достаточно, чтобы их подключить, делаем цикл (5 может хватит), в цикле опрашиваем порты примерно так:
Код:
...
A=0; B=0; C=0;

 for (i=0; i!=5; i++)
  {
    A=A|PINA; B=B|PINB; C=C|PINC;
  }
...

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

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 00:17:59

Аlex писал(а):
Это какую же микруху ИЛИ надо на 20 и более датчиков?
А кто сказал что микруху ? :)

Действительно, зачем микруху, для "ИЛИ" можно просто диоды навешать.

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 00:31:40

Что хоть за датчики такие и где они стоЯт

УЗ микрофон немного переделанные. Если грубо то пьезодатчики. Время срабатывания можно подрегулировать, но это критичный момент.
На МК заводятся через транзюк дабы немного усилить амплитуду.
Программа может просто пропустить подобные импульсы.

Дык потому МК и работает на 8МГц чтобы успеть поймать.
а приемник пусть сам разбирается какой бит в каком порту за какой датчик отвечает

Я не умею программировать на ПК вообще. Да и для МК крайне не очень... :)
Кто ж софт-то писать будет? Нынче у нас капитализьм...
Действительно, зачем микруху, для "ИЛИ" можно просто диоды навешать.

Про диоды я чего-то не сообразил :oops:
Все-равно места нет в корпусе. Да и интересней же програмно проблему решить. Мне - как начинающему контроллерщику.

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 00:43:40

Кстати, (извините за офтопик): Везде пишут, что для UART надо МК от кварца заводить. Я от внутреннего RC завел - работает исправно, крокозябры не шлет. Пробовал от 15 до 30 градусов гонять - норм. Странно... Частота же должна была уплыть...

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 00:50:40

DerMeister писал(а):Я не умею программировать на ПК вообще. Да и для МК крайне не очень... :)
Кто ж софт-то писать будет? Нынче у нас капитализьм...

Тогда, перед отправкой, нужно будет определить по включенным битам портов соответствующие им символы и отправлять как символ в ASCII коде.

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 00:59:25

Кстати сказать при частоте 8МГц и баудрейте 115200, например, отправка занимает примерно 0,1 мсек, для работы с USART-ом ставь лучше внешний кварц, в даташите написано какой лучше и почему.
Какой проц будет стоять?

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 01:07:18

Дык потому МК и работает на 8МГц чтобы успеть поймать.
Дело не в частоте, а в свободном процессорном времени для других операций, кроме опроса входов. Вы пока опрашиваете один вход, на другом может проскочить импульс и программа просто его не отловит. Для этого и существуют события по внешним прерываниям.
Вы хотите и :hunger: и чтоб "костей не осталось" :) Так не бывает...

Частота же должна была уплыть...
Ну дык она же не в 2 раза уплывает :) Но лучше поставить, дабы избежать потом проблем. Или хотя бы предусмотреть для него место на плате.

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 01:14:53

Тогда, перед отправкой, нужно будет определить по включенным битам портов соответствующие им символы и отправлять как символ в ASCII коде.

Так в принципе суть получается та же, что я описывал с переменными для каждого датчика. Только с экономией портов за счет ИЛИ.
Или я по своей неопытности (глупости?) не понимаю чего-то...?
Это всего лишь моя третья программа в жизни :roll: Причем раньше я ни один язык программирования в глаза не видел...
отправка занимает примерно 0,1 мсек

А приведение UART к готовности: очистка буфера, флаг. И дальше проверка условия сработал ли датчик... Это же все такты...
А скорость у меня 9600. Нет кварца чтоб на 115200 подошел.
Для этого и существуют события по внешним прерываниям.

То есть Вы настаиваете, что без внешних ИЛИ и внешних прерываний с этой бедой не справиться?
Вы хотите и и чтоб было всё "безболезненно"... Так не бывает.

Безусловно вы правы, а жаль....
Ну дык она же не в 2 раза уплывает

Просто в интернете жутко пугают RCшкой, мол крокозябры сплошные идут... Вот я и удивился...

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 01:23:38

То есть Вы настаиваете, что без внешних ИЛИ и внешних прерываний с этой бедой не справиться?
Боюсь, что с такими короткими импульсами от датчиков - нет :(

Только с экономией портов за счет ИЛИ.
С ИЛИ порты не экономятся, а реализуется один источник прерывания для всех датчиков. В любом случае, по мимо схемы с ИЛИ, Вам нужно будет заводить сигналы от каждого датчика на порты, если Вы хотите знать какой датчик сработал. Ито, если программа успеет выйти на обработчик до того, как импульс закончится.
Лучше вешать датчики на целиковый порт(ы) сразу, чтобы его (их) разом прочитать, а потом уже работать с прочитанным результатом. А не читать по отдельным битам.

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 04:16:04

Вроде бы уже долгие годы выпускают МК с тучей внешних прерываний и DMA. Зачем себе наживать гемморой непонятно.

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 05:13:17

То есть Вы настаиваете, что без внешних ИЛИ и внешних прерываний с этой бедой не справиться?


У вас всё равно там места нет, а так, можно ещё одновибраторов поставить 20-ть штук. :) А вообще, как же вы угадаете момент, когда датчики срабатывают пакетно? Либо внешнее прерывание, либо в цикле опроса крутитесь и как только что-то сработало, тут же опрашивайте датчики и потом передавайте. Но только 2 мкс на импульс пропустить будет очень просто. Так что, прерывание - ваш выбор. Только в обработчике, наверное, тоже не успеете все датчики опросить - у вас будет тактов 20 на всё, хотя считать 3 порта и проверить на срабатывание вы успеете.

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 09:28:31

Люди, да о чём это вы все!? :)
8МГц это 8 тактов за одну микросекунду, 12 за полторы. Вход в обработчик прерывания это минимум 7 тактов (плюс накладные расходы). Опрашивать три порта, да если писать на Си - никак не получиться. Только частоту поднимать и на ассемблере - тогда можно попробовать уложиться. И, думается мне, что со вложенными прерываниями при отправке по UART-у придётся делать.

А с отправкой данных на скорости 9600 при событиях раз в 10 миллисекунд. 1/9600=0,0001041667 == 0,1042 миллисекунды -> 1 байт за 1,042 миллисекунды, если совсем без пауз (теоретически) -> 20 байт не влезут по времени. А вот отправлять три байта, как тут было предложено, вполне получиться.

Учтите, что данные по UART-у будут с задержкой приходить: задержка из-за способа передачи + задержка в API на стороне компа. Это может быть намного больше 10 миллисекунд.

Есть ATmega48/88/168, у которых есть три Pin Change Interrupt. Но в виду временных характеристик импульсов - не получиться.

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 09:36:08

DerMeister писал(а):То есть Вы настаиваете, что без внешних ИЛИ и внешних прерываний с этой бедой не справиться?
Всё зависит от...
Коту утром (после ночи) полагается пожрать и спать, поэтому разевающаяся в зевке пасть не даёт толком прочесть тему.
Поэтому попробую свести в одну кучу всё, что я понял.
  • Есть толпа датчиков, которые срабатывают «кучно». Максимальная протяжённость кучи между первым и последним импульсом, в приницпе, ивестна и она меньше 10-милисекундного периода пачек.
  • Датчики могут сработать вообще «одновременно».
  • Каждый датчик в сработавшем состоянии находится 1.5-2мкс.
  • Используется AVR
  • Выбрана тактовая 8 МГц.


У многих AVR есть pin change interrupt -- вот оно и «или», лишь бы хватило ножек, поддерживающих PCINT. У меги48 их 23, но UART украдёт кое-что.
Но.

3 такта подсинхронизация входов в системе pin change interrupt.
1…4 такта завершение предыдущей команды (ну хорошо, 1…3, если без MUL и обращения к EEPROM, 1…2 если без вызовов подпрограмм)
3 такта собственно «вызов» прерывания
2 такта rjmp из векторов на обработчик
Итого 9…12 -- это ещё без сохранения регистров (а на С уж без этого никак).

На 8 МГц имеем 8*(1.5…2) = 12…16 тактов за время нахождения датчика в сработавшем состоянии… Туго… Первый датчик может быть пропущен.
Дальше, как уже писали, можно не выходя из прерывания просто в цикле делать ИЛИ портов и собирать всё до достижения времени, когда уже все должны были закончить (как тут viewtopic.php?p=1366934#p1366934)

Варианты
  1. Написать прпрывание на асме.
  2. Поднять тактовую, всё отладить, потом думать, нужно ли снижать.
  3. Обойтись без прерываний.


Пункт 3
Прерывания PCINT в PCICR запрещаем, но нужные ножки в PCMSK разрешаем.
Вот мы знаем, что должна прийти пачка импульсов.
Зачитываем все порты (чтобы проинициализировать триггера сравнения системы PCINT). Сбрасываем флаги в PCIFR.
Зануляем буферные переменные, куда будем «наиливать» состояние портов.
Инициализируем защитный таймер (который остановит нашу работу, когда уже все импульсы должны были прийти) или счётчик циклов «наиливания», рассчитанный из времени выполнения команд цикла и максимальной длительности пачки
В цикле читаем PCIFR до пока он не станет не равным 0.
От этого момента в цикле собираем по ИЛИ маски сработавших датчиков.
Всё должно успеть, если аккуратно.

А в конце просто посылаем эти три маски.
Например, текстом в 16-ричном коде с переводом строки, это 7…8 байт (CR…CR/LF)

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 09:42:25

Импульсы слишком коротки, можно легко пропустить. Схемы с ИЛИ, а также применение МК с кучей входов способных дернуть прерывание тож сомнительно. Ибо в любом случае надо будет опрашивать порт.
Может удлинить импульсы? Скажем до 1мс, и их уже ловить? Но это внешняя обвязка уже

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 09:59:28

Если импульсы действительно не меньше 1.5 мкс (12 тактов @ 8 MHz), то первый импульс (если он на «дальнем», по положению в цикле, порте) таки может быть пропущен из-за ожидания начала пачки (до 6 тактов в цикле while(PCIFR==0) ). Без ожидания возникает вопрос, как ограничить время сбора.
Поднятие тактовой до одной из моих любимых частот 14.7456 спасает ситуацию безусловно.

Код:
include <avr/io.h>

uint8_t pb, pc, pd;

void collect(uint16_t max_cycles)
{
        // Проинициализировали систему выделения перепадов чтением портов
        // Раз уж ждём 1-чек на сработке, то до сработок там нули,
        // так что заодно и проинициализировали нулями интересующие нас биты.
        // А что в не-интересующих, так и не важно
        uint8_t tb = PORTB, tc = PORTC, td = PORTD;

        PCIFR = 0x03; // сбросили флаги

        while (PCIFR == 0) ;

        do {
                tb |= PORTB;
                tc |= PORTC;
                td |= PORTD;
        } while (--max_cycles);

        // Маски интересующих битов всё равно хранятся в PCMSK,
        // пусть эта функция и берёт их оттуда.
        pb = tb & PCMSK0;
        pc = tc & PCMSK1;
        pd = td & PCMSK2;
}

avr-gcc -mmcu=atmega48 -O2 -S
Код:
collect:
        in r20,37-32
        in r19,40-32
        in r18,43-32
        ldi r21,lo8(3)
        out 59-32,r21
.L2:
        in r21,59-32    ; while (PCIFR == 0) ;
        tst r21
        breq .L2
.L4:     ; do {
        in r21,37-32    ; 1
        or r20,r21      ; 1
        in r21,40-32    ; 1
        or r19,r21      ; 1
        in r21,43-32    ; 1
        or r18,r21      ; 1
        sbiw r24,1      ; 2
        brne .L4        ; 2 вместе 10 тактов, сам цикл вписывается в 12
         ; } while (--max_cycles);

        lds r24,107
        and r24,r20
        sts pb,r24
        lds r24,108
        and r24,r19
        sts pc,r24
        lds r24,109
        and r24,r18
        sts pd,r24
        ret

Кстати, если бы в цикле сначала сделать in, in, in трёх портов в три регистра, и только потом or, or, or, то и первый импульс не пропал бы. Но уже аж такое объяснить С-компилятору врядли выйдет. Так что или асм, или поднять тактовую.
Последний раз редактировалось avreal Пт авг 10, 2012 10:18:53, всего редактировалось 2 раз(а).

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 10:01:14

BCluster писал(а):Импульсы слишком коротки, можно легко пропустить. Схемы с ИЛИ, а также применение МК с кучей входов способных дернуть прерывание тож сомнительно. Ибо в любом случае надо будет опрашивать порт.
Может удлинить импульсы? Скажем до 1мс, и их уже ловить? Но это внешняя обвязка уже

Там итак уже места не хватает :dont_know: .

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 11:32:13

Вообще, такие задачи нужно решать "в лоб", без всякого гемора. Если импульс короткий, значит его нужно тупо удлинить, хотя бы раз в 10. Ибо без удлинения задачу не решить. Т.к. любой из датчиков может сработать с небольшой задержкой и его просто-напросто можно пропустить. А ведь есль может случиться бяка, она обязательно случиться. Надеяться на авось не стОит.
Думаю, что для маленькой ёмкости около каждого транзистора найдётся место.

Re: Как на С "приплюсовать" два символа?

Пт авг 10, 2012 16:09:54

Отдельно отвечать не буду, попробую всем сразу. Потому что:
Мда...
Честно говоря не ожидал, что все так сложно получится...
Согласен, что событие по внешнему прерыванию спасут ситуацию. Но в данном случае у меня нет возможности вешать "1000000" диодов, пусть даже и SMDшных - не влезут. А переделывать все заново я не хочу, боюсь потеряю интерес и все. У меня такое бывает.
А я уверен что програмно можно сделать ВСЕ, ну или почти все. Вон люди такие загогулины в программах выполняют, дивишься порой.
Согласен с avreal - asm бы сдесь был как нельзя кстати. Может даже и необходим. Но, к сожалению, я его не знаю и учить пока никак не собираюсь. Он в моем далеком детстве оставил глубокую психотравму в моей душе :)
Согласен с Alex - надо наверно пробовать увеличивать длительность импульса. Впринципе микросекунд до 10-15 можно попробовать. Тогда все мои дурные вопросы сами собой и отвалятся.
Ладно, господа Коты, думаю нужно начать заниматься делом, а то так можно демагогировать весьма долго, а проблема так и останется стоять, как у молодого. Тем более, что благодаря вам, я впринципе знаю в какие стороны надо пробовать тыкаться.
Эхх..... жаль, что я так поздно начал заниматься МК... Это так круто!
Ладно, буду запускать свой CVAVR да тяжеленькой музычки немного.....
Спасибо вам великое! Вы мне очень помогли. Я даже вроде как и умнее стал что ли.... :oops:

Re: Как на С "приплюсовать" два символа?

Сб авг 11, 2012 12:06:21

Мда... И что вы думаете?
Увеличил я значится время срабатывания датчиков. Уж на сколько не знаю. Только и так не эдак, и эдак не так. Теперь МК на одно срабатывание мне шлет по 15-20 символов. То биш одно срабатывание он успевает ловить кучу раз за раз.
За что боролись, на то и напоролись....
Ответить