Для реализации выберем модуль входной. Представим его в графическом виде при помощи блок-схемы алгоритма.
Sym<0x20 |
Sym=0x0C |
Очистка дисплея |
DispPos=0 |
Sym=0x0D |
DispPos &= 0x10 |
WriteComm((DispPos<<2)|0x80) |
Вход |
Sym >0x7F |
Sym = Table[Sym & 0x7F] |
WaitReady() |
WriteDataAddr = Sym |
DispPos++ |
DispPos &= 0xF |
Выход |
Для реализации выберем модуль ВХОДНОЙ. Представим его в графическом виде при помощи блок-схема алгоритма.
При входе в процедуру осуществляется проверка символа, если он является служебным то происходят следующие действия, очистка дисплея, обнуление позиции курсора. После этого выполняется возврат коретки, обнуление позиции в строке и установка курсора в начало строки. Если символ я является буквой или цифрой то вначале он согласно своему коду в таблице символов выбирается из нее, после этого происходит ожидание готовности и как только индикатор будет готов, он выведет символ на экран и сместит курсор на необходимую позицию. Приведём представление архитектуры ПО контроллера инкубатора в виде графа состояний системы.
Руководство программиста
Программа управления домофоном, написанная на языке С. Программа содержит следующие процедуры: процедура MAIN которая описана ниже, процедуру инициализации – INIT(), процедуру ожидания готовности индикатора – WaitReady(), процедуру записи команды – WriteComm(), процедуру вывода символов на экран – WriteData(). В программе также используется охранный таймер, сброс которого осуществляется библиотечной процедурой _WDR() в теле основной программы.
Пояснения к программе приведены в самом листинге.
#include <io2313.h> //файл описания регистров АТ90S2313
#include <ina90.h> //файл процедур семейства АТ90Sxxxx
#define DispBASE 0x010000/* 1 - указание компилятору на расположение индикатора во внешней
памяти данных, DispBASE его базовый адрес =0000 */
#define ReadStateAddr (*(char *) (DispBASE+0x800)) /*адрес регистра состояния=0200h*/
#define WriteCommAddr (*(char *) (DispBASE+0x000)) /* адрес регистра команд =0000h*/
#define ReadDataAddr (*(char *) (DispBASE+0xC00)) /* адрес регистра данных по чтению =0300h*/
#define WriteDataAddr (*(char *) (DispBASE+0x400))/* адрес регистра данных по записи =0100h*/
char DispPos; /* переменная - текущая позиция маркера*/
/*********************************************************************************/
void main(void)
{
INIT(); //инициализация контроллера
_SEI(); // Общее разрешение прерываний
// Бесконечный цикл
while (1)
{
_WDR(); // Сброс охранного таймера
}
}
/*********************************************************************************/
void INIT(void) // инициализация контроллера
{
TCCR1A = 0x00;
TCCR1B = 0x14;
TIMSK |= Bit(MskTIE1); // Таймер 1 - разрешение прерываний
GIMSK |= Bit(MskInt0); // INT0 - разрешение прерывания
WDTCR = 0x0F; // Настройка WATCHDOG
// Настройка портов
DDRА = 0xFF; //11111111 – РА0...РА7-на выход – данные на ЖКИ
PORTD = 0x00; //все на вход и в третье состояние
}
/****************************************************************************/
/* Ожидание готовности дисплея */
void WaitReady(void)
{
while (ReadStateAddr & 0x80); /* Ожидать сброса бита занятости */
}
/****************************************************************************/
/* Запись команды в дисплей */
void WriteComm(char Cmd)
{
WaitReady();
WriteCommAddr = Cmd; /* Запись команды */
}
/*Таблица кодировки выводимых символов из таблицы */
code const char Table[128] = (0x41,0xA0,0x42,0xA1,0xE0,0x45,0xA3,0xA4, 0xA5,0xA6,0x4B,0xA7,0x4D,0x48,0x4F,0xA8,
0x50,0x43,0x54,0xA9,0xAA,0x58,0xE1,0xAB, 0xAC,0xE2,0xAD,0xAE,0x62,0xAF,0xB0,0xB1,
0x61,0xB2,0xB3,0xB4,0xE3,0x65,0xB6,0xB7, 0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0x6F,0x6E,
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7, 0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7, 0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7, 0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
0x70,0x63,0xBF,0x79,0xE4,0x78,0xE5,0xC0, 0xC1,0xE6,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
0xA2,0xB5,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
0xEA,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF);
/****************************************************************************/
/* Вывод символов */
void WriteData(char Sym) /* Sym - выводимый символ в коде ASCII */
{
if (Sym < 0x20) /* Служебные символы */
{
switch (Sym)
{
case 0x0C: /* Очистка дисплея */
WriteComm(0x01); /* Команда очистки дисплея */
DispPos=0; /* Обнулить позицию курсора */
break;
case 0x0D: /* Возврат каретки */
DispPos &= 0x10; /* Обнулить позицию в строке */
WriteComm((DispPos<<2)|0x80); /* Установить курсор в начало строки */
break;
}
}
else /* Обычные символы */
{
if (Sym >0x7F) /* Вторая половина ASCII таблицы? */
Sym = Table[Sym & 0x7F]; /* Перекодировать через таблицу */
WaitReady(); /* Ожидать готовности */
WriteDataAddr = Sym; /* Вывести символ на экран */
DispPos++; DispPos &= 0xF; /* Коррекция положения курсора – диапазон его
значений 0…15, т.е. переход из 15 позиции в 0*/
}
else /* Цифры */
{
if (Sym >0x30 && Dat <0x39) /* Код символа входит в диапазон? */
WaitReady(); /* Ожидать готовности */
WriteDataAddr = Sym; /* Вывести символ на экран */
DispPos++; DispPos &= 0xF; /* Коррекция положения курсора – диапазон
его значений 0…15, т.е. переход из 15 позиции в 0 */
}
}
Заключение
Проработав соответствующий материал и применив полученные знания по дисциплине МПС было спроектировано устройство домофон и соответствующее программное обеспечение для него.
Литература
1. Мясников В.И. Микропроцессорные системы. Учебное пособие по курсовому проектированию.- Йошкар-Ола: МарГТУ, 2003.
2. Предко М. Руководство по микроконтроллерам. В 2-х томах. – М.: Постмаркет, 2001.
3. Евстифеев А.В. Микроконтроллеры AVR семейства Classic фирмы “ATMEL”. М.: “Додэка–XXI” 2002.