Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Примеры решения лабораторных работ / Программирование 8535 на СИ

.pdf
Скачиваний:
53
Добавлен:
26.01.2023
Размер:
2.19 Mб
Скачать

{

 

 

 

case 0:

 

 

 

PORTC=c1;

//

код "1"

 

PORTD=0x01;

//

индикатор

HG1

break;

 

 

 

case 1:

 

 

 

PORTC=c2;

//

код "2"

 

PORTD=0x02;

//

индикатор

HG2

break;

 

 

 

case 2:

 

 

 

PORTC=c3;

//

код "3"

 

PORTD=0x0 4;

//

индикатор

HG3

}

 

 

 

n++;

//

смена номера индикатора

n%=3;

 

 

 

}

 

 

 

// ---------------

главная

функция ---------------------

 

void main(void)

 

 

 

{

 

 

 

DDRC =0xFF; // все биты порта C - на выход PORTC=0x00; // сегменты не светятся

DDRD =0x0 7; // младшие три бита порта D - на выход PORTD=0x0 0; // индикаторы не выбраны

TIMSK=0x01; // разрешение прерывания по переполнению таймера 0

SEI(); // общее разрешение прерываний - установка бита 7 регистра SREG TCCR0=0x04; // =0000 0100, коэффициент предделителя 256,

//частота прерываний будет 8000000/256/256=122 Гц,

//частота обновления числа (3 цифры): 122/3=40 Гц

for (;;)

;

}

// ---------------------------------------------------------------

Задание на выполнение

1.Наберите программу «Пример 1». Определите, при каких минимальных значениях макроопределения NUM начинается мерцание символов? Почему это происходит?

2.Наберите программу «Пример 2». Определите, при каких минимальных

значениях

коэффициента

предделителя

таймера

Т0

начинается

мерцание

символов?

 

 

 

 

 

 

 

 

3.

Измените программу «Пример 2» таким образом, чтобы высвечивались:

а) год рождения;

 

 

 

 

 

 

 

б) месяц рождения;

 

 

 

 

 

 

 

в) день рождения;

 

 

 

 

 

 

 

г) дата рождения (день вместе с символом «точка» и месяц, например, 11.09)

 

д) возраст

 

 

 

 

 

 

 

е)

входным сигналом

PA0

изменяется

индикация:

либо

год рождения, либо

дата рождения.

 

 

 

 

 

 

 

4.

Напишите программу,

которая выводит на

первый

индикатор

десятичную

цифру от 0 до 9. Код цифры, которая выводится на индикатор, вводится в двоичной форме в порт A: PA0.PA3.

5.

Напишите

программу,

которая

выводит

на

первый

индикатор

шестнадцатеричную цифру от 0 до F. Код цифры, которая выводится на индикатор,

вводится в двоичной форме в порт А: PA0.PA3.

 

 

 

 

6.

Выведите

на экран динамическую

индикацию

двух

шестнадцатеричных

чисел, набранных по 2 полубайтам порта А:

младшая цифра числа набирается на

входах PA0...PA3, старшая - на PA4...PA7.

 

 

 

 

 

7.Напишите программу для вывода с интервалом 0,5 секунды на

семисегментный индикатор чисел от 0 до 200. Паузу реализуйте программным путем. Для смены выводимых символов используйте прерывания таймера 2. Для вычисления кодов, соответствующих числу (от 0 до 9-ти включительно), напишите функцию.

8. Составьте программу, которая выводит на семисегментные индикаторы десятичный эквивалент двоичного восьмиразрядного кода.

Работа №4. Внешние прерывания микроконтроллера AVR

Цель работы

Познакомиться

с

организацией

внешних

инициативных

сигналов

микроконтроллера

ATmega8535. Составить и отладить программы

работы с

наружными сигналами.

 

 

 

 

 

 

Пояснения к работе

 

 

Очень часто

возникает

задача обработки данных

при возникновении какого-

либо внешнего события. Так, например, для расчета периода (или частоты) гармонического сигнала необходимо знать, в какой момент времени этот сигнал изменяет свой знак - отрицательный на положительный или наоборот. Уловив этот момент, микроконтроллер запускает подпрограмму расчета периода входного сигнала. Для создания таких алгоритмов в программах используются внешние

прерывания.

 

 

 

 

 

В

общем

случае

прерывание прекращает нормальный ход выполнения

программы

для

решения

приоритетной задачи, определяемой внутренним или

внешним

событием

микроконтроллера.

При

возникновении

прерывания

микроконтроллер

сохраняет

в стеке содержимое

счетчика команд PC и

загружает в

него адрес соответствующего вектора прерывания. По этому адресу, как

правило,

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

Последней командой подпрограммы обработки прерывания должна быть

команда

ассемблера RETI, которая обеспечивает возврат в основную

программу и

восстановление

предварительно

сохраненного

счетчика команд.

Таким

образом,

после

выполнения

подпрограммы

обработки

прерывания

микроконтроллер

возвращается на то место программы, где ее прервали.

 

 

 

 

Поскольку

источниками

прерываний,

в

частности, являются

различные

периферийные устройства микроконтроллера, количество прерываний зависит от конкретной модели микроконтроллера.

 

Прерывания микроконтроллера AVR. Таблица векторов прерываний

 

Как и все

микроконтроллеры

AVR,

микроконтроллеры

семейства

Mega

имеют

многоуровневую систему приоритетных прерываний.

Младшие

адреса

памяти

программ,

начиная с адреса

$0000,

отведены под

таблицу векторов

прерывания. Каждому прерыванию соответствует адрес в этой таблице, который

загружается

в счетчик

команд

при

возникновении

прерывания.

Положение

вектора

в таблице

также определяет

и

приоритет

соответствующего

прерывания:

чем

меньше

адрес,

тем

выше приоритет прерывания. Размер вектора

прерывания

зависит от объема памяти программ микроконтроллера и составляет 1

слово

для

моделей

контроллеров

AVR.

Соответственно

для

перехода

к

подпрограммам

обработки

 

прерываний

используются

команды

ассемблера

RJMP.

Для

разрешения

всех аппаратных

прерываний устанавливается в

«1»

флаг

I (бит

7)

регистра

SREG

(приложение 2), для запрещения этот флаг устанавливается в «0». Практически во

 

 

 

всех

микроконтроллерах

 

семейства

 

Mega

положение

таблицы

 

векторов

прерываний может

быть

 

изменено.

Таблица

может

располагаться не

только в

начале

памяти

программ,

а также и в начале области загрузчика.

 

Причем

перемещение

таблицы

может

быть

осуществлено

непосредственно

 

в

ходе

выполнения программы.

 

 

 

 

 

 

 

 

 

 

 

 

Управление

размещением

таблицы

прерываний

осуществляется

 

двумя

младшими разрядами регистра GICR (см. прил. 4): IVSEL (1-й разряд) и IVCE (0-й

разряд).

Состояние

флага

IVSEL

определяет

положение

таблицы

в

 

памяти

программ. Если флаг сброшен в «0», таблица векторов прерываний располагается в начале памяти программ, если флаг установлен в «1» — в начале области загрузчика. Конкретное значение начального адреса области загрузчика зависит от установок конфигурационных ячеек B00TSZ1 и B00TSZ0.

 

Разряд

IVCE

предназначен

 

для разрешения изменения флага IVSEL. Для

изменения

положения

таблицы

 

векторов

прерываний

необходимо

установить

разряд

IVCE

в

«1»

 

и затем

в

течение следующих четырех машинных циклов

занести требуемое значение в разряд IVSEL. При

этом разряд

IVCE

сбрасывается

в

«0». В противном случае разряд

IVCE будет сброшен аппаратно по истечении

четырех машинных циклов, запрещая

дальнейшее

изменение

флага

IVSEL.

На

время

выполнения

 

описанной

 

последовательности

прерывания

 

автоматически

запрещаются

и

разрешаются только

после

сброса

флага

IVCE.

Состояние

флага

I

регистра SREG при этом не меняется.

 

 

 

 

 

 

 

 

 

 

 

 

 

Размер таблицы векторов прерываний зависит от модели микроконтроллера.

Распределение

адресов

векторов

прерываний

контроллера

ATMega 8535

приведено

в приложении

3,

и

частично в

табл.

1.

При размещении векторов

прерываний

в

области загрузчика к значениям, указанным в таблице, следует прибавить значение начального адреса области загрузчика.

Табл. 1. Таблица векторов прерываний ATmega8535

№ вектора

Источник

Описание

Aдpec (слово)

 

 

 

прерывания

 

 

 

1

RESET

Сброс микроконтроллера

$0000

2

INT0

Внешнее прерывание 0

$0001

3

INT1

Внешнее прерывание 1

$0002

 

 

 

 

19

INT2

Внешнее прерывание 2

$0012

При возникновении прерывания флаг I регистра SREG аппаратно сбрасывается, запрещая, тем самым, обработку следующих прерываний. Однако в подпрограмме обработки прерывания этот флаг можно снова установить в «1» для разрешения вложенных прерываний. При возврате из подпрограммы обработки прерывания (команда ассемблера RETI) флаг I устанавливается аппаратно. Следует

помнить, что при вызове подпрограмм

обработки

прерываний регистр состояния

SREG не сохраняется. Поэтому пользователь должен самостоятельно запоминать

содержимое этого

регистра при входе

в

подпрограмму обработки прерывания (если

это необходимо)

и восстанавливать

его

значение

перед вызовом команды RETI

(выходом из прерывания).

При написании программ на языке Си

компилятор

автоматически

выполняет

данное действие, однако при написании

программ

на ассемблере

следует

внимательно относиться к данному пункту.

 

 

 

Внешние прерывания микроконтроллера ATmega8535

Из табл. 1 видно, что контроллер содержит три вектора внешних прерываний (соответственно входы INT0, INT1, INT2). Подача внешних сигналов на выводы микроконтроллера выполняется в соответствии с табл. 2.

Табл. 2. Выводы внешних прерываний микроконтроллера

Наименование внешнего прерывания

Вывод микроконтроллера

INT0

PD2

INT1

PD3

 

 

INT2

PB2

 

 

При этом надо помнить, что при использовании

внешнего

прерывания

необходимо

определить

соответствующий

вывод

 

микроконтроллера

на

 

ввод

сигнала.

 

Например,

для

применения

внешнего

прерывания

INT1

при

инициализации портов необходимо записать:

 

 

 

 

 

 

 

 

PORTD = 0x08;

 

//

бит

PD3(INT1) с подтягивающим резистором

 

 

 

DDRD = 0x00;

 

//

все

биты порта D на ввод (реально необходимо

 

 

 

 

 

 

// определить на ввод только 3 бит регистра DDRD)

 

 

 

Для того, чтобы использовать в программе внешние прерывания необходимо:

 

 

а) разрешить внешние прерывания (биты регистра GICR);

 

 

 

 

 

б)

определить, на

какие

уровни

или

фронты

входных

сигналов будет

реакция

в программе, т.е. определить условие генерации прерываний (регистры MCUCR и

MCUCSR);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

в) написать подпрограммы обработки прерываний.

 

 

 

 

 

 

 

Разрешение

обработки

внешних

прерываний

определяется

состоянием

трех

старших

битов регистра

GICR

(табл. 3). Если в соответствующем

разряде

регистра

GICR

записана

логическая

1,

то

соответствующее

внешнее

прерывание

разрешается.

Табл. 3. Разряды регистра GICR - разрешение внешних прерываний

Бит

Наименование бита

Описание

7

INT1

Разрешение внешнего прерывания INT1

6

INT0

Разрешение внешнего прерывания INT0

5

INT2

Разрешение внешнего прерывания INT2

 

 

 

Например, записав в 7 разряд GICR логическую «1», разрешается работа

внешнего прерывания INT1:

GICR = 0x80; //1000 0000 - разрешение обработки прерывания INT1

Условие генерации прерывания определяется содержимым разрядов регистра MCUCR и MCUCSR. В табл. 4 приведено назначение битов регистра MCUCR для определения условий генерации прерываний от INT0 и INT1, а в табл. 5 -

 

назначение 6 бита регистра MCUCSR для

прерывания INT2.

Например, для

 

генерации прерывания INT1 по спадающему

(отрицательному) фронту входного

 

сигнала значения 3 и 2 разрядов ISC11 и ISC10 регистра MCUCR устанавливаются

 

соответственно в состояния «1» и «0»:

 

 

 

 

 

 

 

 

MCUCR = 0x08;

// 0000 1000 - генерация прерывания INT0 по

 

 

 

 

 

 

// спадающему фронту входного сигнала на PD3

 

Табл. 4. Назначение младших битов регистра MCUCR

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Бит

Наименова

 

Назначение

 

 

 

Описание условий генерации прерываний

 

 

 

 

 

 

 

 

 

 

 

 

ние бита

 

битов

 

 

 

 

 

 

 

 

 

 

 

 

 

ISC11

ISC10

 

 

 

 

 

 

 

 

Условие

 

 

 

 

 

 

 

 

 

 

 

 

 

0

 

0

 

по низкому уровню на INT1

 

 

 

ISC11,

 

 

 

 

 

 

 

 

 

генерации

 

 

 

 

 

 

3,2

 

 

0

 

1

 

по любому изменению уровня INT1

 

 

ISC10

 

прерывания

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

INT1

 

1

 

0

 

по спадающему фронту INT1

 

 

 

 

 

 

 

1

 

1

 

по нарастающему фронту INT1

 

 

 

 

 

Условие

ISC01

ISC00

 

 

 

 

 

ISC01,

 

 

0

 

0

 

по низкому уровню на INT0

 

 

 

 

генерации

 

 

 

 

 

1,0

 

 

0

 

1

 

по любому изменению уровня INT0

 

 

ISC00

 

прерывания

 

 

 

 

 

 

 

 

1

 

0

 

по спадающему фронту INT0

 

 

 

 

 

INT0

 

 

 

 

 

 

 

 

 

1

 

1

 

по нарастающему фронту INT0

 

 

 

 

 

 

 

 

 

Табл. 5. Назначение 6 бита регистра MCUCSR

 

 

 

 

 

 

 

 

 

 

 

 

Бит

Наименова

 

Назначение битов

 

Описание условий генерации прерываний

 

 

 

 

 

 

 

 

 

 

 

 

 

ние бита

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ISC2

 

 

 

6

 

ISC2

 

Условие генерации

 

 

 

 

 

 

 

 

 

0

 

по спадающему фронту INT2

 

 

 

прерывания INT2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

по нарастающему фронту INT2

 

 

 

 

 

 

 

 

 

 

 

 

Для

создания подпрограмм

обработки

внешних прерываний

используются

так называемые флаги прерываний. Исходное значение флага нулевое. В момент возникновения соответствующего события флаг устанавливается в единичное состояние. После обработки прерывания значения флага автоматически или принудительно устанавливается в состояния «0».

Флаги внешних прерываний контроллера размещаются в регистре GIFR и приведены в табл. 6.

Табл. 6. Разряды регистров GIFR

Бит

Наименование бита

Описание

7

INTF1

Флаг внешнего прерывания INT1

6

INTF0

Флаг внешнего прерывания INT0

5

INTF2

Флаг внешнего прерывания INT2

 

 

 

Так, например, если в результате события на входе сформировался запрос на

внешнее

прерывание

INT1,

то

7

разряд

регистра

GIFR

(бит

INTF1)

устанавливается в «1». Флаг INTF1 сбрасывается аппаратно

при

запуске

подпрограммы обработки

прерывания

или

программно, записью в

него логической

«1». Флаг INTF1 сброшен постоянно, если генерация прерывания должна

 

 

port_init(void)

происходить по НИЗКОМУ уровню на выводе INT1. Эти флаги чаще всего используются при программировании на ассемблере.

Впрограммах на языке Си обработчик прерывания записывается иначе: в

программе

обычно

используются

директива

#pragma

и

функция

с

соответствующим названием.

Так, например, для обработки

внешнего

прерывания

INT1 подпрограмма обработки записывается в такой форме:

 

 

 

 

#pragma interrupt_handler int1_isr:3 // обработчик прерывания

 

 

// INT1 (вектор прерывания - 3)

 

 

 

 

 

 

void int0_isr(void)

 

 

 

// имя функции обработки прерывания

 

{

 

 

 

 

 

 

 

 

 

 

 

...

 

 

 

 

 

//тело функции

 

 

 

}

 

 

 

 

 

 

 

 

 

 

 

Пример

1.

Рассмотрим

программу

с применением

внешнего

прерывания

INT0,

которая

включает

и

выключает каждую секунду светодиод, подключенный

к

выходу

PB0.

При

этом

для расчета промежутка времени используется выход

генератора 50 Гц (сетевая

синхронизация),

подаваемый на

вход микроконтроллера

PD2 (вход внешнего прерывания INT0). Пусть генерация прерывания возникает по

 

нарастающему фронту.

 

 

 

 

 

 

 

 

 

// ---------------------------------------------------------------

 

 

 

 

 

 

 

 

 

 

 

 

#include <iom8535v.h>

 

 

 

 

 

 

 

 

 

#include <macros.h>

 

 

 

 

 

 

 

 

 

 

unsigned char count=0;

 

 

//

count - счетчик прерываний

 

 

 

unsigned char priz_on=0; // priz_on - признак включенного светодиода

void

{

PORTB = 0x00; // записываем 0 в бит PB0 DDRB = 0x01; // бит PB0 на выход

PORTD = 0x04; // ставим бит PD2(INT0) на вход со включенным

DDRD = 0x0 0; // подтягивающим резистором

}

// подпрограмма обработки прерываний от входа INT0 с вектором 2

#pragma interrupt_handler int0_isr:2 void int0_isr(void)

{

count++;

if (count==50)

 

//

прошла секунда

{

 

 

 

 

count=0;

 

//

сбрасываем

значение счетчика

priz_on=!priz_on;

//

и обращаем

состояние светодиода

if (priz_on) PORTB|=1;

 

 

else

PORTB&=0xFE;

 

 

}

 

 

 

 

}

 

 

 

 

void init_devices(void)

 

 

 

{

 

 

 

 

CLI ();

 

 

 

 

port_init();

 

 

 

 

MCUCR = 0x03;

//

0000 0011 -условие возникновения прерывания INT0 -по

// нарастающему фронту

GICR = 0x40; // 0100 0000 -разрешаем прерывания по входу INT0 TIMSK = 0x00; // источники прерываний таймеров отсутствуют

SEI () ;

}

void main (void)

{

init_devices();

//

инициализация периферийных устройств

for (;;) ;

//

бесконечный цикл

}

 

 

// ---------------------------------------------------------------

 

 

 

 

Задание на выполнение

1.Наберите программу по примеру 1 и проверьте, как она работает.

2.Измените программу примера 1 следующим образом:

а) используется внешнее прерывание INT1 по ниспадающему фронту;

б) используется внешнее прерывание INT2 по ниспадающему фронту. Продолжительность включения светодиода 0,5 с;

в) используется внешнее прерывание INT0 по любому изменению уровня. Продолжительность включения светодиода должна остаться исходной - 1 с.

3. Используя внешнее прерывание INT1 и таймер T0, напишите программу расчета периода сети и вывода его в двоичном коде (в миллисекундах) в порт С.

Примерный алгоритм вычисления может быть

следующим.

На

вывод INT1

подается

сигнал с

генератора

50 Гц. При появлении нарастающего фронта этого

сигнала

программа

начинает

считать импульсы

с таймера

Т0,

работающего с

частотой 1 кГц (период прохождения импульсов 1 мс). Счет заканчивается при возникновении нового прерывания INT1, после чего результат выдается в порт С. Для того, чтобы информация на выходе не слишком часто менялась, желательно обновлять информацию не 50 раз за секунду, а несколько реже, например, 1 раз в секунду.

4.Выполните аналогичную задачу с выводом информации на 7-сегментный

индикатор, при этом используйте динамическую индикацию. Подумайте, как увеличить точность измерения периода.

5.Напишите программу определения частоты сети с точностью не хуже 1 Гц.

Результат выводить на 7-ми сегментный индикатор с шагом по времени 1 секунда. Время между сетевыми импульсами измерять с помощью таймера.

Работа №5. Программирование шестнадцатиразрядного таймера Т1 микроконтроллера

Цель работы

Познакомиться с работой 16-разрядного таймера микроконтроллера ATmega8535. Составить и отладить программу работы с таймером.

Пояснения к работе

Модуль 16-разрядного таймера Т1 входит в состав модели микроконтроллера ATmega8535. Таймер/счетчик Т1 может использоваться для отсчета временных интервалов и как счетчик внешних событий. Кроме того, он может выполнять запоминание своего состояния по внешнему сигналу. Он может работать также в качестве широтно-импульсного модулятора переменной разрядности и к тому же многоканального. Структурная схема таймера Т1 приведена на рис. 1.

Рис. 1. Структурная схема таймера Т1

 

Входы/выходы таймера Т1

 

 

 

Каждый

таймер/счетчик

использует

один

или

более

выводов

микроконтроллера. Как правило, эти выводы - линии портов ввода/вывода

общего

назначения, а функции, реализуемые этими

выводами при работе совместно с

таймерами/счетчиками,

являются

их

альтернативными

функциями.

Для

микроконтроллера Atmega 8535 такими выводами являются:

-PB1 (T1) - вход внешнего сигнала таймера Т1;

-PD6 (ICP) - вход захвата таймера Т1;

-PD4 (0C1B), PD5 (0C1A) - выходы схем сравнения A и B таймера Т1. При использовании альтернативных функций портов ввода/вывода

необходимо, как правило,

самостоятельно сконфигурировать эти выводы в

соответствии с их функциональным назначением - на вход или выход.

 

 

Предделитель таймера

 

В качестве источника

тактовых импульсов таймера Т1

могут использоваться

как внешние импульсы (со входа

T1), так и сигнал с выхода

тактового генератора.

Эти сигналы поступают на

вход

предделителя, формирующего тактовые сигналы

таймера Т1. Структурная схема предделителя таймера Т1 показана на рис. 2.

Рис. 2. Структурная схема предделителя таймера/счетчика Т1

Для управления состоянием предделителя используется регистр специальных функций SFIOR (в данной лабораторной работе не используется).

Регистры таймера Т1

В состав таймера/счетчика Т1 входят следующие регистры ввода/вывода:

-16-разрядный счетный регистр TCNT1;

-16-разрядный регистр захвата ICR1;

Соседние файлы в папке Примеры решения лабораторных работ