Top.Mail.Ru

Микроконтроллер AVR и GPIO. Порты ввода-вывода.

Долгое время мы оставляли без внимания микроконтроллеры AVR, и вот пришла пора исправить это недоразумение. Как и для других контроллеров, будем постепенно рассматривать различную периферию AVR’ок, сначала теорию, регистры, ну и под конец небольшие примеры.

В качестве IDE  я использую AVR Studio 5, шестую версию даже не пробовал, не так часто последнее время мне попадаются задачи для AVR. А вообще неплохо иметь еще и установленную AVR Studio 4, потому что порой случается так, что запрограммировать контроллер из AVR Studio 5 не представляется возможным. Вот совсем недавно я хотел прошить ATMega2560 при помощи программатора STK500 и это оказалось неосуществимо через 5-ую студию... Хорошо осталась со старых времен 4-ая, и проблема решилась в течение пары минут.

Что тут еще можно сказать?... Да в принципе, это все, можно переходить к делу!

Начинать, естественно, будем с GPIO – портов ввода-вывода, потому как без них никуда. И прежде чем описывать регистры, которые управляют работой портов, отмечу несколько "электрических" моментов.

На входе каждой ножки микроконтроллера заботливые разработчики поставили пару диодов, которые должны спасти микроконтроллер в случае превышения допустимого напряжения. НО! На деле все не столь радужно, и если подать на вход микроконтроллера, например, 7.5 В, то контроллеру уже никто и ничто не поможет, проверено на собственном опыте. Поэтому все эксперименты нужно проводить аккуратно.

Теперь к регистрам. Вся работа с портами ввода-вывода в AVR’ках сосредоточена в трех регистрах – DDRx, PORTx, PINx. Символ "x" заменяется соответствующим названием порта (A, B…). То есть, если мы хотим работать с портом A микроконтроллера, то нам нужны регистры DDRA, PORTA, PINA. Если мы хотим работать с пятым пином порта А (РА5), то нас интересует пятый бит упомянутых выше регистров. Как видите, все довольно просто, осталось лишь разобраться, что же и куда надо записывать, и за что отвечает каждый из этих регистров. Итак, начинаем...

Регистр DDRx.

DDRx отвечает за направление работы соответствующих выводов микроконтроллера. Каждый пин может быть либо входом, либо выходом, третьего не дано. Для того, чтобы настроить вывод на работу в режиме входа в регистр DDR для этого порта нужно записать 0, для выхода – 1. Пусть нам нужно настроить РА6 как вход, а РА3 как выход. Что делаем? Верно, 3-й бит регистра DDRA выставляем в 1, а в 6-й бит все того же регистра DDRA записываем 0.

Регистр PINx.

В этот регистр мы записать ничего не можем, он предназначен исключительно для чтения данных. В этом регистре информация об уровне сигнала на соответствующем входу. Как мы помним, микроконтроллер – это цифровое устройство, и сигналы на его ножках могут иметь либо высокий уровень (логическая 1), либо низкий (логический 0). Если мы хотим узнать, что у нас там на входе РВ4, то нас интересует 4-й бит регистра PINB.

Регистр  PORTx.

С этим регистром чуть посложнее, чем с предыдущими. Его функциональность зависит от того, в какой направлении работают выводы микроконтроллера. Если вывод используется в качестве входа, то регистр PORTx задает тип входа. Тут возможно два варианта:

  • PORTx = 1 – при такой конфигурации мы получаем вход с подтяжкой вверх (Pull Up)
  • PORTX = 0 – высокоимпедансный вход (Hi-Z).

Итак, продолжаем с регистром PORTx. Если вывод работает в качестве выхода, а в регистре PORTx единица, то на выводе будет высокий уровень сигнала, аналогично, PORTx = 0 – низкий уровень.

Давайте рассмотрим небольшой пример для иллюстрации всего сказанного. Пусть требуется настроить вывод РС4 на работу в режиме входа с подтяжкой вверх. Для этого нам надо:

  • в 4-й бит регистра DDRC записать 0 (режим входа)
  • в регистре PORTC 4-й бит выставить в 1 (подтяжка вверх).

В принципе это все, что касается теории, углубляться дальше не будем. Осталось соблюсти традиции и поиграть с диодом. Пусть диод подключен к выводу PВ5. Заставим его помигать, и прежде всего создадим проект. Я, как уже говорил, использую AVR Studio 5, а в качестве контроллера выберу мой любимый ATMega88 )

/***************************************************************************************/
#include<avr/io.h>


/***************************************************************************************/
// Простенькая функция для формирования задержки
void delay(unsigned int time)
{
	unsigned int i = 0;
	for (i = 0; i < time; i++);
}


/***************************************************************************************/
// Инициализация нашего вывода, он работает на выход
void initAll()
{
	DDRB = 0b00100000;
}


/***************************************************************************************/
// Собственно тело функции main()
int main(void)
{
	initAll();
	
	while(1)
	{
		// Зажигаем диод
		PORTB = 0b00100000;
		
		// Отдыхаем
		delay(50000);
		
		// Гасим диод
		PORTB = 0b00000000;
		
		delay(50000);
	}
}


/***************************************************************************************/

И на этом на сегодня заканчиваем, до скорого 🤝

Подписаться
Уведомить о
guest

3 комментариев
Старые
Новые
Межтекстовые Отзывы
Посмотреть все комментарии
Ярослав
Ярослав
10 лет назад

Эдравсвуйте!
В чем суть использования древних авр? Ведь стм и дешевле и навороченее ну и тем более быстрее.

Эндрю
Ответ на комментарий  Ярослав
2 лет назад

ИМХО, AVR для своих целей, задач определённого уровня, есть фюзы.
STM более универсален, но более сложен.

3
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x