Шаг 3. Разговорчики через UART
В этот раз мы попробуем связать компьютер и нашу микросхемку) Чуточку модернизируем предыдущую схему, перепишем программу и получим, что при нажатии кнопок на клавиатуре у нас будут загораться восьмибитный код символа (если единичка - соответствующий светодиод горит, если нолик - не горит).
Что потребуется нам в этот раз и подручных средств: из старой схемы остаются 8 светодиодиков и 9 резистров, из новенького - пара резисторов этак на 10 кОм да переходник Usb - Usart - можно сделать самому, если вдруг есть старые дата-кабели от телефонов, или же попросту заказать где-нибудь на алиэкспрессе. А также нам нужен конденсатор - у нас на 100 мкФ при максимальном напряжении 25В.
Чуть-чуть о том, что такое USART и с чем его едят:
UART - это последовательный асинхронный интерфейс для передачи данных.
А теперь понятно:
Интерфейс - совокупность средств, методов и правил взаимодействия между элементами системы.
Последовательный - значит, одна линия для передачи данных, и биты информации передаются один за одним.
Асинхронный - значит, и у приёмника, и у передатчика есть свой генератор импульсов - он задаёт, с какой частотой будут передаваться биты.
Можно сказать, чем-то похоже на морзянку) Сидит по разные концы провода такая парочка: один готов передавать, другой - получать.
При передаче по интерфейсу USART каждому блоку данных (обычно байту - 8 бит) предшествует СТАРТ-бит, сигнализируюший приёмнику о начале передачи, и завершает его СТОП-бит, обеспечивающий паузу между передачами.
Ну что ж, с теорией покончили, ближе к делу! Вот схемка:
В принципе, тут добавлено не так уж много, и вроде всё более-менее должно быть понятно… Новый элемент - конденсатор, он используется как стабилизатор при возможных скачках напряжения. Возможно, возник вопрос «а зачем нужны резисторы при соединении переходника и микросхемки?» - но об этом дальше.
Пока же разберёмся, что вообще нам нужно:
- Включаем наш передатчик, настраиваем его на нужную частоту
- Ждём, когда придут данные - код символа
- Дождались - включаем наши светодиодики… Только вот проблема - мы-то привыкли, что единичка - включено, а нолик - выключено. А вот если мы подадим на вывод, к которому подключён светодиод, логическую 1 - ничего и не загорится((((Поэтому проделываем над нашим считанным символом инверсию - где были нолики, там станут единицы…
- Отвечаем компьютеру тем же символом)
Ну вот, в принципе и всё… Будем смотреть конкретнее:
Чтобы настроить наш передатчик… Ура, за нас всё сделано - достаточно только задать скорость: библиотечная процедура UART1_Init(9600)
Отлично, теперь смотрим, что нужно делать в цикле:
Сначала проверяем, пришли ли нам какие-нибудь данные. Тут опять за нас уже подготовили функцию UART1_Data_Ready(). Она возвращает «1», если что-то новенькое до нас дошло, и «0» - если нет.
Теперь, соответственно, нам нужно прочитать символ. Так как в дальнейшем мы его будем ещё использовать, то вначале заведём переменную типа char, и назовём её, например,cSymbol. Ну а чтобы читать данные, есть готовая функция - UART1_Read().
С этим разобрались, едем дальше: зажигаем наши светодиодики, не забыв проделать инверсию: portB = ~cSymbol;
И напоследок, отсылаем компьютеру «эхо» - тот же символ: UART1_Write(cSymbol)
Вот и всё
Соответственно, получаем программу:
Си:
//передача символа от компьютера к микросхеме по UART. Отсылка символа обратно и отображение символа на светодиодной дорожке typedef unsigned char byte; //определяем ссылки на регистры ввода-вывода #define ddrLED_Road DDRB #define portLED_Road PORTB #define ddrUART DDRD #define portUART PORTD //глобальные переменные и константы const byte DDR_LED_ROAD_INIT = 0xFF; //настройка порта со светодиодами - на выход и const byte PORT_LED_ROAD_INIT = 0xFF; //светодиоды не горят const byte UART_RX_MASK = 0x01; //маски для выводов UART const byte UART_TX_MASK = 0x02; void main() { byte cRecievedSymbol; //переменная для хранения символа, принимаемого через UART //инициализируем все порты ввода-вывода на вход без подтяжки DDRA = 0; PORTA = 0; DDRB = 0; PORTB = 0; DDRD = 0; PORTD = 0; //инициализация занятых портов ddrLED_Road = DDR_LED_ROAD_INIT; portLED_Road = PORT_LED_ROAD_INIT; ddrUART = (ddrUART | UART_TX_MASK) & (~UART_RX_MASK); portUART |= UART_RX_MASK | UART_TX_MASK; //инициализация периферии - в нашем случае, UART-а UART1_Init(9600); while(1) { if(UART1_Data_Ready() == 1) //если получили данные { cRecievedSymbol = UART1_Read(); //считали символ portLED_Road = ~cRecievedSymbol; //отобразили принятый символ на светодиодной дорожке UART1_Write(cRecievedSymbol); //и отправили его обратно } } }
Паскаль:
//передача символа от компьютера к микросхеме по UART. Отсылка символа обратно и отображение символа на светодиодной дорожке program UART; const DDR_LED_ROAD_INIT = 0xFF; //настройка порта со светодиодами - на выход и PORT_LED_ROAD_INIT = 0xFF; //светодиоды не горят UART_RX_MASK = 0x01; //маски для выводов UART UART_TX_MASK = 0x02; var //указатели и константы для портов - где будет UART и где будут светодиоды ddrUART : byte at DDRD; portUART : byte at PORTD; ddrLED_Road : byte at DDRB; portLED_Road : byte at PORTB; cRecievedSymbol: byte; //переменная для хранения символа, принимаемого через UART begin //инициализируем все порты ввода-вывода на вход без подтяжки DDRA := 0; PORTA := 0; DDRB := 0; PORTB := 0; DDRD := 0; PORTD := 0; //инициализация занятых портов ddrLED_Road := DDR_LED_ROAD_INIT; portLED_Road := PORT_LED_ROAD_INIT; ddrUART := (ddrUART or UART_TX_MASK) and (not UART_RX_MASK); portUART := portUART or UART_RX_MASK or UART_TX_MASK; //инициализация периферии - в нашем случае, UART-а UART1_Init(9600); while(1) do begin if(UART1_Data_Ready() = 1) then //если получили данные begin cRecievedSymbol := UART1_Read(); //считали символ portLED_Road := not cRecievedSymbol; //отобразили принятый символ на светодиодной дорожке UART1_Write(cRecievedSymbol); //и отправили его обратно end; end; end.
Готовая программка - тут.
А вот как это выглядит:
Ну, естественно, нужна программа для «общения» с микросхемой. Так вот, в наших средах есть свой личной терминальчик (Ctrl + T). Наша задача - поставить правильно частоту, выбрать порт, к которому подключён передатчик, определить, что у нас один стоп-бит, отключить контроль чётности (parity) и управление потоком передачи данных (flow control), а также выбрать размер "слова" (то, сколько бит мы передаём за раз) 8 бит - именно так настраивается UART с помощью библиотечной функции. Нажимаем кнопку "Connect&, и вуаля - все работает! Вводим в строку "1", и на светодиодной дорожке появляется... 0x31 - код ANSII-символа "1". Чтобы увидеть действительную единицу, нужно использовать терминальчик с отправкой шестнадцатиричных чисел - например, терминал COM Port Toolkit.
Теперь пару слов о волшебных резисторах, или как жадность может погубить микросхемку:
В этот раз мы столкнулись с такой коварной вещью, как паразитное питание… После выключения из сети - о, боги! - у нас всё равно продолжали гореть светодиоды… Дело в том, наша микросхемка искала какой-нибудь другой источник питания - и находила его в лице нашего переходника; иными словами, она работала от usb. Однако питания для нормальной её работы, естественно, не хватало, вот и начались страшные и таинственные глюки через раз.
А наши резисторы легко и просто решают проблему - они просто не пускают ток, который пытается вытребовать себе микросхемка) Вот как-то так)
Автор - Moriam
Обсудить на форуме