Наступила очередь рассказать о довольно интересной теме — о том, как подключить 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) } |
Исходники программы



152 комментария: Урок 8. Передача данных через UART в AVR микроконтроллерах