Простые устройства
Просто об устройствах

WinAVR: консольный ввод-вывод

Тайные знания в массы!Методика «программирования кликами мышки» настолько прочно въелась в сознание соверменных пользователей компьютеров, что многие начинающие программисты микроконтроллеров считают WinAVR очень сложным и неудобным, а CVAVR напротив — очень простым и удобным. Мое мнение о CVAVR негативное, но сейчас не об этом. Я попробую показать, что решение многих типовых задач в WinAVR может быть ничуть не сложнее, чем использование плодов Code Wizard из CVAVR.

Речь пойдет о консольном вводе-выводе. Я имею ввиду организацию обмена информаци-ей между микроконтроллером и терминальной программой. Последняя имеется в любой версии Windows и называется Hyper Terminal или как-то похоже, для большинства реальных задач этого более чем достаточно. Подключение традиционно осуществляется через СОМ-порт, причем совершенно безразлично, как именно он реализован: будет ли это аппаратный RS-232 порт материнской платы, шнур-переходник USB-RS232 или микросхема FTDI в связке с микроконтроллером.

{ads2}Основная проблема видится именно в программе для микроконтроллера. Почитатели CVAVR, пару раз кликнув мышкой, при помощи Wizard-а получают заготовку программы, в которой функции sprintf и scanf уже работают через USART. Я докажу, что при использовании WinAVR аналогичный результат будет достигаться ничуть не сложнее.

Итак, скачиваем архив, в котором я приготовил три файла. Эти файлы вы должны будете скопировать в папку вашего проекта, хотя файл avr_helper.h я бы рекомендовал разместить в папке с «системными» заголовочниками (в папку avr\include\ внутри папки, куда установлен WinAVR), т. к. он содержит ряд универсальных макросов, которые будут вам полезны чаще, чем требуется консольный ввод-вывод.

Файл com_io.c должен быть включен в состав проекта для компиляции: если вы работаете с makefile, то допишите его в строчку с другими исходниками, а если пользуетесь AVR Studio, то добавьте его к проекту традиционным способом. Пользователям Eclipse вообще никаких усилий прикладывать не придется — все исходники из папки проекта автоматически (по умолчанию) добавляются к списку компилируемых.

Другой файл com_io.h должен быть немного отредактирован, а затем подключен директи-вой #include в каждом файле проекта, где будет требоваться работа с консольным вводом-выводом. Редактирование этого файла выполняет задачу CVAVR-овского Wizard-а по настройке требуемых параметров ввода-вывода:

НастройкиКак видите, каждый макрос содержит исчерпывающее описание в комментариях, надеюсь, никаких вопросов не возникнет. Скорость обмена рекомендую задавать из ряда стандартных, а при компиляции проекта смотреть за Warning-ами — там может быть предупреждение о том, что заданная скорость недостижима при выбранной тактовой частоте.

Собственно говоря, это все, что нужно сделать (!!!), чтобы в вашем проекте все функции семейства printf выводили через USART в терминал, а все функции семейства scanf — вводили данные из консоли (разумеется, для работы ввода константа ONLY_OUT должна содержать нулевое значение).

Хочу предупредить сразу о некоторых моментах, которые могут удивить начинающих программистов:

  1. Для поддержки printf и scanf автоматически подключаются библиотеки, которые увеличивают результирующий код примерно на 1,5 килобайта (прибавка может быть разной для разных типов микроконтроллеров).
  2. По умолчанию sprintf и scanf не поддерживают работу с числами float и double – если необходимо использовать их при вводе-выводе, следует подключить принудительно библиотеку поддержки «плавающей точки» (см. документацию к WinAVR). Поддержка плавучки прибавит к вашему проекту еще килобайт-другой.
  3. В соответствии со стандартом Си функции printf и scanf – это блокирующие функции, в них нет никакой «встроенной» буфферизации. Это означает буквально следующее: если вы задали скорость обмена 300 бод и решили вывести строку из 100 символов, то этот процесс займет больше 3-х секунд. При вводе функция scanf не вернет управление, пока не будут введены все требуемые ею данные.
  4. По умолчанию сделано так, что к каждому символу '\n' автоматически добавляется символ '\r'. Если это вам не требуется, вы должны в файле com_io.c найти и модифицировать функцию uart_putchar.
  5. В моем коде не учтена возможность наличия в микроконтроллере более чем одного модуля UART/USART. Если в используемом вами МК имеется два или более таких модулей, вам придется подкорректировать макросе INIT(7) в файле com_io.c, изменив наименования регистров на нужные, например, UCSRA заменить на UCSR0A или UCSR1A в зависимости от номера используемого USART.

Надеюсь, теперь все на самом деле убедились, что необходимость во всяких автоматических генераторах исходников не так уж и велика. В отличие от «библиотек» CVAVR исходный код рассматриваемого модуля полностью открыт и доступен для правки, поэтому несложно модифицировать его под любые ваши потребности, например, реализовать вывод в один модуль USART, а ввод — в другой.

Отдельное примечание для любителей все тестировать «в протеусе». Из версии в версию протеус тянет одну и ту же ошибку в своем симуляторе AVR: при выполнении аппаратного сброса он не устанавливает регистры UART/USART в состояние, предписываемое даташитом. Поэтому в файле com_io.c в макросе INIT(7) вы можете видеть как бы «лишние» операторы, задающие начальные значения регистрам — без этого симуляция в протеусе работать не будет, хотя «в железе» все отлично и без этих операторов. Если пара лишних байт в вашем коде не является решающей, рекомендую не менять в коде ничего для «совместимости с протеусом».

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

{ads1}

{code}#include

#include "com_io.h"

int main(void){

printf("\nI like WinAVR!\n");

return 0;

}{/code}

И вот попробуйте теперь сказать, что консольный ввод-вывод в WinAVR – это сложно!

Вложения:
ФайлОписаниеРазмер файла:
Скачать этот файл (console_io.zip)console_io.zipМодуль поддержки консольного ввода-вывода3 Кб

Комментарии   

#1 kot-69 22.03.2012 00:38
Спасибо за статью. Супер!!!
#2 MTh 28.06.2012 05:51
Спасибо большое. Выручила либа сегодня :)
#3 druidcat 06.08.2012 12:26
Спасибо тебе большое ARV, у меня такое ощущение, что ты единственный в рунете помогаешь людям по WinAVR и printf. В поисковике ввожу эту проблему и все ссылки на твои посты с 2008 по нынешний год. И на кошачьем форуме ты тоже помогаешь людям с WinAVR.
У меня вопрос, почему то, если заканчивать строку printf("\nI like WinAVR!\n"); на \n то выходной файл весит около 400байт, а если убрать /n, то 1,3килобайта. Почему так? Обязательно в makefail настройка printf должна стоять normal, если поставить mini то файл выходной с /n будет весить примерно 1.3 килобайта. Или если например выводить число printf("/n%d",1 23); то тоже файл весит 1.3килобайта. Можно как нибуть выводить числа, и чтоб код выходного файла весил меньше килобайта?
#4 ARV 09.08.2012 01:17
честно говоря, я на счет размера кода не сильно заморачивался, и пока не могу сказать, почему на '\n' такая странная реакция...

что касается "экономного" вывода, то мне видится лишь один способ: использовать itoa и другие функции работы со строками для самостоятельной подготовки выводимого текста - так можно достичь заметного эффекта.
#5 ARV 29.05.2013 16:10
в первой строке примера после include исчезает avr/io.h из-за угловых скобок - имейте ввиду.

Добавить комментарий

Защитный код
Обновить

Обсудить эту статью на форуме (0 ответов).

Copyright 2019 © simple-devices.ru.
При использовании материалов ссылка на simple-devices.ru обязательна.