
отчеты по лабораторным работам / дискретные порта ввода-вывода / lab2
.docx
Лабораторная работа № 2
“Дискретные порты ввода-вывода”
Вариант № 2
Работу выполнил
Студент гр. 3100
Голубцов Евгений
2010
Задание
Разработать и реализовать драйверы светодиодного индикатора и DIP-переключателя контроллера SDK-1.1. Написать тестовую программу с использованием разработанных драйверов по алгоритму, соответствующему варианту задания.
Описание работы
Данная лабораторная работа посвящена изучению дискретных портов ввода-вывода встраиваемых микроконтроллеров. Дискретные (цифровые) порты используются для ввода-вывода дискретных значений логического «0» или «1». Исследование портов будет проводиться на примере светодиодного индикатора (линейки из 8 светодиодов) и DIP-переключателя, входящих в состав контроллера SDK-1.1.
Ниже на рисунке показано расположение линейки светодиодов и DIP-переключателя в стенде SDK-1.1.
Для удобства, двоичный (шестнадцатеричный) код, задаваемый DIP-переключателем, выставляется следующим образом: первый переключатель соответствует младшему (0-му) разряду двоичного кода; восьмой переключатель соответствует старшему (7-му) разряду. Переключатель, установленный в положение «ON», следует считать единичным разрядом, а в противоположное положение – нулевым.
Требования к выполнению работы
Все программы должны быть написаны на языке Си. Разрабатываемые драйверы устройств должны быть выполнены в виде отдельных функций (функции установки состояния светодиодов и функции чтения состояния DIP-переключателя). В тестовой программе для осуществления анимации запрещается использовать «покадровое» формирование картинки. Для реализации алгоритма анимации должны быть использованы логические, арифметические и бинарные операции, а также операции сдвигов.
Для задержек в программе следует использовать пустые циклы (тысячи – десятки тысяч итераций, в зависимости от длительности задержки).
В варианте задания представлен лишь фрагмент анимации, при этом все анимации являются циклическими. По приведенному фрагменту требуется определить алгоритм анимации и реализовать его.
Вариант № 2
В случае установки на DIP-переключателе кода 0x22 (шестнадцатеричное значение) на светодиодный индикатор должна выводиться первая анимация, в случае установки кода 0xDD (шестнадцатеричное значение) – вторая анимация. Во всех остальных случаях светодиодный индикатор отражает инвертированное значение, выставленное на DIP-переключателе.
Блок-схема программы.
Текст программы с комментариями.
#include "aduc812.h" // Подключаем заголовочные файлы
#include "led.h"
#define MAXBASE 8; // Создаем символическое имя
// Задержка на заданное количество мс
void delay ( unsigned long ms )
{
unsigned long i, j;
for( j = 0; j < ms; j++ )
{
for( i = 0; i < 50; i++ );
}
}
//readDIP
//Чтение из нужного регистра ПЛИС ALTERA MAX3064(3128)
//
//Вход: regnum - адрес (номер) регистра
//Выход: val – прочитанное значение
//Результат: прочитанное из регистра значение
//Описание: Чтение из порта ПЛИС ALTERA MAX3064(3128)
// путем переключения адресуемой страницы памяти на страницу, где
// расположены (куда отображаются) порты ввода-вывода ПЛИС.
unsigned char readDIP()
{
unsigned char oldDPP = DPP;
unsigned char val = 0;
unsigned char xdata *regnum = 0x080002; // 0x080002 - адрес регистра данных параллельного порта (разряды 0..7)
DPP = MAXBASE; // Переключение страничного регистра DPP
val = *regnum ; // regnum - адрес регистра ПЛИС
DPP = oldDPP;
return ~val;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
//Функция вывода анимации, если на DIP-переключателях стоит значение 0х22 или 0хDD //
//или вывод инвертированного значения, выставленного на DIP-переключателях //
////////////////////////////////////////////////////////////////////////////////////////////////////
void AnimationFunc()
{
unsigned char u; // Переменная для хранения значений регистра DPP
unsigned char r1=0x22; // Адрес для первой анимации
unsigned char r2=0xdd; // Адрес для второй анимации
int i=0;
unsigned char leftPart=0x00; // Левая часть светодиодов
unsigned char rightPart=0x00; // Правая часть светодиодов
unsigned char state = leftPart | rightPart; // Делим светодиоды на левую и правую часть
if( (u = readDIP()) == r1) // Получение значения в регистре dpp и сравниваем с 0x22
{
leftPart=0x80; // Адрес первого светодиода в левой части
rightPart=0x08; // Адрес первого светодиода в правой части
for ( i = 0; i<10; i++ )
{
if (i<3)
{
state = leftPart | rightPart;
leds( state ); delay(500); // Устанавливаем положения для светодиодов и задержку
leftPart = leftPart >> 1; // Сдвигаем светодиод в левой части вправо на 1 разряд
rightPart = rightPart >> 1; // Сдвигаем светодиод в правой части вправо на 1 разряд
}
else
if (i<6)
{
state = leftPart | rightPart;
leds( state ); delay(500); // Устанавливаем положения для светодиодов и задержку
leftPart = leftPart << 1; // Сдвигаем светодиод в левой части влево на 1 разряд
rightPart = rightPart << 1; // Сдвигаем светодиод в левой части влево на 1 разряд
}
else
{
state = leftPart | rightPart;
leds( state ); delay(500);
leftPart = leftPart >> 1;
rightPart = rightPart >> 1;
}
}
}
else
{
if ( ( u = readDIP()) == r2) // Получение значения в регистре dpp и сравниваем с 0xdd
{
state=(0x01); // Устанавливаем положение светодиода в 0х01
for ( i = 0; i<10; i++ )
{
if (i<7)
{
leds( state ); delay(500);
state = state << 1; // Сдвигаем светодиод влево на 1 разряд
}
else
{
leds( state ); delay(500);
state = state >> 1; // Сдвигаем светодиод вправо на 1 разряд
}
}
}
else
{
leds( ~u ); // Если на DIP-переключателях другой адрес, получаем его инверсию и
delay(500); // выводим
}
}
}
void main( void )
{
while( 1 )
{
AnimationFunc(); // Вызов процедуры вывода анимации
}
}