Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Software UART
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > MCS51
lancode
Подскажите, как реализовать программный UART порт на Si8051f320
Я беру вот этот пример с сайта:
https://www.silabs.com/Support%20Documents/...lDocs/an115.pdf
https://www.silabs.com/Support%20Documents/...are/an115sw.zip

в комментариях этого примера написано что он будет работать с C8051F00x и C8051F01x
поправил что смог под свой МК, компилирую, получаю ошибки на этих строках:
EIE2 |= 0x20; // Enable IE7.
PRT1IF |= 0x80; // Trigger IE7.
PRT1IF &= ~(0x80); // Clear IE7 interrupt flag
PRT1IF |= 0x80; // interrupt to service.

Хорошо, иду читать документацию, в datasheet написано что у данного МК нету такого прерывания (IE7), точнее оно есть, но нигде не используется. Думаю, меняю что-то, правлю исходиник... в общем, запутался.

Итак, задача, реализовать программный UART (или адаптировать этот семпл с сайта, для Si8051f320).
Притом реализовать хотя бы только чтение (RX) скорость 9600.
Возможно потом понадобится реализовать и TX
Помогите, пожалуйста, разобраться.
Kolia
А не проще ли воспользоваться аппаратным UART
lancode
Нет, не проще.
Мне нужно 4 порта UART.
Sofware UART - хорошее решение.
Вообще, я на форуме cygnal.org видел несколько подобных тем, но проблема так и не была решена.
Думаю, что если кто-то поможет разобраться с программным UART - эти исходники будут полезны многим.
barabek
Цитата(lancode @ Oct 19 2008, 22:01) *
Подскажите, как реализовать программный UART порт на Si8051f320
Я беру вот этот пример с сайта:
...


Не всегда хватает хардверных UARTов smile.gif.
Не поятно для какой конкретной цели Вы реализуете. Извините, не хочется разбираться с апнотом. Поэтому поделюсь своим. Использовал его для приема сигнала с приемника GPS. Там посылки NMEA, заканчиваются 0x0d 0x0A. Поэтому конец посылки легко выхватывается. Нужно что-то другое - адаптируете или спросите. Вариантов много - можно использовать PCA, можно разбить прием битов и обработку байтов на отдельные прерывания.
PS. Прога изначально была написана для 410, если где-то накосячил при переделке в инициализации, заранее извините.
c8051
Цитата(lancode @ Oct 20 2008, 17:15) *
Мне нужно 4 порта UART.
Sofware UART - хорошее решение.

Когда-то делал 8 портов, но пример брал от Atmel

C8051Fxxx - сильно отличаются инициализацией, а также внутр. генератором:
C8051Fxxx = 24,5 МГц, кроме
C8051F32x = 12
C8051F34x = 24

М.б. лучше взять 2 hard uart ( F34x) + аппаратное переключение ?
barabek
Пока писал первое сообщение, да еще с моим затупочным инетом, пропустил требование 4 uart. Предлагаю еще один старый вариант. Он рабочий, но писал его давно, а пришлось переделывать под другой контроллер (с 410 под Ваш 320), посему возможны ошибки. Приведен пример для одного Rx, но по аналогии легко адаптировать под 3 софтверных UART. Еще, в 410 входы компаратора на мультеплексоре можно выставить NONE, в 320 нет. Я думаю, это не должно мешать, т.к. сам компаратор не включен.
lancode
barabek Спасибо большое, попробовал твои примеры. Вроде работает. Конечно придется дописать и поправить под себя.

Задача немного изменилась. Скорость приема вместо 9600 стала 115200.
Взял этот же пример, поставил скорость. Запустил, не работает.
Можно ли, и если можно, то как сделать, чтоб этот же пример работал на скорости 115200 ?

Цитата
М.б. лучше взять 2 hard uart ( F34x) + аппаратное переключение ?

Это как? Что такое аппаратное переключение? Что будет если данные передаются одновременно по обоим портам?
c8051
Цитата(lancode @ Oct 27 2008, 10:04) *
Что такое аппаратное переключение? Что будет если данные передаются одновременно по обоим портам?

Активными двунаправленными будут 2 hard uart (большая скорость) для выбранных клиентов.
Остальные могут только передавать запросы (они идут на прерывания)
или работать на низкой скорости(soft uart)
Когда ф340 решит сделать активными(быстрыми) новую пару, то соответственно "старые" клиенты должны перейти перейти на медленный(soft) или ожидание очереди
barabek
насчет 115200 не проверял. Сейчас к сожалению нет времени этим заняться. Но 24е+6/115200=208, т.е. всего 208 тактов между прерываниями на биты, если работает только один порт на прием. А так как 4 порта - как-то интуитивно маловато времени smile.gif . На передачу конечно проще, можно разные порты синхронизировать.
barabek
не могу старое сообщение отредактировать. Вот что я подумал. Прикинул грубо: функция "PCA_inter" из второго примера по листингу полностью занимает 91 байт. С учетом того что не все команды однотактовые, но не все выполняются из-за ветвлений, то впринципе можно постараться выжать требуемую скорость. Только, конечно же, перенастроить частоту PCA на частоту SYSCLK, а не на перегрузку таймера T0 как было. В обработку байтов (по фиктивному прерыванию компаратора) сделать как можно короче, только запись в массив памяти. Обработку оставить на main. Может вообще обработку байтов (запись в массив) перенести в прерывание по PCA.
Но биться стоит, если транзакции происходят относительно редко. Иначе только в прерываниях засядите и на обработку времени не останется.
lancode
barabek
Беру твой пример soft_rx.
На скорости 9600 - все работает нормально.
Повышаю скорость до 115200.
На этой скорости появляются такие ошибки:
Код
передаю алфавит:
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
принимаю:
"bcddfghijklmnopqrstuvwxy{abcdefghijklmnopqrstuvwxyz"
Обратите внимание на 4 символ и на символ "{"


Эта ошибка "плавает", каждый раз получается разный результат.
Логично предположить что происходит небольшой сдвиг, из-за рассинхронизации скорости приема и передачи.
Смотрим в код и видим:
Код
#define SYSCLOCK 12000000
#define BOUDRATE 115200
#define HALFBITTIME  256-SYSCLOCK/48/BOUDRATE/2
#define BITTIME      256-SYSCLOCK/48/BOUDRATE

Здесь возникает ошибка округления
BITTIME = 154 вместо 253,8

Я попробовал увеличить частоту таймера с SYSCLOCK/48 до SYSCLOCK/4.
но видимо что-то сделал неправильно, сдвиг стал только больше. например вместо буквы "a" стал получать букву "и". Подскажите как можно обойти эту ошибку округления. maniac.gif
barabek
Цитата(lancode @ Nov 3 2008, 06:15) *
...
Здесь возникает ошибка округления
BITTIME = 154 вместо 253,8

Я попробовал увеличить частоту таймера с SYSCLOCK/48 до SYSCLOCK/4.
но видимо что-то сделал неправильно, сдвиг стал только больше. например вместо буквы "a" стал получать букву "и". Подскажите как можно обойти эту ошибку округления. maniac.gif


Странная ошибка округления! Надеюсь Вы правильно все настройки для таймера и осцилятора сделали.
Лучше, конечно, взять не 256-SYSCLOCK/48/BOUDRATE, а 256-SYSCLOCK/BOUDRATE, т.к. дискретность на один бит получается больше. При 12 МГц клоке на бит получаем SYSCLOCK/BOUDRATE=104 клока. Рекомендую и частоту взять не 12, а 24 МГц с умножителя. Вообще частоту и предделитель лучше выбирать такими, чтобы количество клоков на бит было максимальным, не превышающим 256. Приоритеты желательно для обоих прерываний выставить высшими, и, сответственно, using 2.
Еще рекомендация. Если у есть нормальный осцил добавь глобальную переменную типа sbit centertoggle=Px^y; на любой свободный пин и в функции T0_RX_SoftWare сразу после объявления переменных добавить перещелкивание этой переменной centertoggle=!centertoggle;. Тогда на двухлучевом осциле можно по фронтам этого сигнала посмотреть, где же происходит обработка битов на самом деле.
Если все же не будет получаться, я попробую проверить. У меня, кажется, на работе есть кит 320. Правда, если появится "окно" на работе на этой или следущей неделе smile.gif. Если это нужно, уточните, может все же на PCA сделать? Все-таки сразу 3 Rx получаем.
lancode
Поднял частоту таймера с SYSCLOCK/48 до SYSCLOCK
Поставил оба прерывания с высшем приоритетом.
Включил - не работает. Экспериментальным путем добился того, что наибольшее сходство данных которые передаются на МК, с теми, которые фактически приняты, получается при
HALFBITTIME 256-(SYSCLOCK/BOUDRATE/2-X)
при значениях X = 6, 7. При изменении количества команд в функции T0_RX_SoftWare - также приходится подстраивать число X.
Однако полного отсутствия ошибок добиться так и не получилось. Наверное это связано с разным количеством команд при обработке стартового бита и/или бита данных.
(данные передаю не посимвольно, а сразу строкой символов по 300.)

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

Цитата
Если все же не будет получаться, я попробую проверить. У меня, кажется, на работе есть кит 320. Правда, если появится "окно" на работе на этой или следущей неделе . Если это нужно, уточните, может все же на PCA сделать? Все-таки сразу 3 Rx получаем.

Сделать наверное действительно лучше на PCA. Но я делал на таймере, потому что с PCA пока не разобрался. Подумал, что на таймере будет легче заставить пример работать, а потом уже перейти на PCA.
barabek
Вот, как и обещал, сделал, только предыдущий вариант полностью переделал. Правда не знаю, как у Вас отличаются посылки друг от друга, поэтому сделал, что посылка заканчивается переводом строки '\n', как у модемов. Но это не главное, под себя переделаете. В коде добавлены два пина служебных. Один, как я и советовал, перещелкивается при заходе в прерывание, второй пин устанавливается при заходе в прерывание и сбрасывается при выходе. Можно было и только вторым пином обойтись, но так понаглядней. Их нужно будет удалить, что бы не отнимали время. Сигналы на софтверном пине RX0 (P0.0), а также на обоих вспомогательных представлены на прилагаемой осцилограмме (они подписаны). Как видно из рисунка на прерывание всреднем уходит порядка 2,5 мкс. Посему, в принципе, 3 одновременных приема должно получиться, в натяжечку. А если еще пооптимизировать, да на ASMе... Сам проверил только один одновременный прием, не захотел на ките с лишними допайками возиться. А штатно установлен только 1 преобразователь 232 в TTL. Поэтому проверку оставляю Вам smile.gif. О результате сообщите, пожалуйста, вдруг самому придется на таких скоростях работать.

P.S. В папке имеются лишние файлы, а отредактировать не получается. На самом деле в проекте используются только 4 файла: "init.c","interrupts.c","main.c","values.c". Коменты от старых файлов остались на русском, новые по настоятельной рекомендации здешних гуру попытался на импортном писать smile.gif. Такая вот каша.
lancode
barabek Огромное спасибо за пример. Вот как только появилось немного времени - сел разобраться с ним. Скачал, запустил, работает.
Прием для 1 канала работает отлично. Все данные без ошибок.
Попробовал перекинуть провод по которому передаются данные с P1.0 на P1.1 или P1.2 - чтоб проверить прием по другим каналам PCA. Сразу не пошло. Просто не вызывается прерывание PCA_inter. Решил что глюк где-то в инициализации PCA. С ходу, в общем, не разобрался.
Сейчас буду отлаживать, тестировать. Если что новенькое появится - напишу сюда. smile.gif

Еще раз говорю огромное спасибо за помощь, хочу также научиться программировать микропоцессоры, как Вы smile.gif
Комментарии что на Русском, что на Английском читаются у меня отлично. Проблем с кодировкой нет.
p.s. Классный у Вас осциллограф smile.gif
barabek
Цитата(lancode @ Nov 13 2008, 01:24) *
Попробовал перекинуть провод по которому передаются данные с P1.0 на P1.1 или P1.2 - чтоб проверить прием по другим каналам PCA. Сразу не пошло. Просто не вызывается прерывание PCA_inter. p.s. Классный у Вас осциллограф smile.gif


В майне забыл запустить 1 и 2 PCA - модули (PCA0CPM0=PCACPMfalledge; - запуск 0-го модуля, аналогично сделать для 1 и 2).
А осцил самому нравится smile.gif. И куплен на халяву - что нравится вдвойне smile.gif
lancode
Ага. Инициализация была пропущена. Я не заметил blush.gif
Сейчас результы работы UART такие:
Тестировал прием данных на порты по-отдельности:
Порт P1.0 и P1.1 принимают данные без ошибок.
Порт P1.2 - не получается правильно принять данные. Прерывание вызывается, обрабатывается, но что-то работает неверно - байты искажаются.
Соединил перемычкой P1.0 и P1.1. Хотел таким образом протестировать одновременный прием данных по обоим линиям.
На P1.0 все в порядке, а на P1.1 - неверные данные.
Пока нет возможности протестировать одновременный прием разных данных на все порты, но потом я это сделаю.
Перещелкивание пинов, которое использовалось для отладки на осцилографе я удалил. Больше не знаю как можно оптимизировать по скорости.
Подозреваю что прием работает неправильно из-за вот этих настроек:
sfr16 PCA0CP0=0xfb;
sfr16 PCA0CP1=0xe9;
sfr16 PCA0CP2=0xeb;

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

ps. Можно ли принимать данные на разных скоростях? Например на одном порту 115200, на другом - 9600, а на третьем - 19200. Пока мне это не нужно делать, просто интересная идея возникла. smile.gif
barabek
Цитата(lancode @ Nov 21 2008, 00:23) *
Ага. Инициализация была пропущена. Я не заметил blush.gif
Сейчас результы работы UART такие:
Тестировал прием данных на порты по-отдельности:
Порт P1.0 и P1.1 принимают данные без ошибок.
Порт P1.2 - не получается правильно принять данные. Прерывание вызывается, обрабатывается, но что-то работает неверно - байты искажаются.

Нашел ошибку при копировании, необходимо исправить:
Код
     {
     SBUF2sr_temp>>=1;
     SBUF2sr_tempMSB=Rx2sft_pin;
     switch(RX0_state)//здесь ошибка!!! должно быть RX2_state

Цитата
Соединил перемычкой P1.0 и P1.1. Хотел таким образом протестировать одновременный прием данных по обоим линиям.
На P1.0 все в порядке, а на P1.1 - неверные данные.
Пока нет возможности протестировать одновременный прием разных данных на все порты, но потом я это сделаю.
Перещелкивание пинов, которое использовалось для отладки на осцилографе я удалил. Больше не знаю как можно оптимизировать по скорости.

Так я и знал smile.gif. После того как запостил, подумал-подумал и вот что приходит на ум. Если на каждую обработку бита уходит по 2.5 мкс, а длительность бита около 8 мкс, то при одновременном приеме приемник №1 (и тем более №2) обновляют свои счетчики (PCA0CPх+=HALFBITTIME;)на это время позднее (для №2 это вообще больше 5мкс). Поэтому эти процедуры нужно как-то вынести в самое начало обработчика прерывания, однако это увеличит длительность обработки. Стоит ли это делать, все равно в некоторых ситуациях при ПОЧТИ одновременном приеме возможна задержка обработки в максимуме почти на это-же время и, соответственно, срыв синхронизации. Улучшить ситуацию можно (кажется так и сделано в апноте), если не считывать стартовый бит, а после фронта старта отсчитывать 1,5 длительности бита до первого бита данных. Тогда максимально узкое место по времени будет 8мкс - длительность 1 бита, а не 4мкс - длительность 0,5 бита. Чуть ухудшится помехозащищенность, но она и так никакая, так что ничего страшного smile.gif. Вобщем, как-то мне страшновато стало 3 приемника, 2 я думаю, можно потянуть, был бы камень побыстрей, тогда...
А вот замкнуть два входа приемников я не догадался smile.gif, а сейчас кит использован, не начем погонять 05.gif
Цитата
Подозреваю что прием работает неправильно из-за вот этих настроек:
sfr16 PCA0CP0=0xfb;
sfr16 PCA0CP1=0xe9;
sfr16 PCA0CP2=0xeb;

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

Это не задержки, это адреса модулей, чтобы с ними можно было общаться как с 16битным числом, подробнее почитайте в "Cx51 Compiler" (у меня файл называется "c51.pdf") - возможно он есть и у Вас на компе. Поставляется вместе с кейлом, либо в нете легко найти. Только обратите внимание, что они хранятся не в том порядке байтов, как обычный "int", но это так, на будущее.
Цитата
ps. Можно ли принимать данные на разных скоростях? Например на одном порту 115200, на другом - 9600, а на третьем - 19200. Пока мне это не нужно делать, просто интересная идея возникла. smile.gif

конечно разные скорости возможны. Для этого вводить не одно определение #define BITTIME (SYSCLK/BAUDRATE), а соответствующие. Главное, чтобы не получилось больше 65536, Т.е. в нашем случае минимальный бодрейт получается 366 бит/с. Если переделать, что на старте отсчитывать 1,5 бита, получим 549.
lancode
Ошибку поправил. Теперь работают все 3 порта.

Цитата
а сейчас кит использован, не начем погонять

Вы распаиваете схему прямо там, на макетной плате кита?
Я просто взял шлейф от floppy дисковода и подключаю через него разные макетные платы. Так можно отлаживать разные проекты одновременно. Не знаю насчет помехозащищенности, но проблем пока не возникало. smile.gif

В принципе, моя задача решена. У меня редко будет одновременный прием данных на таких скоростях. А если часть данных побъется, то это не страшно.

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

p.s. Если Вы все-таки реализуете одновременный прием на разных портах, то мнтересно бы было потестить этот исходиник smile.gif Это так, если будет интерес и время свободное. smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.