Наступила очередь рассказать о довольно интересной теме — о том, как подключить AVR микроконтроллер к компьютеру. Для этого, у микроконтроллеров есть приемопередатчик. У некоторых их, даже два.
Update:10.02.17
Использовать будем UART наиболее простой и распространенный интерфейс. Чтобы понять как он работает, представьте себе что уарт это водопроводный кран, из которого течет вода — байты. Каждая новая капля, «затирает» старую, поэтому главная задача нашей программы успевать забирать данные до того, как придут новые.
Существует два основных способа, это все время в цикле проверять наличие новых данных по флагам или настроить прерывание, по приходу нового байта. Если программа не использует задержки и скорость передачи низкая, то можно использовать первый способ, в остальных случаях, лучше использовать прерывания.
Данные приходят последовательно один байт за другим, поэтому часто UART называют последовательным портом. Если ваша программа достаточно простая, то можно принять/передать один байт и на основании этого выполнить какое то действие. Например если приняли байт 100, то включили светодиод.
if(byte == 100) { PORTB.1 = 1; } |
Только не стоит путать ASCII символ и байт, например i = ‘1’ i = 1 не одно и тоже. В чем разница можно почитать тут
Если ваша программа подразумевает, нечто более сложное, т.е. прием нескольких байт, то в прерывании по приходу данных складываем их в массив, далее в основном цикле разбираем массив. Стоит понимать, что поток не имеет ни начала, ни конца, он просто льется постоянно, поэтому нужно самому придумать какие то условности которые бы говорили о том, что сейчас пришел первый байт, а сейчас последний. Типовое решение, это использование спецсимволов, либо таймаутов. Пример можно посмотреть тут
Теперь перейдем к железу. У Atmega8 всего один приемопередатчик, PD0 — Rx, receiver (приемник) и PD1 — Tx, transmitter (передатчик).
Аналогичные ножки есть на нашем переходнике FT232. Соединяем микроконтроллер и переходник между собой. В протеусе это будет выглядеть так:
Напишем программу, которая по сигналу от компьютера будет включать светодиод и выключать. В CodeVision создаем новый проект, микроконтроллер atmega8, частота 8МГц (тактирование от кварца), на закладке USART включаем приемник и передатчик.
Обратите внимание, при текущей частоте микроконтроллера и скорости передачи, ошибка составляет 0,2%, т.е. данные могут теряться, но вероятность этого крайне низкая. Порт B настроим как выход — к нему подключим светодиод.
#include <mega8.h> #include <stdio.h> void main(void) { char data; PORTB=0x00; DDRB=0xFF; PORTD=0x00; DDRD=0x00; // USART initialization // Communication Parameters: 8 Data, 1 Stop, No Parity // USART Receiver: On // USART Transmitter: Off // USART Mode: Asynchronous // USART Baud Rate: 9600 UCSRA=0x00; UCSRB=0x10; UCSRC=0x86; UBRRH=0x00; UBRRL=0x33; while (1) { data=getchar(); if(data=='1') { PORTB=0xFF; } if(data=='0') { PORTB=0x00; } }; } |
В текущем алгоритме используется простой способ функция getchar() постоянно проверяет не появились ли новые данные. После того как данные пришли — записываем их в переменную data; если пришла единичка, зажигаем светодиод; если 0, то выключаем его. Еще раз обратите внимание ‘1’ означает ASCII символ 1, реально байт будет равен 0x31. Сделано так, потому что большинство терминалов при нажатии кнопки на клавиатуре, отправляет именно символы.
Собираем схемку и прошиваем. Подключаем к компьютеру. Запускаем программу KeTerm или другой терминал. Подсоединяемся к нужному com порту. Шлем единичку — светодиод включается, шлем 0 светодиод выключается.
Урок был бы неполным, если не применить наши знания по C#.
Создадим проект, нарисуем 2 кнопки и последовательный порт
В свойствах последовательного порта не забудьте настроить PortName, он должен соответствовать номеру порта переходника FT232. Добавим события: по клику на 1 кнопку — отсылаем 1, по клику на 2 кнопку — отсылаем 0, при загрузке формы — открытие порта, при выходе из формы — закрытие порта.
private void button1_Click(object sender, EventArgs e) { serialPort1.WriteLine("1"); } private void button2_Click(object sender, EventArgs e) { serialPort1.WriteLine("0"); } private void Form1_Load(object sender, EventArgs e) { serialPort1.Open(); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { serialPort1.Close(); } |
И напоследок, видео работы всего этого безобразия)
Update: По просьбе Евгения программа немного изменена, теперь при запуске программа автоматически проверяет все ком порты, если есть активные, то они заносятся в comboBox1.
1 2 3 4 5 6 | private void Form1_Load(object sender, EventArgs e) { string[] myPort; //создаем массив строк myPort = System.IO.Ports.SerialPort.GetPortNames(); // в массив помещаем доступные порты comboBox1.Items.AddRange(myPort); //теперь этот массив заносим в список(comboBox) } |
Исходники программы
А исходников к уроку нет?
ЗДравствуйте! СДелайте пожалуйста урок с построением графика по данным микроконтроллера .
уже есть http://avr-start.ru/?p=2261
Привет всем,помогите пожалуйста.
С передачей все ясно.
А как принять с com порта,и отобразить в бейсике?
Не подскажите как COM-порт переделать в USB. У меня отсутствует com-port.
FT232RL
Вмысле FT232RL? Ещё один МК нужен чтобы через USB всё это дело было? Ну а если через COM- порт подключать, то куда какие контакты от МК присоединять?
К ком порту напрямую нельзя подцепиться, ибо логические уровни разные, поэтому либо ставить преобразователь уровней, или использовать переходник usb-uart. В любом случае нужна доп. микросхема.
Пойдёт ?
а что за оболочка в которой вы кнопки вывели?
самопал на Visual C#
Можно ли использовать переходник CP2102 вместо FT232?
можно
Спасибо. Правда пришлось допилить напильником 🙂 Без внешнего кварца на частоте 1 МГц mega 8 за работала с такими настройками:
<codeUCSRA=0x02;
UCSRB=0x10;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x0c;
Здравствуйте. Можете показать как с МК отправлять символы???
Подскажите, если мне нужно подключить микросхему Atmega8, к компьютеру по COM portу используя порты микросхемы RXD и TXD, мне обязательно использовать max3232 и им подобные микросхемы, или я могу напрямую подключить Atmega8 к com порту.
только через преобразователь уровней, типо max
как можна работыть rs485
485 это физический интерфейс, выбирайте подходящую микросхему (например max485) и включайте по схеме в даташите
я подключил параллельно max485 atmega8 отправил uartu данни.. и там какойта ошибки..нужна кодирават сигнал как i2c
485 это всего навсего «удлиннитель», поэтому max485 должна стоять с двух сторон линии, кроме того нужно соблюдать рекомендации даташита, там схема нарисована как подключать. Естественно удлиннителю пофигу, что вы там отправляете или кодируете. Не путайте железо и программу.
Помогите пожалуйста разобраться!…
Написал небольшую программу для проверки COM порта. Прошил МК но что-то он работает не так как надо.
i='0';
j=i;
while (1)
{
if (i==j) {
i=getchar();
}
else {
switch (i) {
case '61' : PORTB=0b00000001; putchar('61'); break;
case '97' : PORTB=0b00000010; putchar('97'); break;
case 61 : PORTB=0b00000100; putchar(61); break;
case 97 : PORTB=0b00001000; putchar(97); break;
};
putchar(i);
j=i;
};
}
С терминала отправлю значение
Dec Hex Bin
= 61 3d 00111101
МК распознает как:
Dec Hex Bin
a 97 61 01100001
Так - как светодиод срабатывает при строке (case 97 : PORTB=0b00001000;)
А возвращает обратно в терминал значение
Dec Hex Bin
O 79 4f 01001111
проверьте еще раз все настройки скоростей, отдельно usb/uart, отдельно мк — закоротив rx и tx
Проверят не один раз. (Parameters: 8 Data, 1 Stop, No Parity, BR: 9600)
На разных системах Windows и Linux? Решил что то-то с терминалом, скачал парочку эффект тот-же. Побывал с разными кварцами (4мГц, 6мГц, 8мГц, 12мГц, 16мГц,) и на разных контролерах (ATmega8, ATtiny2313, ATmega32). Когда заторачиваешь rx и tx возвращается значение что отослал (но МК как-то коряво принимает значение). Голову уже сломал.
Питание МК 5 Вольт ставьте, если было 3.3
чудес не бывает, либо преобразователь сдох, либо с электрическим соединением что то не то.
Дайте пожалуйста кусочек кода для Mega16. Я вставил Ваш код в программу, и при компиляции вылезло куча Warning-ов. Более того, схема не работала, я подключал её к компу через CH340G, которую из ардуинки выпаял
воспользуйтесь codewizard, настойки указаны на картинке в статье
Огромное спасибо автору, просто шедевр! Делаю манипулятор на msp430. Статья просто в пору.Думал использовать проги консоли чтобы управлять с пк, а оказывается можно состряпать самому.еще раз спасибо автору!
а как отправлять данные по UART
прочитать статью выше)
С мк на пк
да все тоже самое только putchar(‘a’)
спасибо попробую написать
if(PINB.1==0)
{
data=putchar();
if(data==’0′)
{
} то есть во так ? ❓
приветствую, я что то запутался, если я например хочу отправить слово с мк на компьютер, то делаю вот так printf(«hello»); ? или так нельзя, а надо по одному символу слать?
и как мне передать число например 1, вот так UDR=1; ? и получить как это число? а то где то видел что ещё прибавляли зачем то 0x30.
putchar(‘A’); а вот так получится передать символ? число так не получится передать?
и зачем мастер код вижна генерит код передатчика с буфером?
все данные шлются по 8 бит, т.е. посимвольно. вы можете использовать функции, которые делают это за вас.
Не. Плохо объяснили. Человек немного путается в понятии байт и символ. Дело все в том что UART передает только байт. То есть число которое может иметь значение от 0 до 255 (если оно бесзнаковое) и от -127 до +127 (если знаковое). Всё, других вариантов нет. Далее Вам предстоит решить что передавать, либо просто число, либо символ. Далее, чем символ отличается от числа. Символ — это код записанный в виде числа. То есть Ваш вопрос о прибавлении 0x30. Если нужно передать число 0, то просто записываем 0, а вот если нужно передать символ 0, то вот тут уже нужно к числу прибавить 0x30. Откуда этот ужас. Откройте ASCII таблицу символов, например Пуск -> Все программы -> Стандартные -> Служебные -> Таблица символов и выберите символ 0. Внизу окна будет написан код символа U+0030. Вот как раз число 0x30 и является кодом символа 0. И так далее до 0x39. Это сделано для удобства преобразования чисел в символ и наоборот.
Алексей, большое спасибо, начинаю понимать
то есть всегда передаётся число, а на принимающей стороне мы уже решаем что это(символ или число)
например мне надо что то передать что бы на экране отобразить 67С (то есть 67 градусов цельсия), тогда я передаю число 67 и приёмник воспринимает как число 67, и опять передаю 67 и приёмник воспринимает как число 67, но приёмнк знает что первый байт надо отобразить как число, а второй байт надо отобразить как символ и преобразует второй байт (то есть число 67) в симсол «C», и на экране отображается 67С
Я прав?
Misha, нет не правы. Число 67 это просто число, а если выводить на ЖК то число необходимо преобразовать в символы. Давайте рассмотрим число 67. Оно состоит из двух разрядов 6 и 7. То есть нам нужно преобразовать число 67 в два символа 6 и 7. Как это сделать? А просто, берем тоже магическое число 0х30 и прибавляем к нему первый разряд 6. Получается 0х36. Далее к 0х30 прибавляем второй разряд 7 и получаем 0х37. Далее смотрим код символа «С». Если мне не изменяет память, то символ «А» это 0х41. Далее по алфавиту АВС, то есть «С» это 0х43. А для вывода на ЖК готовим такой вот массив srt[] = {0x36, 0x37, 0x43, 0x00}; Далее передаем этот массив в printf() и лицезреем выведенную температуру на ЖК. Число 0х00 в конце массива нужно для функции вывода на ЖК, оно означает конец строки и называется «Пустой символ»