Полная версия этой страницы:
Soft UART
west329_
Apr 30 2008, 06:01
Пока у меня ничего не выходит, дабы не опозориться не буду всё подробно расписывать, написал только часть TX. Проект работает стабильно только на 9600.
Хочу услышать мнения тех кто уже сталкивался с подобным.
Возможно ли написать такой софт на С.
Знаю точно, что есть, правда на ПИК контроллере рабочий проект. Там кварц на 8 Mhz. и скорость не 115200 а 57ххх но сам факт что реализация получилась, настораживает, что иду по тому пути.
Работаю на меге16.
Требуется кроме встроенного ещё 2 дополнительных UART, вот и выдумываю.
64 такта на приём 1 бита... для одиночного канала реально, в принципе, но вот остальной программе всё это будет сильно мешать, по этой же причине два канала уже не получится, скорее всего. Я бы поставил внешний сдвоенный UART или перешел на мегу640 (4 аппаратных UART).
west329_
Apr 30 2008, 06:34
Я вот про это тоже начал подумывать, с одним ещё совладаю а вот 2 как ни прощитывал ничего не выходит.
И хочу добавить ещё это как я понимаю всё на АСМЕ, а у меня тут весь проект на С, и еще 2 прерывания по таймеру висят, при отладке такие кони полезли

Насчет перехода согласен, благодарен за подсказку недумал что такие меги есть, но пока такой возможность не придвидется в ближайшее время.
Может испльзовать кварц на 20Mhz ???
MrYuran
Apr 30 2008, 07:02
вполне реально, понадобится 1 прерывание от ноги и 1 - от таймера
соотношение частот =64 - вообще идеальный вариант
(в том смысле что не дробный и достаточно большой)
Не настораживает, что по даташиту максимум 16 МГц и то при питании 5 В.
В свое время мы AVR разгоняли конечно, но при этом стандартная периферия вела себя скажем мягко - не адекватно, а Вам нужно использовать UART блоки, так что врядли.
viakon
Apr 30 2008, 07:21
Бестолку выдумывать. 32 команды на один уарт возможно только если больше программа ничего делать не будет. Это то тебя я так понимаю не устраивает. имею реальный проект на С мега128, два програмных уарта на 9600 и 19200, помимо аппаратных. Нормально работает.
Цитата
Требуется кроме встроенного ещё 2 дополнительных UART, вот и выдумываю.
Ну я бы делал так - во первых, перешел на Mega162, там 2 усарта. Теперь надо решить проблему с третьим. Для приема я бы делал так - заводил RXD на какой-нибудь INT по спаду, в прерывании через полбита проверял, старт это или нет и дальше запускал бы SPI, у которого MISO тоже подключен на RXD и предделитель настроен на 1/64 - по прерыванию от SPI имеем байт данных, можно задержаться на бит и проверить стоповый, если уж очень надо. Затем процесс повторяется. Надо только посмотреть, когда точно запускать SPI и какой режим выбрать, чтобы семплы попадали в середину битов.
Про передачу можете додумать сами

Кстати, хорошим способом будет использование не INT, а ICP - тогда можно будет по содержимому таймера точно определить место запуска SPI, независимо от времени реакции на прерывание - это актуально для быстрого обмена и наличия других прерываний. Кстати, похоже, что без вложенных прерываний Вам не обойтись.
mdmitry
Apr 30 2008, 08:22
В ATmega640/1280/2560 4 USART
west329_
Apr 30 2008, 08:49
С данной ситуации готов пожертвовать работой основной программы и всеми сторонними прерывания, прийдется выключить.
Нащёт увеличения частоты неподумал, наверно 20мг перебор будет.
Я тут прикинул может коммутатор на выходе УАРТ порта поставить, какой-то CD4052. еслы не разберусь с софтом
MrYuran
Apr 30 2008, 09:05
Цитата(west329_ @ Apr 30 2008, 11:49)

С данной ситуации готов пожертвовать работой основной программы и всеми сторонними прерывания, прийдется выключить.
Нащёт увеличения частоты неподумал, наверно 20мг перебор будет.
Я тут прикинул может коммутатор на выходе УАРТ порта поставить, какой-то CD4052. еслы не разберусь с софтом
Если только передавать надо, тем более не во все сразу, то я вообще никаких проблем не вижу.
Кстати, у АВР есть возможность привязывать выходы регистров-защёлок таймера к ногам?
(как к примеру у МСП430)
Цитата
Кстати, у АВР есть возможность привязывать выходы регистров-защёлок таймера к ногам?(как к примеру у МСП430)
Это Вы про Output Compare? Ну выходы есть, а к произвольным ногам - к сожалению нельзя...
west329_
Apr 30 2008, 09:39
Цитата(MrYuran @ Apr 30 2008, 13:05)

Если только передавать надо, тем более не во все сразу, то я вообще никаких проблем не вижу.
Кстати, у АВР есть возможность привязывать выходы регистров-защёлок таймера к ногам?
(как к примеру у МСП430)
не моглиб вы обьяснить поподробнее
MrYuran
Apr 30 2008, 10:01
Цитата(west329_ @ Apr 30 2008, 12:39)

не моглиб вы обьяснить поподробнее
очень просто.
берёте выход защёлки.
выставляете там стартовый бит (0)
засекаете на таймере битовый интервал.(именно на этой защёлке)
определяете режим выхода (1/0), соответствующий следующему биту.
когда таймер досчитает до конца бита, он сразу выставит на ногу нужный уровень (1/0), а у вас будет время (64 такта) чтобы в прерывании от таймера выставить следующий интервал и режим вывода, соответствующий следующему биту.
И так 10 раз. (для одного байта)
_4afc_
Apr 30 2008, 10:29
Цитата(west329_ @ Apr 30 2008, 10:01)

Пока у меня ничего не выходит, дабы не опозориться не буду всё подробно расписывать, написал только часть TX. Проект работает стабильно только на 9600.
Хочу услышать мнения тех кто уже сталкивался с подобным.
Возможно ли написать такой софт на С.
Работаю на меге16.
Ну TX можно и 8 аппаратных сделать ( на один порт).
Для 8xRX я бы делал синхронное считывание порта с частотой 250кГц и разбирал бы уже полученные данные. Лучше конечно на асме - тогда зная сколько тактов занимают команды можно обрабатывать два считывания на 125кГц или 3 на 85кГц и т.д. Таймер лучше заводить один раз иначе нахватаете джитера.
На С наверно можно написать, просто придётся каждый билд тестить с нуля.
На асме есть ещё одно преимущество - можно разделить регистры так, что используемые в прерывании не будут использоваться в основной программе.
Работаю на меге48.
Artem_Petrik
Apr 30 2008, 19:47
Недавно читал статью Иосифа Каршенбойма "Квадрига Аполлона и микропроцессоры". Там как раз про такой случай написано. Идея в том, что нужно меньше извращаться, а брать либо проц с достаточным количеством УАРТов, либо просто подобрать самый дешовый проц с УАРТом и наставить их столько, сколько надо УАРТов. Соединить их в кучу скажем по SPI, и наслаждаться многоядерностью

. А с программными UART масштабиремость будет совсем плохой, особенно учитывая, что уже сейчас есть обоснованные опасения, что ресурсов может не хватить. А если потом захочется что-то добавить?
Конечно если устройство предполагается производить десятками тысяч, то имеет смысл побороться за удешевление, если же нет, то нужно просто сравнить цену mega640 и, скажем, mega162+mega48, выбрать что дешевле, и забыть о прграммных интерфейсах.
Это мое ИМХО.
SasaVitebsk
Apr 30 2008, 22:21
В общем-то соглашусь с предыдущим автором. С учётом цен на МК особо нет смысла усложнять и удлинять процедуру разработки/отладки.
Есть единственное отклонение из этого правила - массовость. В смысле как минимум сотни тысяч штук. Иными словами если удорожание разработки приведёт к удешевлению конечного изделия и разница в стоимости * на объём выпуска даст существенный экономический выигрыш (при достаточной надёжности работы изделия) - то тогда - оправдано.
На мой вгляд если рассматривать только обработку USART исключая другие задачи, то эта задача выполнимая, но повозится придётся. Но существует ещё кварц 11059920 и 14745600 (18432000 уже за пределами). Скажем на кварце 14745600 исходя из формулы F/115200/2 = 64 такта на выборку/128 на бит - вполне реально обработать 8 каналов непрерывно передающих информацию.
Цитата(SasaVitebsk @ Apr 30 2008, 21:21)

Скажем на кварце 14745600 исходя из формулы F/115200/2 = 64 такта на выборку/128 на бит - вполне реально обработать 8 каналов непрерывно передающих информацию
Ну, за 64 такта можно и 24 канала на передачу залудить, а как на приём?
SasaVitebsk
May 1 2008, 18:18
Я имел ввиду приём/передачу. Хотя конечно 2 выборки на бит и маловато. 8 каналов, естественно исходя из порт на вывод и порт на ввод.

Я думаю вы понимаете о чём я.
Конечно при таком подходе рост затрат от числа каналов будет незначительным, но всётаки будет, в связи с тем, что придётся распихивать данные по каналам (буферам).
defunct
May 1 2008, 18:43
Цитата(SasaVitebsk @ May 1 2008, 20:18)

Я имел ввиду приём/передачу. Хотя конечно 2 выборки на бит и маловато. 8 каналов, естественно исходя из порт на вывод и порт на ввод.

Я думаю вы понимаете о чём я.
На устойчивый прием надо хотя бы 3 выборки на бит, еще лучше 5. Если рассматривать 3 выборки и кварц 16Mhz - получим 46 тактов на выборку. Теоретически подъемно, и погрешность будет меньше чем те же 3 выборки с кварцем 14.7456Mhz.
Про то, что на "C" можно реализовать - можно забыть сразу, на "C" прием/передачу 115200 поднять нельзя..
SasaVitebsk
May 1 2008, 20:30
Цитата(defunct @ May 1 2008, 22:43)

На устойчивый прием надо хотя бы 3 выборки на бит, еще лучше 5. Если рассматривать 3 выборки и кварц 16Mhz - получим 46 тактов на выборку. Теоретически подъемно, и погрешность будет меньше чем те же 3 выборки с кварцем 14.7456Mhz.
Про то, что на "C" можно реализовать - можно забыть сразу, на "C" прием/передачу 115200 поднять нельзя..
Про 3 выборки - согласен. Про "С" - скажем так - хлопотно. Собственно то же самое можно сказать и про ASM.

Всётаки приходится признать, что это изврат.
defunct
May 1 2008, 20:34
Цитата(SasaVitebsk @ May 1 2008, 22:30)

Про "С" - скажем так - хлопотно.
Это будет уже не C ;>
west329_
Sep 22 2008, 10:26
Вернусь опять к поднятому вопросу по поводу SOFT UARTA.
Ситуация следующая, в основном всё заработало, линию ТХ сделал первую, для начало пришлось как посоветовали на АСМ написать Program Modul, и подключить к основному проекту на С. Скорость вывода решил оставить 57600. Все заработало нормально.
До настоящего времени всё устраивало но потребовалась линия SOFT RX. Восновном решил изначально пойти по тамуже пути, но наткнулся на одну проблему.
При приёме байта информации в HARD реализции UARTA, у меня вызывается прерывание, в котором, (хоть и не желательно так делать) выполняются некоторые действия над принятым байтом, собственно перевожу их ASCII в HEX по таблице. Ничего серьезного НО, SOFT UARTA в той реализации которую я сделал не оставляет совсем свободного времени для работы программы перевода между входящими байта.
Хотелось бы для этих целей задействовать часть свободной аппаратуры контроллера, прерывание таймера или внешние прерывания, чтоб дать поработать контроллеру.
Возможно уже кто-то сталкивался с подомными ситуациями ?
SasaVitebsk
Sep 22 2008, 12:33
Честно говоря - не совсем понял проблемы. Более точно её опишите.
Если вы вызываете софтовое прерывание одно на 8 прерываний приёма (я так понял) и оно вам мешает, то разрешите в нём прерывание. Соответственно оно размажется на 2-3 прерывания от бита и всё. Только за переменными следите.
west329_
Sep 22 2008, 12:55
Цитата(SasaVitebsk @ Sep 22 2008, 15:33)

Честно говоря - не совсем понял проблемы. Более точно её опишите.
Если вы вызываете софтовое прерывание одно на 8 прерываний приёма (я так понял) и оно вам мешает, то разрешите в нём прерывание. Соответственно оно размажется на 2-3 прерывания от бита и всё. Только за переменными следите.
Принимаем только с одного устройства.
Получается так, чтоб принять пакет данных, около 150байт, между приёмами байт входящие байты обрабатываются, это для аппаратного юарта. А софтовый не позволяет так сделать так как после приёма одного байта мне сразу надо прыгать в процедуру приёма следующего байта, чтоб его не пропустить.
Хотелось както уйти от неприрывного опроса ноги а перекинуть это дело на таймер или прерывание, или на оба этих средства сразу.
rezident
Sep 22 2008, 16:02
Цитата(west329_ @ Sep 22 2008, 18:55)

Хотелось както уйти от неприрывного опроса ноги а перекинуть это дело на таймер или прерывание, или на оба этих средства сразу.
Посмотрите как это реализуется на таймереА в применении MSP430.
http://focus.ti.com/mcu/docs/mcusupporttec...ctName=slaa078aПару лет назад делал накопитель с IrDA и UART на таймереА MSP430. На скорости 57600 работало при тактовой 7372,8 кГц.
SasaVitebsk
Sep 22 2008, 16:59
Цитата(west329_ @ Sep 22 2008, 15:55)

Хотелось както уйти от неприрывного опроса ноги а перекинуть это дело на таймер или прерывание, или на оба этих средства сразу.
Так тут и обсуждалось таймером!!! Что значит непрерывный???
Обычно делается так.
1) Таймер инициализируется на частоту полинга. Обычно данная частота в 3 раза превышает максим. частоту передачи.
2) Сущ. 2 варианта начала приёма. 1 - по прерыванию фронта (старт бит) запускается таймер, 2 - непрерывный поллинг старт бит определяется по первому нулевому биту.
3) бит мажоритарным методом, либо другим на ваше усмотрение.
4) формируется байт по всем условиям - ST+X...+P.
5) По формированию байта - таже процедура, что и при приёме байта по аппаратному USART. Разницы быть не должно, это позволяет обрабатывать единым образом.
Я бы сделал без формирования прер по фронту с 3 выборками на бит, либо с формированием + 1 выборка на бит. Драйвер закончил стандартным кольцевым буфером.
Я реализовывал на 7372800 115200. Работало очень устойчиво. Правда в этот момент все остальные прерывания были запрещены.
Syberian
Sep 23 2008, 03:25
Можете кидаться тапками, но контроллер ИМХО мог бы заниматься чем-нибудь более полезным...
Берется какая-нибудь ПЛИС с минимумом внешней обвязки и встроенной флеш-памятью. Клепается на ней хоть 30 УАРТов с буферизацией. Связь с контроллером - желательно по параллельной 8бит шине.
Тут и дуплексный throughput порядка 8 МБит@20 MHz будет обеспечен легко, и скалабельность достигается дикая...
Есть вариант еще проще! AT94K10AL-25AJC
Давно мечтал заюзать такую штюкку... AVR+FPGA в одном флаконе! Ценник ок. 300 рублей. Ноль обвязки. На 10к вентилей можно затолкать столько УАРТов, что и не снилось. А AVR ядро доделает все остальное.
west329_
Sep 23 2008, 05:43
Ход мыслей понятен. Вижу реализацию в таком порядке:
1. Ожидаю внешнее прерывание по спаду.
2. Как только происходит EXTint, захожу в прерывание и запускаю таймер TIMERint на длину (бит/2). Отключаю EXTint.
3. По прерыванию TIMERint обновляю время срабатывания на (бит) и считываю подряд 8 байт.
4. Как только считано 8 байт, обновляю время срабатывания TIMERint на (бит + (бит/2)). Физически игнорирую стоб бит , чтоб дать возможность контроллеру обработать принятый байт.
5. По прерыванию TIMERint очищаю флаги. Отключаю TIMERint. Включаю EXTint. Дальше пункт 1.
Цитата
считываю подряд 8 байт.
8 бит
Цитата
Как только считано 8 байт, обновляю время срабатывания TIMERint на (бит + (бит/2))
Нет, все еще на (бит), по девятому прерыванию от таймера проверяете, получили ли 1, если да - значит обрабатываете байт (если видите 0 - значит, ошибка фрейма). В любом случае запрещаете прерывания от таймера и разрешаете EXTInt.
А в остальном - совершенно правильно.
PS Перед разрешением EXTInt не забудьте его сбросить флаг.
west329_
Sep 23 2008, 07:00
Цитата(Rst7 @ Sep 23 2008, 09:44)

8 бит
Нет, все еще на (бит), по девятому прерыванию от таймера проверяете, получили ли 1, если да - значит обрабатываете байт (если видите 0 - значит, ошибка фрейма). В любом случае запрещаете прерывания от таймера и разрешаете EXTInt.
А в остальном - совершенно правильно.
PS Перед разрешением EXTInt не забудьте его сбросить флаг.
Да, там биты, это я поспешил

.
С проверкой стоп бита тоже согласен. А время для обработки принятого байта будет когда будет приниматся следующий байт на прерываниях, не подумал.
SasaVitebsk
Sep 23 2008, 08:07
Да. По 9 - кольцо.
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.