Green-sell.info

Новые технологии
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Программирование сом портов

Программирование сом портов

§ 54. С чего начать? Или получение первых результатов от COM порта

Вот мы и добрались до COM порта. Но с ним все не так просто как с LPT, и его полноценное использование потребует значительно больших усилий. Главной загвоздкой является и его главное преимущество — передача данных в последовательном виде. Если в LPT байт данных передается по 8-ми линиям по биту на каждую, и состояние каждой линии можно было легко посмотреть, то в COM порту байт данных передается бит за битом по одной линии (относительно земли, конечно) и посмотреть что там передается с помощью одних светодиодов не удастся. Для этого нужно специальное устройство — преобразователь потока последовательных данных в парраллельный, т.н. USART (Universal Synchronous/Asynchronous Receiver Transmitter). Например, он есть в составе материнской платы компьютера, снабженного COM портом, в любом более мение серьезном микроконтроллере.

Надеюсь, вы еще пали духом в освоении COM порта. Все не так уж и мрачно. Некоторые результаты можно получить и без USART. Сформулируем задачу, которую реализуем на начальном этапе работы с COM портом:

«Хочу что бы к компьютеру через COM порт подключался светодиод. Запускаю программу. Далаю какое-то действие в этой программе, светодиод загорается, делаю другое — светодиод тухнет.»

Задача довольно специфичная (с учетом того, что USART не используется) и является чистой «самопальщиной», но вполне реализуема и работоспособна. Давайте приступим к ее реализации.

Опять берем системный блок вашего ПК и смотрим в тыловую часть. Примечаем там 9-ти штырьковй разъем — это и есть COM порт. Реально их может быть неколько (до 4-х). На моем ПК установлено два COM порта (см. фото).

2. Удлинитель COM порта

Нам потребуется удлинитель COM порта, но не просто удлинитель, а т.н. нуль-модемный кабель. Как он выглядит? Так как на фото, причем на обох его концах установлен разьем типа «мама». Далее втыкайте его в любой COM порт Вашего ПК и выводите его на рабочее место.

3. Аппаратная часть

С аппаратной частью нам тоже придется «повозиться», в том смысле что она будет сложнее чем с первым устройством для LPT порта. Дело в том что протокол RS-232 по которому идет обмен данными в COM порту, имеет несколько отличное соотношение логическое состояние — напряжение. Если обычно это логический 0 0 В, логическая 1 +5 В, то в RS-232 это соотношение следующее: логический 0 +12 В, логическая 1 -12 В.

И например, получив -12 В не сразу понятно что с этим напряжением делать. Обычно проводят преобразование уровней RS-232 в ТТЛ (0, 5 В). Самый простой вариант — стабилитроны. Но я предлагаю сделать этот преобразователь на специальной микросхеме. Называется она MAX232.

Микросхема эта дешевая и широко распространенная. Особенных проблем в ее добывании возникнуть не должно. Что она умеет? Она одновременно может преобразовывать два сигнала из RS-232 в ТТЛ и еще два из ТТЛ в RS-232.

Теперь давайте посмотрим, а какие сигналы из COM порта мы можем посмотреть на светодиодах? В действительности, в COM порту есть аж 6 независимых линий, представляющих интерес для разработчика устройств сопряжения. Две из них пока для нас недоступны — линии по передаче последовательных данных. А вот оставшиеся 4 предназначены для управления и индикации процесса передачи данных и мы сможем «передалать» их под свои нужды. Две из них предназначены для управления со стороны внешнего устройства и мы их пока трогать не будем, а вот последние две оставшиеся линии мы сейчас и поиспользуем. Они называются:

  • RTS — Запрос на передачу. Линия взаимодействия, которая показывает, что компьютер готов к приему данных.
  • DTR — Компьютер готов. Линия взаимодействия, которая показывает, что компьютер включен и готов к связи.

Сейчас мы немного передалаем их назначение, и светодиоды, подключенные к ним будут либо тухнуть либо загораться, в зависимости от действий в нашей собственной программе.

Итак, давайте соберем схему, которая позволит нам проводить задуманные действия.

А вот ее практичекая реализация. Я думаю вы меня простите, что я сделал ее в таком стремном макетном варианте, ибо делать плату для такой «высоко продуктивной» схемы не хочется.

4. Программная часть

Тут все попроще. Давайте создадим Windows приложение в Microsoft Visual C++ 6.0 на основе MFC для управления двумя линиями взаимодействия COM порта. Для этого создаем новый проект MFC и указываем ему имя, например, TestCOM. Далее выбираем вариант построения на основе диалога.

Придайте внешний вид окну диалога нашей программы, как на рис. ниже, а именно добавьте четыре кнопки, по две на каждую из линий. Одна из них соответственно необходима для того чтобы «погасить» линию, другая чтобы ее «установить» в еденицу.

Далее, в файле TestCOMDlg.h в описание класса диалога добавьте строчку: HANDLE hFile;.

Чтобы наша программа могла упрявлять линиями COM порта, его надо сначала открыть. Напишем код, ответственный за открытие порта при загрузке программы.

С помощью стандарной функции Win API CreateFile() открываем COM-порт COM2. Далее проверяем успешность открытия с выводом информационного сообщения. Вот тут надо сделать важное замечание: COM2 — это в моем компьютере, а на Вашем компьютере Вы могли подключить его к другому COM порту. Соответственно, его имя нужно изменить на то, кокай порт Вы используете. Посмотреть, какие номера портов присутствуют на Вашем компьютере, можно так: Пуск -> Настройка -> Панель управления -> Система -> Оборудование -> Диспетчер устройств -> Порты (COM и LPT).

В итоге, функция CTestCOMDlg::OnInitDialog(), расположенная в файле TestCOMDlg.cpp, класса нашего диалога должна принять вид:

Теперь добавим обработчики кнопок управления линиями. Я дал им соответствующие имена: функция, которая устанавливает еденицу на линии DTR — OnDTR1(), 0 — OnDTR0(). Для линии RTS соответственно аналогичным образом. Напомню, что обработчик создается при двойном щелчке на кнопке. В итоге, эти четыре функции должны принять вид:

Поясню немного как они работают. Как видно, внитри себя они содержат вызов одной и той же Win API функции EscapeCommFunction() с двумя параметрами. Первый из них — это хэндл (HANDLE) на открытый порт, второй — специальный код действия, соответствующий необходимому состоянию линии.

Все, комилируем, запускаем. Если все хорошо, должны увидеть сообщение об успешном открытии порта. Далее, нажатием соответствующих кнопок мигаем светодиодами, подключенными к COM порту.

Обмен данными через СОМ-порт

Обмен данными по СОМ-порту
Доброго времени суток. Пишу 2 программы, обменивающиеся данными по COM-порту. Одна посылает.

Обмен данными через COM- порт
Добрый день, пытаюсь освоить передачу данных. Отсылаю на мк скажем "1", приходит "1" и "-38".

Обмен данными через COM порт
Нашел исходник программы для работы с com портом. Какие есть стандартные команды, чтобы получить.

Обмен данными через COM-порт
Всем доброго времени суток! Подскажите пожалуйста как передать введенные данные из компонента.

Обмен данными через COM-порт в Windows
Разработчики высокоуровневых языков программирования, очевидно, считают прием/передачу данных по протоколу rs232 через коммуникационный порт экзотической процедурой: мол, рядовому пользователю как бы и без надобности, а нерядовой — разберется самостоятельно. Потому ни в turbo pascal, ни в delphi нет штатных средств обмена данными таким способом. Однако в последнее время, особенно в связи с распространением микропроцессорных устройств, такая задача встает в любительских программах все чаще — в силу простоты и дешевизны реализации последовательным портом оборудованы многие научные и инженерные приборы, разнообразные датчики и измерители.

Простота аппаратного исполнения (для обычной двусторонней связи требуется всего три провода) асинхронного коммуникационного порта ведет, однако, к некоторому усложнению необходимого программного обеспечения. Можно, конечно, попробовать послать байт на устройство com1 средствами dos, подобно тому, как это делается для lpt1 (оно же prn), но успех вряд будет достигнут — как минимум, надо сначала настроить скорость обмена. Потому для dos-программ это делается средствами bios или прямым программированием порта «по железу». А в windows, к счастью, есть соответствующие функции api.

Для организации обмена нужно проделать следующие шаги:

Читать еще:  Виды сред программирования

получить дескриптор порта (handle — указатель, куда посылать все относящееся к порту);
получить адрес dcb — data control block;
установить новые параметры dcb;
послать установленные параметры в порт;
приступить к чтению принимаемых данных или к передаче.
Рассмотрим все по порядку. Получить дескриптор можно с помощью универсальной функции createfile. Так как СОМ — устройство последовательное, то его можно рассматривать как файл, что и делается (и в dos, между прочим, тоже). У этой функции множество применений (описание в help, если распечатать, занимает страниц семь). Для нее требуется масса входных параметров, но большинство из них нам не нужны и приравниваются, в зависимости от типа, либо к 0, либо к величине nil (указатели, которые никуда не указывают). В нашем случае получается следующий синтаксис функции:

createfile (stcom, generic_read+generic_write, 0, nil, open_existing, 0, 0);

Здесь stcom — строка типа pchar, в которой записано имя файла, в данном случае — просто ‘com1’ или ‘com2’, смотря какой порт нужен. Параметр generic_read+generic_write означает, что порт открывается как для вывода, так и для ввода. open_existing означает проверку существования, и если объявленного порта нет, после вызова функции возникнет ошибка, которую можно проанализировать обычным методом delphi: try . except.

Получить адрес dcb можно, если применить функцию getcommstate (pcom, pdcb); здесь pcom — дескриптор порта, pdcb — возвращаемый адрес структуры dcb. Установить параметры порта в этой структуре можно непосредственно, но если вы обратитесь к ее описанию в help, то бессонная ночь вам обеспечена. Поэтому проще сделать это с помощью вызова функции buildcommdcb (stcom, pdcb), в которой stcom в данном случае содержит набор устанавливаемых параметров в виде строки (см. пример ниже). Установленные параметры посылаются в порт с помощью функции setcommstate (pcom, pdcb). Все эти функции возвращают значение типа boolean, которое равно true, если операция прошла успешно. Чтение из порта и запись в порт осуществляются с помощью симметричных функций readfile и writefile, также универсальных и потому содержащих ненужный нам параметр, который мы приравняем к nil:

boolean readfile (pcom, xb, 1, xn, nil);

Здесь xb — переменная любого целого типа, в которой возвращается прочитанное значение (для writefile в ней содержится, наоборот, записываемое), 1 — столько байт прочесть из xb (для СОМ-порта это, очевидно, всегда 1), xn — сколько байт действительно прочитано. Следующий программный фрагмент инициализирует порт СОМ1 и осуществляет прием данных до тех пор, пока не будет нажата любая клавиша на клавиатуре. Принимаемые данные преобразуются в строку и выводятся на экран через пробел в компоненте label1 (с переводом строки через каждые 32 значения; разумеется, можно выводить в любой компонент, имеющий свойство text или caption, или еще куда-нибудь):

stcom:=’com1′;
try
pcom:= createfile (stcom, generic_read+generic_write, 0, nil, open_existing, 0, 0);
except ;
if getcommstate(pcom,pdcb)
then stcom:=’com1: baud=9600 parity=n data=8 stop=1′
else ;
if buildcommdcb(stcom,pdcb) then setcommstate(pcom,pdcb)
else ;
while (msg.message <> wm_keydown) do
begin
bb:=readfile(pcom,xb,1,xn,nil);
if not bb then break;
st:=st+’ ‘+inttostr(xb);
if length(st) mod 32=0
then st:=st+chr(10)+chr(13);
label1.caption:=st;
peekmessage(msg,form1.handle,0, 0,pm_remove); <читаем сообщение из очереди, если есть - удаляем>
application.processmessages; <очищаем очередь сообщений - на всякий случай>
end;

Прежде чем подключать к компьютеру какие-либо устройства, следует сказать пару слов о технике безопасности. Если прибор беспаспортный или, тем более, самодельный, следует проверить следующее: а) напряжение на выходе порта прибора не должно превышать значений +/-15 В (минимум +/-3 В), и на экране осциллографа не должно наблюдаться заметных выбросов и «шпилек», превышающих эти значения, — в противном случае вы рискуете лишиться com-порта (это особенно неприятно, если порт расположен на материнской плате; в сомнительных случаях лучше экспериментировать с дополнительной isa-картой, оборудованной com-портами; б) нужно убедиться, что выход прибора электрически развязан с сетью.

Работа с последовательными портами — работа с COM портами

В настоящее время существует множество устройств, которые обмениваются с компьютером информацией через последовательный порт (COM1, COM2) по протоколу RS-232. Причем такие устройства разрабатывают до сих пор и, я уверен, будут разрабатывать и в дальнейшем. Ведь несмотря на недостатки такой связи: медленная скорость обмена информацией, ограничение на длину соединительных линий — существует и немало достоинств: программная поддержка протокола RS-232 и ему подобных многими периферийными устройствами, специализированными микросхемами, низкая стоимость, минимальное количество соединительных проводов, простота.

Но, как это ни странно, информации по работе с последовательными портами в программах под Win32 очень мало. Материал этой статьи основан на статье Олега Титова Работа с коммуникационными портами (COM и LPT) в программах для Win32 — ознакомиться с ней можно по адресу. Автором очень подробно описаны функции для работы с коммуникационными портами, основное внимание уделено синхронному обмену информацией. Мы же рассмотрим вариант обмена между компьютером и периферийным устройством в асинхронном режиме (как правило, используемом наиболее часто) — причем для простейшего соединения по трем проводам, без использования управляющих сигналов. Таким же образом можно организовать связь между двумя компьютерами (хотя бы для проверки работы своей программы).

Начнем с главного: с последовательными портами в Win32 работают как с файлами. Причем используют только функции API Win32.

Начинается работа с открытия порта как файла, причем для
асинхронного режима ввода-вывода возможен только один вариант:

HANDLE handle = CreateFile(«COM1», GENERIC_READ |
GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,
NULL);

Других вариантов быть не может, поэтому не будем рассматривать
параметры этой функции подробно, единственное, что можно сделать —
это заменить “COM1” на “COM2”. Больше последовательных портов на
компьютере, как правило, нет. При успешном открытии порта функция
возвращает дескриптор handle, с которым и будем работать в
дальнейшем. При неудачном открытии порта функция вернет значение
INVALID_HANDLE_VALUE.

Получив доступ к порту, необходимо его настроить — задать
скорость обмена, формат данных, параметры четности и т. д. Основные
параметры последовательного порта задают структуры DCB и
COMMTIMEOUTS. Структура DCB содержит основные параметры порта и,
кроме этого, довольно много специфических полей.

typedef struct _DCB <

DWORD DCBlength; // sizeof(DCB)

DWORD BaudRate; // current baud rate

DWORD fBinary:1; // binary mode, no EOF check

DWORD fParity:1; // enable parity checking

DWORD fOutxCtsFlow:1; // CTS output flow control

DWORD fOutxDsrFlow:1; // DSR output flow control

DWORD fDtrControl:2; // DTR flow control type

DWORD fDsrSensitivity:1; // DSR sensitivity

DWORD fTXContinueOnXoff:1; // XOFF continues Tx

DWORD fOutX:1; // XON/XOFF out flow control

DWORD fInX:1; // XON/XOFF in flow control

DWORD fErrorChar:1; // enable error replacement

DWORD fNull:1; // enable null stripping

DWORD fRtsControl:2; // RTS flow control

DWORD fAbortOnError:1; // abort reads/writes on error

DWORD fDummy2:17; // reserved

WORD wReserved; // not currently used

WORD XonLim; // transmit XON threshold

WORD XoffLim; // transmit XOFF threshold

BYTE ByteSize; // number of bits/byte, 4-8

BYTE Parity; // 0-4=no,odd,even,mark,space

BYTE StopBits; // 0,1,2 = 1, 1.5, 2

char XonChar; // Tx and Rx XON character

char XoffChar; // Tx and Rx XOFF character

char ErrorChar; // error replacement character

char EofChar; // end of input character

char EvtChar; // received event character

WORD wReserved1; // reserved; do not use

Мы рассмотрим назначение только некоторых основных полей этой
структуры, используемых для нашего случая ввода-вывода, так как
многие поля можно заполнить значениями “по умолчанию”, пользуясь
функцией GetCommState:

Таким образом, нет необходимости вникать во все тонкости
структуры. После этого некоторые поля DCB все же придется заполнить
вручную, а именно:

BaudRate — скорость передачи данных. Возможно указание
следующих констант: CBR_110, CBR_300, CBR_600, CBR_1200, CBR_2400,
CBR_4800, CBR_9600, CBR_14400, CBR_19200, CBR_38400, CBR_56000,
CBR_57600, CBR_115200, CBR_128000, CBR_256000. Можно просто указать
соответствующее число, например 9600, но предпочтительнее все-таки
пользоваться символическими константами.

ByteSize — определяет число информационных бит в
передаваемых и принимаемых байтах. Может принимать значение 4, 5, 6,
7, 8.

Parity — определяет выбор схемы контроля четности. Данное
поле должно содержать одно из следующих значений:


  • EVENPARITY — дополнение до четности;
  • MARKPARITY — бит четности всегда равен 1;
  • NOPARITY — бит четности отсутствует;
  • ODDPARITY — дополнение до нечетности;
  • SPACEPARITY — Бит четности всегда 0.

StopBits — задает количество стоповых бит. Поле может
принимать следующие значения:


  • ONESTOPBIT — один стоповый бит;
  • ONE5STOPBIT — полтора стоповых бита (практически не
    используется);
  • TWOSTOPBIT — два стоповых бита.

После того как все поля структуры DCB заполнены, необходимо
произвести конфигурирование порта, вызвав функцию SetCommState:

В случае успешного завершения функция вернет отличное от нуля
значение, а в случае ошибки — нуль.

Второй обязательной структурой для настройки порта является
структура COMMTIMEOUTS. Она определяет параметры временных задержек
при приеме-передаче. Вот описание этой структуры:

typedef struct _COMMTIMEOUTS <

Поля структуры COMMTIMEOUTS имеют следующие значения:


  • ReadIntervalTimeout — максимальное временной промежуток
    (в миллисекундах), допустимый между двумя считываемыми с
    коммуникационной линии последовательными символами. Во время
    операции чтения временной период начинает отсчитываться с момента
    приема первого символа. Если интервал между двумя
    последовательными символами превысит заданное значение, операция
    чтения завершается и все данные, накопленные в буфере, передаются
    в программу. Нулевое значение данного поля означает, что данный
    тайм-аут не используется.
  • ReadTotalTimeoutMultiplier — задает множитель (в
    миллисекундах), используемый для вычисления общего тайм-аута
    операции чтения. Для каждой операции чтения данное значение
    умножается на количество запрошенных для чтения символов.
  • ReadTotalTimeoutConstant — задает константу (в
    миллисекундах), используемую для вычисления общего тайм-аута
    операции чтения. Для каждой операции чтения данное значение
    плюсуется к результату умножения ReadTotalTimeoutMultiplier на
    количество запрошенных для чтения символов. Нулевое значение полей
    ReadTotalTimeoutMultiplier и ReadTotalTimeoutConstant означает,
    что общий тайм-аут для операции чтения не используется.
  • WriteTotalTimeoutMultiplier — задает множитель (в
    миллисекундах), используемый для вычисления общего тайм-аута
    операции записи. Для каждой операции записи данное значение
    умножается на количество записываемых символов.
  • WriteTotalTimeoutConstant — задает константу (в
    миллисекундах), используемую для вычисления общего тайм-аута
    операции записи. Для каждой операции записи данное значение
    прибавляется к результату умножения WriteTotalTimeoutMultiplier на
    количество записываемых символов. Нулевое значение полей
    WriteTotalTimeoutMultiplier и WriteTotalTimeoutConstant означает,
    что общий тайм-аут для операции записи не используется.

Немного поподробнее о тайм-аутах. Пусть мы считываем из порта 50
символов со скоростью 9 600 бит/с. Если при этом используется 8 бит
на символ, дополнение до четности и один стоповый бит, то на один
символ в физической линии приходится 11 бит (включая стартовый бит).
Значит, 50 символов на скорости 9 600 бит/с будут приниматься

или примерно 57,3 миллисекунды, при условии нулевого интервала
между приемом последовательных символов. Если же интервал между
символами составляет примерно половину времени передачи одного
символа, т. е. 0,5 миллисекунд, то время приема будет

или примерно 82 миллисекунды. Если в процессе чтения прошло более
82 миллисекунд, то мы вправе предположить, что произошла ошибка в
работе внешнего устройства и можем прекратить считывание, тем самым
избежав зависания программы. Это и есть общий тайм-аут операции
чтения. Аналогично существует и общий тайм-аут операции записи.

Формула для вычисления общего тайм-аута операции, например,
чтения, выглядит так:

NumOfChar x ReadTotalTimeoutMultiplier +
ReadTotalTimeoutConstant

где NumOfChar — число символов, запрошенных для операции чтения.

В нашем случае тайм-ауты записи можно не использовать и
установить их равными нулю.

После заполнения структуры COMMTIMEOUTS, необходимо вызвать
функцию установки тайм-аутов:

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

Допустим, вы обмениваетесь с внешним устройством пакетами
информации размером 1024 байта, тогда разумным размером буферов
будет значение 1200. Функция SetupComm интересна тем, что она может
просто принять ваши размеры к сведению, внеся свои коррективы, либо
вообще отвергнуть предложенные вами размеры буферов — в таком случае
эта функция завершится ошибкой.

Приведу пример открытия и конфигурирования последовательного
порта COM1. Для краткости — без определения ошибок. В данном примере
порт открывается для работы со скоростью 9 600 бит/c, используется 1
стоповый бит, бит четности не используется:

handle = CreateFile(«COM1», GENERIC_READ | GENERIC_WRITE,
NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

SetupComm(handle, SizeBuffer, SizeBuffer);

Собираем плату

Значит сделал я такую схемку (да простят меня ардуинщики и физики и вообще…). Короче не будем вдаваться в подробности ее корректности. По крайне мере она работает.

Короче на ней есть два светодиода подключенный к цифровым портам и фоторезистор подключенный к аналоговому порту. Будем писать интерфейс который позволит переключать светодиоды и считывать значения фоторезистора.

Для управления ардуино я буду использовать следующую схему

    Если я отправил символ ‘r’ – значит я хочу чтобы зажегся красный светодиод (англ. r

red)
Если я отправил символ ‘b’ – значит я хочу чтобы зажегся синий светодиод (англ. b

blue)

  • Если я отправил символ ‘p’ – значит я хочу чтобы устройство сообщило мне текущее значение фоторезистора
  • Вот такая у меня получилась программа для ардуино

    Создаем приложение

    И так открываем Qt Creator и создаем новый проект

    выбираем тип приложения

    ну и все собственно

    увидим что-то такое

    чтобы ошибки ушли. Надо один раз запустить приложение. Для этого кликаем на зеленый треугольник (либо жмем Ctrl+R)

    запустится наше интерфейс который пока выглядит вот так:

    Собираем форму

    закрываем его и начинаем править. Для этого переключимся на форму двойным щелчком на mainwindow.ui

    собственно увидим нашу форму:

    Теперь начнем перетаскивать на нее элементы формы. Сначала я хочу чтобы у меня было поле в котором можно ввести порт к которому я буду коннектиться для общения с ардуино.

    Делается это так:

    • Label – это просто метка, не редактируемый текст.
    • LineEdit – поле для редактирования однострочного текста

    Не смотрите что пока все криво, мы в конце добавим немного магии чтобы все выровнять.

    Теперь сделаем две кнопки для включения красного и синего светодиодов

    и еще поле где будем показывать показания с датчика освещённости

    а, ну и еще лог, в который будем писать что отвечает нам ардуинка

    А теперь чуток магии чтобы все это выровнялось

    если немного разъяснить, то тут я объединяю компоненты в горизонтальные группы (чтобы выбрать несколько элементов я удерживаю Ctrl)

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

    Можно запустить (Ctrl+R) и проверить как все работает

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

    меняем его на txtPort

    у остальных полей поменяем потом.

    Добавляем обработчик нажатия на кнопку

    Теперь давайте добавим реакцию на клик кнопки “Включить синий” для этого кликаем на нее правой кнопкой мыши и выбираем “Перейти к слоту”

    в Qt используется так называемый механизм сигналов (signal) и слотов (slot) это расширений C++, которое позволяет связывать событие с реакцией на событие более менее естественный образом.

    В общем открывается такое окно где виден список сигналов которые может послать кнопка. Например когда вы просто нажали на кнопку но еще не отпустили кнопку мышь, генерируется сигнал pressed, а если же вы отпустил мышь то сгенерируется сигнал clicked.

    Короче суть в том что мы к этому сигнал сейчас привяжем функцию (или если мыслить в рамках Qt – слот)

    выбираем clicked и жмем OK:

    нас кидает в редактор кода

    не будем мудрствовать и для начала давайте просто выведем какое-нибудь сообщение, правим функцию

    скорее всего вы увидите что QMessageBox подчеркнуто и выдается ошибка:

    это потому что мы не подключим заголовочный файл с этим классом, ставим курсор на QMessageBox и жмем Alt+Enter

    и видим как вверху добавился необходимый include

    теперь давайте запустим приложение и проверим что кнопка действительно заработала.

    Жмем Ctrl+R и кликаем на кнопку

    Выводим значение из txtPort

    Давайте теперь попробуем сделать так чтобы по нажатию на кнопку выводилось содержимое поля для ввода порта. Подправим функцию:

    Посылаем сообщение arduino

    Для работы с COM портом у QT есть класс QSerialPort, давайте подправим функцию чтобы она отправил символ “b” в порт и тем самым зажгла светодиод:

    он опять будет ругаться на QSerialPort (ставьте курсор на него, жмите Alt+Enter, выбирайте #include , ну либо руками сами добавляйте)

    Пробуем запустить. Жмем Ctrl+R

    И видим кучу ошибок:

    дело в том что QSerialPort специализированная библиотечка и чтобы ее начать использовать надо попросить QT использовать ее dll файл.

    Как это сделать. Для этого есть документация!) В ней указано что надо прописать класс заработал.

    У QtCreator встроенная документация по Qt, так что ставим курсор на QSerialPort и жмем F1

    собственно тут видно какой заголовочный файл (Header) достаточно указать, и еще что-то про qmake

    qmake – это такой себе компилятор QT, который делает из QT C++ кода обычный C++ код, его поведение настраивается в *.pro файле

    Кликаем в левом меню Редактор

    далее выбираем GuiController.pro – собственно pro файл, ну или проще говоря project файл

    в самом верху в нем строчка:

    добавим к ней снизу

    пробуем запустить снова (Ctrl+R)

    уже по крайней мере запустилось!) Попробуем нажать на кнопку

    Ну да мы ведь порт не указали, так что логично

    Пробуем зажечь светодиод

    Собираем и подключаем нашу ардуинку. Заливаем на нее программу, за одно проверяем какой порт использовать

    запускаем нашу программу, вводим порт COM3 и смотрим:

    Давайте теперь добавим то что вернет arduino в ответ на зажжение светодиода, как мы помним там у нас есть:

    а в нашем обработчике мы в холостую читаем данные:

    попробуем сохранить результат в какую-нибудь переменную и вывести ее в наше большое поле для текста.

    Только сначала дадим ему осознанное имя. Переключаемся на mainwindow.ui

    теперь идем обратно в mainwindow.cpp и правим on_pushButton_clicked:

    у нас в программе никаких “Blue is on” так что можно с чистой совестью заявить что это отправило нам ардуино.

    Правим красную кнопку

    По аналогии с синей кнопкой добавим обработчик на красную.

    запускаем и проверяем:

    в общем показывать что диоды у меня действительно переключаются мне чего-то лень, но вот сообщения по крайне мере точно приходят с ардуино =)

    Читаем значения датчика освещености

    Дадим осознаное имя поля для значения фоторезистора

    И добавим обработчик кнопке обновить:

    и пишем код (по сути копипастим с правкой в двух местах):

    Обновляем значения датчика освещённости в режиме реального времени

    Тыкать все время на кнопку обновить не очень интересно. Лучше, чтобы это делалось на автомате. При чем не именно кликанье на кнопку, а просто команда запроса значения и вывода его на форму. Допустим раз в секунду или чаще.

    Для этого есть возможность добавить таймер, ему можно указать вызывать некоторую функцию с каким-то промежутком.

    Делается это так. В конструкторе добавляем таймер

    Теперь как только мы укажем правильный порт, начнут приходить значения:

    Вот собственно и все!

    БОНУС

    Писать порт все время лениво. Есть возможность получить список всех доступных портов. Делается это так.

    Сначала идем на mainwindow.ui и удаляем txtPort, на место него ставим Combo Box

    правим ему свойства

    • objectName меняем на cmbPort
    • кликаем дважды на sizePolicy и в свойстве Горизонтальная политика ставим Expanding, чтобы этот комбо бокс как и lineEdit занимал все свободное место

    возвращаемся к коду mainwindow.cpp и в конструкторе добавляем:

    Прикольно, что прям сразу подключается! Такие дела =)

    Arduino. Работа с COM-портом

    Для связи микроконтроллера с компьютером чаще всего применяют COM-порт. В этой статье мы покажем, как передать команды управления из компьютера и передать данные с контроллера.

    Подготовка к работе

    Большинство микроконтроллеров обладают множеством портов ввода-вывода. Для связи с ПК наиболее пригоден из них протокол UART. Это протокол последовательной асинхронной передачи данных. Для его преобразования в интерфейс USB на плате есть конвертор USB-RS232 – FT232RL.
    Для выполнения примеров их этой статьи вам будет достаточно только Arduino-совместимая плата. Мы используем EduBoard. Убедитесь, что на вашей плате установлен светодиод, подключенный к 13му выводу и есть кнопка для перезагрузки.

    Таблица ASCII

    Для примера загрузим на плату код, выводящий таблицу ASCII. ASCII представляет собой кодировку для представления десятичных цифр, латинского и национального алфавитов, знаков препинания и управляющих символов.

    Переменная symbol хранит код символа. Таблица начинается со значения 33 и заканчивается на 126, поэтому изначально переменной symbol присваивается значение 33.
    Для запуска работа порта UART служит функция Serial.begin(). Единственный ее параметр – это скорость. О скорости необходимо договариваться на передающей и приемной стороне заранее, так как протокол передачи асинхронный. В рассматриваемом примере скорость 9600бит/с.
    Для записи значения в порт используются три функции:

    1. Serial.write() – записывает в порт данные в двоичном виде.
    2. Serial.print() может иметь много значений, но все они служат для вывода информации в удобной для человека форме. Например, если информация, указанная как параметр для передачи, выделена кавычками – терминальная программа выведет ее без изменения. Если вы хотите вывести какое-либо значение в определенной системе исчисления, то необходимо добавить служебное слово: BIN-двоичная, OCT – восьмеричная, DEC – десятичная, HEX – шестнадцатеричная. Например, Serial.print(25,HEX).
    3. Serial.println() делает то же, что и Serial.print(), но еще переводит строку после вывода информации.

    Для проверки работы программы необходимо, чтобы на компьютере была терминальная программа, принимающая данные из COM-порта. В Arduino IDE уже встроена такая. Для ее вызова выберите в меню Сервис->Монитор порта. Окно этой утилиты очень просто:

    Теперь нажмите кнопку перезагрузки. МК перезагрузится и выведет таблицу ASCII:

    Обратите внимание на вот эту часть кода:

    Она останавливает выполнение программы. Если вы ее исключите – таблица будет выводиться бесконечно.
    Для закрепления полученных знаний попробуйте написать бесконечный цикл, который будет раз в секунду отправлять в последовательный порт ваше имя. В вывод добавьте номера шагов и не забудьте переводить строку после имени.

    Отправка команд с ПК

    Прежде чем этим заниматься, необходимо получить представление относительного того, как работает COM-порт.
    В первую очередь весь обмен происходит через буфер памяти. То есть когда вы отправляете что-то с ПК устройству, данные помещаются в некоторый специальный раздел памяти. Как только устройство готово – оно вычитывает данные из буфера. Проверить состояние буфера позволяет функция Serial.avaliable(). Эта функция возвращает количество байт в буфере. Чтобы вычитать эти байты необходимо воспользоваться функцией Serial.read(). Рассмотрим работу этих функций на примере:

    После того, как код будет загружен в память микроконтроллера, откройте монитор COM-порта. Введите один символ и нажмите Enter. В поле полученных данных вы увидите: “I received: X”, где вместо X будет введенный вами символ.
    Программа бесконечно крутится в основном цикле. В тот момент, когда в порт записывается байт функция Serial.available() принимает значение 1, то есть выполняется условие Serial.available() > 0. Далее функция Serial.read() вычитывает этот байт, тем самым очищая буфер. После чего при помощи уже известных вам функций происходит вывод.
    Использование встроенного в Arduino IDE монитора COM-порта имеет некоторые ограничения. При отправке данных из платы в COM-порт вывод можно организовать в произвольном формате. А при отправке из ПК к плате передача символов происходит в соответствии с таблицей ASCII. Это означает, что когда вы вводите, например символ “1”, через COM-порт отправляется в двоичном виде “00110001” (то есть “49” в десятичном виде).
    Немного изменим код и проверим это утверждение:

    После загрузки, в мониторе порта при отправке “1” вы увидите в ответ: “I received: 110001”. Можете изменить формат вывода и просмотреть, что принимает плата при других символах.

    Управление устройством через COM-порт

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

    При отправке в COM-порт символа “H” происходит зажигание светодиода на 13ом выводе, а при отправке “L” светодиод будет гаснуть.
    Если по результатам приема данных из COM-порта вы хотите, чтобы программа в основном цикле выполняла разные действия, можно выполнять проверку условий в основном цикле. Например:

    Если в мониторе порта отправить значение “1” светодиод будет мигать с частотой 5Гц. Если отправить “0” – частота изменится на 1Гц.

    Ссылка на основную публикацию
    ВсеИнструменты
    Adblock
    detector
    ×
    ×