Историята по-долу се разви преди доста време, но скоро ми се наложи да си я припомня. Реших, да си запиша нещата тук, пък може и на някой друг да свърши работа.
Напоследък серийните портове взеха напълно да изчезват от компютрите – осбено от преносимите. Дори и моят, който не е първа младост няма такъв (сигурно и защото е евтин модел).
RS232 интерфейсът може да е бавен, с обемист конектор и да работи на малки разстояния, но той има и едно предимство – изклютително прост е. Ако се занимавате с разни малки контролери ще знаете, че той е в порядъци по-удобен, достъпен, евтин и прост за реализация от USB или ETHERNET например.
И така, за да се сдобия с тази незаменима екстра се запътих към близкия магазин за конвертор от USB към сериен порт. Взех си и компютъра, защото за мен е важно чудото да работи под Линукс, а обикновено по опаковките това не го рекламират много. Преди да го купя включих USB конверторът и ядрото веднага го разпозна и се появи нов сериен порт. Купих го.
За съжаление радостта ми беше кратка, защото след като се прибрах установих, че въпросният конвертор не може да си комуникира с никакво серийно устройство – макар, че се разпознава. Може да е бил дефектен моя, но по-сокоро предположението ми е, че има проблеми с драйвера – cypres_m8. След това съм пробвал с други конвертори с чипове на FTDI и Prolific 2303 и при тях нямаше такъв проблем със серийната комуникация. Въпреки това при ситуации в които използвате серийния порт не съвсем по предназначение, а примерно превключвате контролните линии много бързо (bit banging) за да говорите някакъв друг протокол тези конвертори може и да не работят.
В крайна сметка реших да си взема „истински“ RS232 под формата на PCMCIA карта. След търсене с Гугъл попаднах на блога на Данчо, където той беше обявил за продажба точно такава карта поради несъвместимост с неговия компютър. Видяхме се. Пъхнах картата в моя компютър – ядрото я разпозна веднага – взех я.
Прибрах се. Първата ми работа беше да тествам новата придобивка – отново нищо! Никаква комуникация, нито с мобилния ми телефон, нито със стар външен модем, който успях да изровя.
Самата платка получих в картонена кутия, на която имаше йероглифи и единствено се разбираше, че пристига от Хонг Конг. Имаше и диск с драйвери – само за Унидоус. Всички отличителни белези по картата се свеждаха до надпис „BBL PCMCIA RS-232 CARD“. Търсенето за информация по тези ключови думи не даде полезен резултат.
Решен да не се предавам толкова лесно направих следния експеримент. Стартирах minicom и настроих порта на скорост 9600 бита в секунда. Пуснах да се изпраща файл съдържащ единствено буквата „а“. След това закачих изходящата линия (TX) към осцилоскоп и видях следното:
Ура! Картата все пак работи и дори предава данни. Единствената малка подробност е, че ги предава доста по-бързо от колкото се очаква. На картинката по-горе осцилоскопът е настроен на 50 микросекуни за деление по оста Х. Грубо в едно деление се предават 3 бита, значи скоростта е над 62500 бита/секунда – доста над очакваните 9600.
След още малко търсене, проблемът напълно се изясни. Основният компомент осигуряващ серийната връзка e чип от вида UART (Universal Asynchronous Receiver-Transmitter). По-конкретно в моята платка има 16c950. Ядрото го разпознава правилно и драйверът успешно си говори с него. Скоростта обаче се определя чрез делене на тактовата честота получена от външен кварцов резонатор. Оказва се, че няма начин драйверът да разбере каква е честотата на този резонатор. До преди време най-масово се е използвал резонатор с честота 1.8432 MHz, която разделена на 16 дава базова скорост от 115200 бита/сек. Това е записано и в кода на драйвера като стойност по подразбиране.
В момента често се използват резонатори с по-високи честоти за да се постигнат по-големи скорости. Имайки предвид, че при мен получената скорост е около 7-8 пъти по-голяма от очакваната и стандартните стойности дадени в спецификацията на чипа установих, че в моята платка резонаторър най-вероятно е с честота 14.7456MHz, което разделено на 16 дава базова скорост от 921600 бита/сек. За щастие има лесен начин тази скорост да бъде указана с помощта на програмата setserial:
setserial /dev/ttyS0 baud_base 921600
Повтарям теста с осцилоскопа и този път резултатът е доста обнадеждаващ:
Предаването на един бит отнема малко над 2 деления или 100 микросекунди. При зададена скорост от 9600 това е точно колкото се очаква – 1/9600=0,000104167 сек или около 104 микросекунди.
Комуникацията с мобилния телефон, стария външен модем и всичко друго което закача вече работи!
Остана само да добявя едно udev правило, за да не пиша горната команда всеки път когато пъхам картата. Аз си създадох нов файл – /etc/udev/rules.d/10-serial.rules и в него добавих само един ред:
KERNEL=="ttyS0", RUN+="/bin/setserial /dev/ttyS0 baud_base 921600"
Вече всички инструменти са на лице и мога да се заема с работата по проекта за монтаж на вентилатор в банята :).
Да се избере 8 пъти по-ниска интерфейсна скорост от терминалния емулатор. Само 110, 150, 300, 600 остават неизползваеми, но все пак сме 21 век.
Да, това също е възможен вариант, но малко по-неудобен – всеки път трябва да делиш наум скоростта и да пресмяташ новата стойност. Аз освен терминалния емулатор ползвам и разни други софтуери, които комуникират по серийния порт и си ползват някаква скорост по подразбиране, и така не трябва всеки път да указвам друга. В крайна сметка един ред в конфигурационен файл не е кой знае колко сложно.
То интересното беше, докато разбера какъв е проблема. Вече като знам може да се заобиколи или реши сравнително лесно.
просто не винаги има осцилоскоп- т.е. до диагностиката на проблема можеше да се стигне и без осцилоскоп или break-box.
🙂
радо, радвам се, че все пак pcmcia-то, което размених за usb-то ти върши някаква работа. четейки първите редове ми стана неудобно, че съм ти дал нищо за нещо (о: хе-хе. добре, че си спец :>
9600bps(baud_per_second) това ти е баунда т.е (1 01010101 0) затова ти излиза повече от очакваната скорост 😉