Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Микропроцессоры(Коротицкий Евгений Викторович) / лабы_гр3480 / Основы языка Си для микроконтроллеров AVR.doc
Скачиваний:
1508
Добавлен:
18.04.2015
Размер:
797.7 Кб
Скачать
    1. Доступ к регистрам ввода/вывода

Каждому порту в микроконтроллере AVRсоответствуют минимум три регистра:

• DDRx— регистр направления данных (х — буква соответствующего порта, например:DDRB— регистр направления данных Порта В). Этот регистр определяет, как должен быть сконфигурирован вывод порта — как вход или как выход. Если в бит этого порта записать 1, то соответствующий вывод порта будет работать как выход; если записать 0, то соответствующий вывод порта будет работать как вход. Например, если в регистреDDRBзаписано число 01000011, то это значит, что 0-й, 1-й и 6-й выводы Порта В сконфигурированы как выходы, а остальные — как входы.

• PORTx— выходной регистр порта х (например,PORTB— выходной регистр Порта В). В биты этого регистра записывают те значения, которые хотят получить на выводах порта, при условии, что выводы сконфигурированы как выходы.

Если вывод сконфигурирован как вход, то при записи в соответствующий бит регистра PORTx1 этот вывод становится «входом с подтяжкой», т. е. этот вывод через резистор примерно 100... 150 кОм, находящийся внутри микроконтроллера, подключается («подтягивается») к напряжению питания микроконтроллера. Таким образом, при отсутствии сигнала на этом входе будет уровень логической 1.

• PINx— выводы порта х (например,PINB— выводы Порта В). Этот регистр содержит значения логических уровней, которые к настоящему времени присутствуют на физических (т. е. реальных) выводах порта. Этот регистр доступен ТОЛЬКО для чтения.

Для доступа к регистрам ввода/вывода микроконтроллера AVRс помощью инструкций ассемблераINиOUTкомпилятор использует ключевые словаsfrbиsfhv.

Пример:

/* Доступ к регистрам ввода/вывода */

/* Определим SFR (Регистры общего назначения) для чипа AT90S8515 */

sfrb PINC=0xl3; // Так как регистр PINA 8-битный, то к нему осуществляется

// 8-битный доступ с помощью sfrb (sfr byte)

// 0x13 — это адрес порта PINC sfrw TCNTl=0x2c;

// так как регистр TCNT1 16-битный, то к нему

// осуществляется 16-битный доступ с

// помощью sfrw (sfr word)

// 0x2с - это адрес регистра TCNT1

/* Основная функция программы */

void main(void) {

unsigned char x; // Объявляем символьную переменную x

x=PINC; // Чтение выводов Порта А

TCNTl=0xF4A6; // Запись в регистры TCNT1L & TCNT1H

}

Адреса регистров ввода/вывода определены в заголовочных файлах.

В начале программы посредством #include можно подключить соответствующий файл для того микроконтроллера, который используется в данном проекте.

      1. Побитовый доступ к регистрам ввода/вывода

Побитовый доступ к регистрам ввода/вывода осуществляется путем добавления выбранных битов после имени регистра.

Поскольку побитовый доступ к регистрам ввода/вывода осуществляется с использованием инструкций CBI,SBI,SBICиSBIS, адрес регистра должен быть в диапазоне 0...1Fhдляsfrbи в диапазоне 0...1Ehдляsfrw.

Пример:

/* Доступ к регистрам ввода/вывода */

/* Определим SFR (Регистры общего назначения) для чипа AT90S2313 */

sfrb PORTB=0xl8; // Объясняем компилятору, по каким адресам находятся

sfrb DDRB=0xl7; //те или иные регистры (порты). Так как все используемые

sfrb PINB=0xl6; // регистры 8-битные, то к ним осуществляется

// 8-битовый доступ с помощью sfrb. Обычно эти

// операторы располагаются в заголовочных файлах

// (см. Доступ к регистрам ввода/вывода)

int a, b, с; // Объявляем целые переменные а, b, с

/* Основная функция программы */

void main(void)

{

/* Зададим направление выводов Порта В */

DDRB.0=0 DDRB.1=0 DDRB.2=0 DDRB.3=0 // зададим биты 0...3 порта В как

// входы

DDRB.4=1 DDRB.5=1 DDRB.6=1 DDRB.7=1 // зададим биты 4...7 Порта В как

// выходы

/* Установим выводы Порта В */

PORTB.0=0; PORTB.1=0; // установим биты 0 и 1 Порта В как простые входы

PORTB.2=1; PORTB.3=1; // установим биты 2 и 3 Порта В как "входы с подтяжкой", т. е. каждый из этих выводов через резистор примерно 100...150 кОм будет соединён с шиной питания. Таким образом, в отсутствие сигнала на этих выводах будет уровень логической 1.

PORTB.4=0; PORTB.5=0; // установим биты 4 и 5 Порта В как выходы, на которых установлен уровень логического 0

P0RTB.6=1; P0RTB.7=1; // установим биты 6 и 7 Порта В как выходы, на которых установлен уровень логической 1

/* опросим выводы Порта В, т. е. их физические значения */

a=PINB.0; // Переменной а присвоим значение вывода 0 Порта В, т. е. значение сигнала, на выводе 0

b=PINB.5; // Переменной b присвоим значение вывода 5 Порта В, т. е. b=0

c=PINB.6; // Переменной с присвоим значение вывода 6 Порта В, т. е. с=1

if (PINB.2) { // Если на выводе 2 Порта В логическая 1,

[группа операторов 1] // то выполняется [группа операторов 1];

}

else

[группа операторов2] // если 0 - то [группа операторов2]

}

Чтобы улучшить удобочитаемость программы, битам в регистрах ввода/вывода можно присвоить символические имена посредством #define.

Пример:

/* Присвоение символических имен битам регистров ввода/вывода */

/* Эта примитивная программа зажигает светодиод по нажатию кнопки. Чип: AT90S2313. Светодиод подключён катодом к выводу 0 Порта В, а анодом через резистор 470 Ом — к плюсу источника питания. Кнопка одним выводом подключена к выводу 1 Порта В, а другим - к минусу источника питания (к "общему"). Частота кварца 1 МГц, хотя в данном случае она может быть любой */

#include <90s2313.h> // подключаем файл, где определены адреса регистров

/* Присвоение символических имен */

#define output_led PORTB.0 // Выход на светодиод

#define input_button PINB.1 // Вход кнопки

/* Основная функция программы */

void main(void)

{

/* Зададим направление выводов Порта В */

DDRB.0=1; // зададим бит 0 Порта В как выход

DDRB.1=0; // зададим бит 1 Порта В как вход

/* Установим выводы Порта В */

output_led =1; // используем символическое имя бита PORTB.0, запишем в него 1, чтобы установить вывод 0 Порта В как выход, на котором установлен уровень логической 1, чтобы светодиод не горел

P0RTB.1=1; // установим бит 1 Порта В как "вход с подтяжкой", чтобы при отжатой кнопке на этом выводе была 1, а при нажатии кнопки уровень менялся на 0

/* Бесконечный цикл */

while (1) // Оператор цикла

{

/* Тело цикла while */

if (input_button==0) // В условии используем символическое

// имя вывода PINB.1. Если кнопка нажата,

output_led=0; // т. е. на выводе PINB.1 логический 0, то зажигаем светодиод

else

output_led=l; // Иначе, если кнопка отжата,гасим светодиод

} // Скобка закрывает цикл while()

} // Скобка закрывает функцию main()

Важно отметить, что побитовый доступ для регистров ввода/вывода, расположенных во внутреннем SRAMвыше адреса 5Fh(например, Порт Е дляATmegal28), РАБОТАТЬ НЕ БУДЕТ, поскольку ассемблерные инструкцииCBI,SBI,SBICuSBISне могут быть использованы для доступа к SRAM.