Современные аппаратные средства связи микроконтроллера с компьютером по интерфейсу RS-232. Часть 1
Разработанный еще в 1969 году последовательный интерфейс RS-232 до сих пор не утратил своего значения. Появление более современных интерфейсов, которыми оснащаются компьютеры (например, USB) и микроконтроллеры (например, CAN, I2C, SPI, RS485) и которые по многим параметрам (скорость и надежность обмена информацией, длина линии связи и т. п.) превосходят интерфейс RS-232, казалось бы, должно привести к «концу» использования этого интерфейса. Но интерфейсом RS-232 продолжают оснащать даже современные компьютеры и микроконтроллеры (а во многие из микроконтроллеров интегрируют даже по два таких интерфейса).
Разработанный еще в 1969 году последовательный интерфейс RS-232 до сих пор не утратил своего значения. Появление более современных интерфейсов, которыми оснащаются компьютеры (например, USB) и микроконтроллеры (например, CAN, I 2 C, SPI, RS485) и которые по многим параметрам (скорость и надежность обмена информацией, длина линии связи и т. п.) превосходят интерфейс RS-232, казалось бы, должно привести к «концу» использования этого интерфейса. Но интерфейсом RS-232 продолжают оснащать даже современные компьютеры и микроконтроллеры (а во многие из микроконтроллеров интегрируют даже по два таких интерфейса).
Все статьи цикла:
- Современные аппаратные средства связи микроконтроллера с компьютером по интерфейсу RS232. Часть 1
- Современные аппаратные средства связи микроконтроллера с компьютером по интерфейсу RS-232. Часть 2
- Современные аппаратные средства связи микроконтроллера с компьютером по интерфейсу RS-232. Часть 3
Вступление
О моём устройстве расскажу немного позже, сохраним интригу. Предвидя вопрос типа «В чём смысл этого топика?», отвечу, что простого и законченного решения в сети я так и не нашёл. Под простым и законченным решением я подразумеваю дуэт микроконтроллера (далее МК) с компьютером (далее ПК) и заготовки кода с функцией автоматического коннекта, а также мега-функцией «поморгать светодиодом». Пришлось повозиться и собрать все элементы мозайки в единую картину, которую я решил оформить в статью. Надеюсь, она поможет новичкам в вопросе «Как связать микроконтроллер с компьютером через USB» без лишних заумных слов. Уточню, что программированием занимаюсь для удовольствия, поэтому не претендую на образцово-показательный код. Это всего-лишь мой личный опыт, и вам судить, дорогой читатель, насколько он полезен.
Обеспечить двусторонний обмен данными между МК и ПК через USB. Никаких плат и софта типа Arduino в готовом решении мы не используем.
Сделать так, чтобы ПО компьютера автоматически определяло наше устройство при подключении его к любому USB-разъему.
USB-устройство должно отображаться в диспетчере устройств под нашим собственным именем (например, под именем нашей компании).
Примечание. Последний пункт я не стал раскрывать в рамках этой статьи, потому что бесконечную простыню текста и картинок читать утомительно. Оставлю материал для будущей статьи, если тема окажется интересной.
Выполнив это, мы получим огромную власть над нашими устройствами. Однако, есть ограничение — скорость передачи данных будет небольшой. Но отправка несложных команд, текста, или легких файлов будет работать быстро.
Создание проекта в среде AVR Studio
Создаем проект AVR GCC, назовем его например Hid_example_firmware. И начнем писать нашу прошивку.
- usbdrv.c;
- oddebug.c;
- usbdrvasm.s.
Для того чтобы добавить файла нужно выбрать в контекстном меню «Add existing Source File(s)»
Далее нам необходимо корректно настроить файл usbconfig.h и также его поместить в папку с проектом. Inline комментарии usbconfig.h была переведена на русский язык. Код приведен ниже.
Теперь правильно настроим usbconfig.h и также поместим в каталог с проектом (ссылка рабочего проекта-примера в конце статьи). Inline документацию usbconfig.h я перевел на русский (использовал перевод от microsin.ru + дополнял сам). Там очень много опций, в статье опишу самые необходимые для быстрого старта (подробности смотрим внутри файла).
Программа на компьютер для USB связи
Для начала сделаем простую консольную программу, потом будем делать программу с окнами.
1) Скачиваем исходные коды консольной программы OpenRobo, которые собраны из исходников проектов V-USB и LibUSB. Распаковываем архив на диск C:, после чего содержимое директории C:OpenRobo должно выглядеть так:
Назначение файлов: include и lib — это драйверы LibUSB для доступа к USB из программы set-led.c — это исходник нашей программы |
2) Скачиваем программу LibUSB, которая нужна для работы с устройством из программы. Устанавливаем. Сайт разработчика LibUSB. После установки подключите собранное устройство к USB. Запустите через меню Пуск/Программы/LibUSB-Win32/Filter Wizard. В открывшейся программе выберите для установки фильтра на порт, в следующем списке выберите только что подключенное устройство, его можно найти по vid:16c0 pid:05df. Нажмите кнопку Install. Если устройства в списке нет, значит вы либо не правильно собрали устройство и оно не опозналось, либо драйверы уже были установлены. В случае смены порта подключения устройства, надо опять заходить и устанавливать фильтр, иначе программа не сможет распознать устройство. Обязательно подключайте устройство USB к тому же порту USB, что был подключен при установке фильтра!
3) Скачиваем программу MinGW, которая нужна для сборки программы из исходника. Устанавливаем. Сайт разработчика MinGW. После установки зайдите в Панель управления, Система, Дополнительные параметры системы, Дополнительно (вкладка), Переменные среды (кнопка), Системные переменные (список), Переменная Path (найти в списке, выделить, нажать кнопку Изменить). Дописываем в поле Значение переменной в конце ;c:MinGWbin и нажимаем ОК, надеюсь вы установили MinGW в C:MinGW, иначе надо путь другой прописать.
Настраиваем системную переменную Path для MinGW
Подготовка программы ПК
↑ А как же это все должно работать?
Подойдя к стадии написания программного обеспечения для МК я задался вопросом, а как же это все будет работать. Немного подумав, я решил, что алгоритм работы должен выглядеть следующим образом:
После включения микроконтроллера (его подключения к ПК), инициализируется его работа, устанавливается режим работы приемо-передатчика UART, после чего разрешаются прерывания и МК ждет приема данных от программы, запущенной на ПК.
При запуске программы и удачном подключении устройства, программа обменивается с МК данными иполучает сообщение об удачном подключении. При повторном подключении программы к уже включенной плате, устройство посылает сообщение о количестве и номере включенных устройств.
Работает МК в режиме ожидания, пока не произойдет прерывание по приему данных. Описанный выше цикл повторяется бесконечно, пока включено питание устройства.
Лок-биты (Pro)
Лок-биты (lock-bits) позволяют управлять доступом к памяти микроконтроллера, что обычно используется для защиты устройства от копирования. Лок-биты собраны опять же в конфигурационный лок-байт, который содержит: BOOTLOCK01, BOOTLOCK02, BOOTLOCK11, BOOTLOCK12, LOCKBIT1, LOCKBIT2 (для ATmega328). Калькулятор лок-битов можно использовать этот. BOOTLOCK биты позволяют запретить самому МК запись (самопрограммирование) во flash память (область программы и область загрузчика)
А вот локбиты LOCKBIT позволяют запретить запись и чтение flash и EEPROM памяти извне, при помощи программатора, т.е. полностью защитить прошивку от скачивания и копирования:
Таким образом включив LOCKBIT1 (лок-байт будет 0x3E) мы запретим внешнюю запись во Flash и EEPROM память, т.е. при помощи ISP программатора, а включив LOCKBIT1 и LOCKBIT2 (лок-байт: 0x3C) полностью заблокируем заодно и чтение данных из памяти микроконтроллера. Повторюсь, всё описанное выше относится к ATmega328p, для других моделей МК читайте в соответствующих даташитах.
Proteus отдыхает
Всенародно любимый симулятор электрических схем Proteus ISIS бесполезен при разработке устройств с программной реализацией USB. Его эмулятор USB поддерживает только чипы с аппаратной поддержкой универсальной последовательной шины (например, AT90USB646 или AT90USB1286).
Ниже приведен небольшой, но очень полезный Makefile, c помощью которого командой make из main.c и usbtest.c легко получить прошивку для чипа — main.hex и бинарник утилиты usbtest:
Чтобы залить прошивку в микроконтроллер с помощью программатора usbtiny, набираем команду:
В avrdude фьюзы задаются не слишком наглядно, но их можно легко рассчитать в одном из online-калькуляторов.
Online-калькулятор фьюзов
Подключаем устройство к компьютеру и проверяем, как оно работает (usbtest c параметром out считывает строку, in — записывает указанную строку в буфер чипа):
Тестирование взаимодействия с ATtiny2313 по USB (заливаем в чип строку, а затем cчитываем ее)
Файлы
Related items
- Библиотека для опроса кнопок
- Работа с SD картой. Воспроизведение wav файла. Ч3
- Работа с SD картой. Подключение к микроконтроллеру. Ч1
- AVR315: Использование TWI модуля в качестве ведущего I2C устройства
- ATtiny10. Самый маленький микроконтроллер AVR
Comments
Есть ли какие-либо определенные подходы
если поток данных между МК и ПК насыщен
( например идут данные разной структуры ,
при этом идет посылка определенных команд
) .
Или тут все зависит от мастерства программировани я .
На ПК я использую VB6 . Там почти все
делаю через обработчик событий CommEvent .
Может быть на ПК в этом случае есть более
фунциональный язык .
Со стороны МК использую CodeVision .
Использовать приемный и передающие fifo буферы. А для «распознавания» принятых данных — state machine(автомат ) на таблицах или switch`е. Больше тут ничего не придумаешь.
Доброго времени суток!alexander shahbazov можете объяснить(на форуме) по подробнее про использование обработчика событий CommEvent(компонент MSComm1). Я сам программирую в VB6, с недельку назад разобрался с USART-ом на Mege8535. Буду очень благодарен! 🙂
Dim chr As String
Private Sub ATmega8_OnComm()
Select Case ATmega8.CommEvent
Case comEvReceive
chr = ATmega8.Input
‘Здесь уже кому что надо
End Select
End Sub
Собрал на mege48. При приеме символов не отображает практически ничего — черный квадратик. если отправлять с терминала строку с абзацем — показывает абзац.
При отправке на компе принимается группа из 6-7 символов. притом 5 из них одинаковые, а остальные какие-то кракозяблы. Ну никак это не похоже на ОК.
Вчем мой косяк?
— Проект в статье написан для mega8535. Для другого микроконтроллер а его нужно перекомпилировать.
— Кракозябы часто возникают, когда скорость обмена мк и компа не совпадают. У меня в схеме тактовая частота мк — 8МГц, скорость обмена — 9600.
Угу. Перекомпилирова л естественно под 48й кристалл. Фьюзы стоят на внутренний 8 мгц по-умолчанию. скорость 9600. а кракозяблы остались.
Какой компилятор?
У mega48 названия битов и регистров модуля USART отличаются от mega8535 и при перекомпиляции из нужно исправлять. Скинь мне проект на microsmaster’со бака’rambler.ru , я гляну его
Собрал на меге168 работает хорошо.
Только мах232 почемуто на 3,3В не работает.Знаю что 5В надо, но другом проекте другой мах232 работал отлично.
Помогите настроить проект под Atmega8515? я новичек и что-то не разберусь IAR выдает
Error[Pe020]: identifier «UCSZ1» is undefined
Error[Pe020]: identifier «UCSZ0» is undefined
Error[Pe020]: identifier «UDRE» is undefined
Помогите настроить проект под Atmega8515? я новичек и что-то не разберусь IAR выдает
Error[Pe020]: identifier «UCSZ1» is undefined
Error[Pe020]: identifier «UCSZ0» is undefined
Error[Pe020]: identifier «UDRE» is undefined
Разрешаем использование имен битов определенных в хидер файле
В General Options > System ставим галочку Enable bit definitions in I/O-Include files.
интерестно, в нете в некоторых схемах одни соединяют ноги разьема rs232 некоторые нет, в чем разница и что лучше?
Полная версия стандарта RS-232 включает 9 сигналов. В большинстве случаев пользуются сокращенным вариантом — 3 провода (RXD, TXD, GND). Просто так удобнее.
Изучаю работу UART по Вашему примеру 🙂 Но возникла проблема при приеме символов. На передачу все работает замечательно, а прием отсутствует 🙁 В прерывание заходит «через раз» и регистр UDR имеет нулевое значение. Выставляется ошибка кадрирования. Все собрано «в железе» контроллер AtMega162 (программа естественно исправлены на него). Это вероятней всего аппаратная проблема?
Может быть проблема в несогласованнос ти скоростей обмена данными терминала и мк. Ну то есть в терминале выставлена одна скорость, а микроконтроллер посылает/приним ает данные с другой. От чего тактируется мк и какая у него частота?
Привет всем, не уверен, что правильно понял схему:
1. prog connector — это программатор?
2. txd и rxd — это uart/usart переходник?
Спасибо за ответы)
Привіт!
Заюзав ваш приклад використання USART
та знайшов помилку. незнаю як в старих версіях WinAvr але в нових версіях оголошувати переривання потрібно
ISR(USART_TXC_v ect)а не ISR(USART_TX_vect)
ISR(USART_RXC_vect)а не ISR(USART_TX_ve ct). до цього в мене просто ‘завісав’ МК Atmega8.
Написал программу. МК(mega8) передает символы на ПК через usb-uart переходник(bm80 51) только если подключен программатор (avr910).Без него не пересылает. Кто-нибудь сталкивался с подобным?
Подал на него «+5»- все равно, — без программатора, подключенного к ПК символы по Usart’у не передаются.
Pashgan, понял я в чем дело. Чуть голову не сломал от раздумий 🙂 . UART я подключал как показано на схеме: RXD и TXD, без земли (она не указана).Подсое динил землю — все заработало 🙂 .
По-моему, загружать главный цикл примитивной отправкой сообщения — не совсем рационально, там и так достаточно работы будет. Гораздо интереснее заставить это делать сам USART. Для этого не вызываем SendChar(. ) столько раз, сколько символов в буфере отправки, а пользуем прерывание по опустошению UDR. Когда нам требуется отправить сообщение — грузим UDR байтом из буфера по нулевому индексу и сразу разрешаем прерывание UDR. Цепочка такая: первый байт проваливается-U DR опустошается-во зникает прерывание-в прерывании считывается второй байт-прерывание сбрасывается-по опустошению UDR возникает прерывание-. и т.д. Только в прерывании проверять на равенство взятого из буфера байта 0 — признак конца строки. Если взяли 0 — ничего не отправляем и глушим прерывание сбросом бита UDRE.
Таким образом, USART самостоятельно выгребет весь буфер и сам себя успокоит.
Идея любезно подсказана DI HALT’ом. (dihalt.ru)
А что означает если по USART всегда передается 00000000, и ничего не принимается не при каких условиях?
так постоянно нули передавать ещё проще — грузи их по прерыванию UDR и всё
а на практике такая потребность часто возникает?
подключил Вашу программу, символ отсылаю, в ответ приходит — это первое.
Второе, пишу if (sym == ‘q’)
Подключать на прямую без МАХ232 но лучше FT232BM заменить на FT232RL. У RL обвязки никакой не надо там всего 2 конденсатора по питанию достаточно (а цена одинаковая).
К стати не соединяйте Экран USB разъемов с землей, FT232 к этому очень чувствительна и может начать сбоить(типа устройство не опознано) На ноутбуке этого не будет на на стационарном компе может получится.
Я очень долго с этим мучился.
К стати спасибо за доходчивое объяснения)))
Всем привет. Я еще пока очень зелен в МК. Как в AVR Studio 5 быть с этой программой? К примеру прерывание если правильно понимаю __enable_interr upt(); он не понимает. Читал на форумах что в разных компиляторах все команды на одном и том же языке вводятся по разному. Как узнать все эти разности? Может есть где описание типа к примеру для AVR Studio 5 эта команда так будет выглядеть, а для WINAVR вот так. Может кто встречал в интернете подобное. За ранее всем благодарен.
Если кто знает, как в AVR studio 5 при наборе кода сделать что бы выпадал список с подсказками как например вот в этом видео на пятой минуте просмотра http://www.youtube.com/watch?v=3Koa6oy53Os&feature=related . Всем еще раз спасибо
Здравствуйте!
Пишу диплом, и практически сразу стллкнулся с проблемой. Пишу в iar а отлаживаю в протеусе и авр-студии. Необходимо отправлять 3-и 2-ух байтных числа, как только отправляю байт (например все единицы), приходят одни нули. При проверке в студии обнаружил, что когда помещаю число в UDR, на следующем цикле UDR обнуляется. Прочитал что на самом деле для передачи используется другой регистр, а UDR на подобии буфера. Тогда попробовал присваивать UDR одно число и в следующей строчке другое, но UDR всё равно обнуляется, а не ждёт пока регистр отправки отправит предыдущий.
Думаю вопрос глупый, и что я банально что-то упустил из виду=)
присоединяюсь к вопросу- как проверить полученный символ? вот так-
if (data==’A’)
stat=1;
>
if (data==’B’)
stat=0;
>
while (stat)
Так же как и в примере
Code:
sym = USART_GetChar(); //читаем буфер
if (sym) < //если что-то приняли, то
LCD_Goto(6,0);
LCD_WriteData(sym); //отображаем на lcd принятый символ
USART_SendChar(‘O’); //отвечаем компу «Ok »
USART_SendChar(‘k’);
USART_SendChar(‘ ‘);
>
Если не получается, то может быть скорость неправильно настроена.
Code:
sym = USART_GetChar(); //читаем буфер
if (sym)< //если что-то приняли, то
Если не получается, то может быть скорость неправильно настроена.
Делаю вроде по аналогии, но без дисплея. На переходнике USB-UART светодиод моргает — символ отправлен. но Ок нет =( Земля и от LPT программатора и от переходника подключены, питание есть, но молчок
кристалл mega8515, скорость 9600, частота 8000000
поменял на:
1843200 hz, 115200 бод, плучилось 0
светодиоды на переходнике горят оба — символ отправлен и что-то принято, но в одном терминале (keterm) отобраюжаются буквы, в другом SimpleTerm — вопросы, в третьем Advanced Serial Port Monitor — те же буквы. В терминалах выбирал 115200 бод.
Я взял проект, поменял тип микроконтроллер а на mega8515 и запустил компиляцию. В Протеусе полученная прошивка сразу же заработала (тактовая 8 МГц, скорость обмена 9600). В железе нет возможности проверить.
Через что подать символ по UART в Протеусе? В протеусе добавил компонент com, подключил к 8515. и непонятные символы пошли в ответ
Здравствуйте!По дскажите,пожалу йста как организовать мультипроцессор ный обмен между мастером и двумя слейвами.Принци п понимаю,смотрел пример из datasheet на mega8.В Proteus удалось добится только одноразового аппаратного сброса MPCM при прохождении «1» в 9-ом разряде.Дальше- затык.В железе не пробовал пока.
Просто всё — разрешаете прерывание по приёму байта, в прерывании пишите данные в кольцевой буфер, а в основной программе обрабатываете принятые данные.
Гдето я наверно накосячил, так же и пытался сделать
если у кого есть такой кусочек кода для приема, буду благодарен)
Гдето я наверно накосячил, так же и пытался сделать
если у кого есть такой кусочек кода для приема, буду благодарен)
Например так:
Code:
#define RX_BUFFER_SIZE 100
volatile uint8_t RxBuffer[RX_BUFFER_SIZE];
volatile uint8_t RxNext, RxFirst;
ISR(USARTC0_RXC_vect)
uint8_t rx_next=RxNext;
RxBuffer[rx_next]=USARTC0.DATA;
if (++rx_next>=RX_BUFFER_SIZE)
rx_next=0;
RxNext=rx_next;
>
void UsartReceive()
uint8_t rx_first=RxFirst, rx_next=RxNext;
while (rx_first!=rx_next) uint8_t new_byte=RxBuffer[rx_first];
// обработка данных
//
if (++rx_first>=RX_BUFFER_SIZE)
rx_first=0;
>
RxFirst=rx_first;
>
Спасибо, буду ковырять косяк, вроде похоже делал, но принимает только первый байт, второй почему-то ноль
С примером проще разбираться))
здравствуйте, разглядывал много схем с уарт преобразователя ми, и что увидел, на некоторых есть резисторы на линиях rx и tx, на некоторых нету, а на некоторых есть резистор только на одной линии, так вот собственно нужны ли всё таки там резисторы? и зачем?
предпологаю для защиты, например по уарту «плюётся» еденичка, а на втором конце по случайности «мёртвая» земля
и какая сторона в состоянии покоя подтягивает линию к 5-ти вольтам?
мне кажется tx подтягивает к 5-ти вольтам, а rx всегда может только слушать линию(то есть всегда в высокоимпедансн ом состоянии)?
Здравствуйте Pashgan, собрал Вашу схему на mega8515 немного поменял код — все отлично работает. Пошел дальше сделал программу на ПК которая отсылает побайтно содержимое бинарника и сразу столкнулся с проблемой: программа не принимает 0х00 и виснет, так как от контроллера нет ответа. Я попытался в файле usart.c в прерывании подписать еще одну переменную, которая принимает значение 1 при событии приема байта. Вообще корректно ли так делать или нет? С++ начал учить совсем недавно. Далее, попытался переделать функцию USART_GetChar на возвращение структуры состоящей из двух символов буфера и флага приема байта. Пытался компилировать в CVAVR но ни чего не получилось — вообще не пойму в чем проблема вот код
Code:
#include «usart.h»
//однобайтный буфер
volatile unsigned char usartRxBuf = 0;
unsigned char fl = 0;
struct my_strct ;
#define RXCIE 7
#define RXEN 4
#define TXEN 3
#define URSEL 7
#define UCSZ1 2
#define UCSZ0 1
//чтение буфера
my_strct USART_GetChar(void)// на это место компилятор ругается ‘(‘ expected
<
my_strct my;
//unsigned char tmp;
unsigned char saveState = SREG;
#asm(«cli»);
my.buf=usartRxBuf;
my.flg=fl;
//tmp = usartRxBuf;
usartRxBuf = 0;
fl=0;
SREG = saveState;
return my;
//return tmp;
>
//прием символа по usart`у в буфер
interrupt [USART_RXC] void usart_rxc_my(void)
usartRxBuf = UDR;
fl=1;
>